blob: 681a582b5d70fbdb693290ce547ad646c0562289 [file] [log] [blame]
buzbee78f1bdc2017-03-01 10:55:57 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
buzbee78f1bdc2017-03-01 10:55:57 -080017#include "interpreter/interpreter_intrinsics.h"
18
David Sehr9e734c72018-01-04 17:56:19 -080019#include "dex/dex_instruction.h"
Orion Hodson26ef34c2017-11-01 13:32:41 +000020#include "intrinsics_enum.h"
Andreas Gamped9911ee2017-03-27 13:27:24 -070021#include "interpreter/interpreter_common.h"
22
buzbee78f1bdc2017-03-01 10:55:57 -080023namespace art {
24namespace interpreter {
25
buzbee31afbec2017-03-14 15:30:19 -070026
27#define BINARY_INTRINSIC(name, op, get1, get2, set) \
28static ALWAYS_INLINE bool name(ShadowFrame* shadow_frame, \
29 const Instruction* inst, \
30 uint16_t inst_data, \
31 JValue* result_register) \
32 REQUIRES_SHARED(Locks::mutator_lock_) { \
33 uint32_t arg[Instruction::kMaxVarArgRegs] = {}; \
34 inst->GetVarArgs(arg, inst_data); \
35 result_register->set(op(shadow_frame->get1, shadow_frame->get2)); \
36 return true; \
buzbee78f1bdc2017-03-01 10:55:57 -080037}
38
buzbee31afbec2017-03-14 15:30:19 -070039#define BINARY_II_INTRINSIC(name, op, set) \
40 BINARY_INTRINSIC(name, op, GetVReg(arg[0]), GetVReg(arg[1]), set)
41
42#define BINARY_JJ_INTRINSIC(name, op, set) \
43 BINARY_INTRINSIC(name, op, GetVRegLong(arg[0]), GetVRegLong(arg[2]), set)
44
45#define BINARY_JI_INTRINSIC(name, op, set) \
46 BINARY_INTRINSIC(name, op, GetVRegLong(arg[0]), GetVReg(arg[2]), set)
47
48#define UNARY_INTRINSIC(name, op, get, set) \
buzbee78f1bdc2017-03-01 10:55:57 -080049static ALWAYS_INLINE bool name(ShadowFrame* shadow_frame, \
50 const Instruction* inst, \
51 uint16_t inst_data, \
52 JValue* result_register) \
53 REQUIRES_SHARED(Locks::mutator_lock_) { \
54 uint32_t arg[Instruction::kMaxVarArgRegs] = {}; \
55 inst->GetVarArgs(arg, inst_data); \
56 result_register->set(op(shadow_frame->get(arg[0]))); \
57 return true; \
58}
59
buzbee31afbec2017-03-14 15:30:19 -070060
61// java.lang.Integer.reverse(I)I
62UNARY_INTRINSIC(MterpIntegerReverse, ReverseBits32, GetVReg, SetI);
63
64// java.lang.Integer.reverseBytes(I)I
65UNARY_INTRINSIC(MterpIntegerReverseBytes, BSWAP, GetVReg, SetI);
66
67// java.lang.Integer.bitCount(I)I
68UNARY_INTRINSIC(MterpIntegerBitCount, POPCOUNT, GetVReg, SetI);
69
70// java.lang.Integer.compare(II)I
71BINARY_II_INTRINSIC(MterpIntegerCompare, Compare, SetI);
72
73// java.lang.Integer.highestOneBit(I)I
74UNARY_INTRINSIC(MterpIntegerHighestOneBit, HighestOneBitValue, GetVReg, SetI);
75
76// java.lang.Integer.LowestOneBit(I)I
77UNARY_INTRINSIC(MterpIntegerLowestOneBit, LowestOneBitValue, GetVReg, SetI);
78
79// java.lang.Integer.numberOfLeadingZeros(I)I
80UNARY_INTRINSIC(MterpIntegerNumberOfLeadingZeros, JAVASTYLE_CLZ, GetVReg, SetI);
81
82// java.lang.Integer.numberOfTrailingZeros(I)I
83UNARY_INTRINSIC(MterpIntegerNumberOfTrailingZeros, JAVASTYLE_CTZ, GetVReg, SetI);
84
85// java.lang.Integer.rotateRight(II)I
86BINARY_II_INTRINSIC(MterpIntegerRotateRight, (Rot<int32_t, false>), SetI);
87
88// java.lang.Integer.rotateLeft(II)I
89BINARY_II_INTRINSIC(MterpIntegerRotateLeft, (Rot<int32_t, true>), SetI);
90
91// java.lang.Integer.signum(I)I
92UNARY_INTRINSIC(MterpIntegerSignum, Signum, GetVReg, SetI);
93
94// java.lang.Long.reverse(I)I
95UNARY_INTRINSIC(MterpLongReverse, ReverseBits64, GetVRegLong, SetJ);
96
97// java.lang.Long.reverseBytes(J)J
98UNARY_INTRINSIC(MterpLongReverseBytes, BSWAP, GetVRegLong, SetJ);
99
100// java.lang.Long.bitCount(J)I
101UNARY_INTRINSIC(MterpLongBitCount, POPCOUNT, GetVRegLong, SetI);
102
103// java.lang.Long.compare(JJ)I
104BINARY_JJ_INTRINSIC(MterpLongCompare, Compare, SetI);
105
106// java.lang.Long.highestOneBit(J)J
107UNARY_INTRINSIC(MterpLongHighestOneBit, HighestOneBitValue, GetVRegLong, SetJ);
108
109// java.lang.Long.lowestOneBit(J)J
110UNARY_INTRINSIC(MterpLongLowestOneBit, LowestOneBitValue, GetVRegLong, SetJ);
111
112// java.lang.Long.numberOfLeadingZeros(J)I
113UNARY_INTRINSIC(MterpLongNumberOfLeadingZeros, JAVASTYLE_CLZ, GetVRegLong, SetJ);
114
115// java.lang.Long.numberOfTrailingZeros(J)I
116UNARY_INTRINSIC(MterpLongNumberOfTrailingZeros, JAVASTYLE_CTZ, GetVRegLong, SetJ);
117
118// java.lang.Long.rotateRight(JI)J
119BINARY_JJ_INTRINSIC(MterpLongRotateRight, (Rot<int64_t, false>), SetJ);
120
121// java.lang.Long.rotateLeft(JI)J
122BINARY_JJ_INTRINSIC(MterpLongRotateLeft, (Rot<int64_t, true>), SetJ);
123
124// java.lang.Long.signum(J)I
125UNARY_INTRINSIC(MterpLongSignum, Signum, GetVRegLong, SetI);
126
127// java.lang.Short.reverseBytes(S)S
128UNARY_INTRINSIC(MterpShortReverseBytes, BSWAP, GetVRegShort, SetS);
129
buzbee78f1bdc2017-03-01 10:55:57 -0800130// java.lang.Math.min(II)I
buzbee31afbec2017-03-14 15:30:19 -0700131BINARY_II_INTRINSIC(MterpMathMinIntInt, std::min, SetI);
132
buzbee78f1bdc2017-03-01 10:55:57 -0800133// java.lang.Math.min(JJ)J
buzbee31afbec2017-03-14 15:30:19 -0700134BINARY_JJ_INTRINSIC(MterpMathMinLongLong, std::min, SetJ);
135
buzbee78f1bdc2017-03-01 10:55:57 -0800136// java.lang.Math.max(II)I
buzbee31afbec2017-03-14 15:30:19 -0700137BINARY_II_INTRINSIC(MterpMathMaxIntInt, std::max, SetI);
138
buzbee78f1bdc2017-03-01 10:55:57 -0800139// java.lang.Math.max(JJ)J
buzbee31afbec2017-03-14 15:30:19 -0700140BINARY_JJ_INTRINSIC(MterpMathMaxLongLong, std::max, SetJ);
141
buzbee78f1bdc2017-03-01 10:55:57 -0800142// java.lang.Math.abs(I)I
buzbee31afbec2017-03-14 15:30:19 -0700143UNARY_INTRINSIC(MterpMathAbsInt, std::abs, GetVReg, SetI);
144
buzbee78f1bdc2017-03-01 10:55:57 -0800145// java.lang.Math.abs(J)J
buzbee31afbec2017-03-14 15:30:19 -0700146UNARY_INTRINSIC(MterpMathAbsLong, std::abs, GetVRegLong, SetJ);
147
buzbee78f1bdc2017-03-01 10:55:57 -0800148// java.lang.Math.abs(F)F
buzbee31afbec2017-03-14 15:30:19 -0700149UNARY_INTRINSIC(MterpMathAbsFloat, 0x7fffffff&, GetVReg, SetI);
150
buzbee78f1bdc2017-03-01 10:55:57 -0800151// java.lang.Math.abs(D)D
buzbee31afbec2017-03-14 15:30:19 -0700152UNARY_INTRINSIC(MterpMathAbsDouble, INT64_C(0x7fffffffffffffff)&, GetVRegLong, SetJ);
153
buzbee78f1bdc2017-03-01 10:55:57 -0800154// java.lang.Math.sqrt(D)D
buzbee31afbec2017-03-14 15:30:19 -0700155UNARY_INTRINSIC(MterpMathSqrt, std::sqrt, GetVRegDouble, SetD);
156
buzbee78f1bdc2017-03-01 10:55:57 -0800157// java.lang.Math.ceil(D)D
buzbee31afbec2017-03-14 15:30:19 -0700158UNARY_INTRINSIC(MterpMathCeil, std::ceil, GetVRegDouble, SetD);
159
buzbee78f1bdc2017-03-01 10:55:57 -0800160// java.lang.Math.floor(D)D
buzbee31afbec2017-03-14 15:30:19 -0700161UNARY_INTRINSIC(MterpMathFloor, std::floor, GetVRegDouble, SetD);
162
buzbee78f1bdc2017-03-01 10:55:57 -0800163// java.lang.Math.sin(D)D
buzbee31afbec2017-03-14 15:30:19 -0700164UNARY_INTRINSIC(MterpMathSin, std::sin, GetVRegDouble, SetD);
165
buzbee78f1bdc2017-03-01 10:55:57 -0800166// java.lang.Math.cos(D)D
buzbee31afbec2017-03-14 15:30:19 -0700167UNARY_INTRINSIC(MterpMathCos, std::cos, GetVRegDouble, SetD);
168
buzbee78f1bdc2017-03-01 10:55:57 -0800169// java.lang.Math.tan(D)D
buzbee31afbec2017-03-14 15:30:19 -0700170UNARY_INTRINSIC(MterpMathTan, std::tan, GetVRegDouble, SetD);
171
buzbee78f1bdc2017-03-01 10:55:57 -0800172// java.lang.Math.asin(D)D
buzbee31afbec2017-03-14 15:30:19 -0700173UNARY_INTRINSIC(MterpMathAsin, std::asin, GetVRegDouble, SetD);
174
buzbee78f1bdc2017-03-01 10:55:57 -0800175// java.lang.Math.acos(D)D
buzbee31afbec2017-03-14 15:30:19 -0700176UNARY_INTRINSIC(MterpMathAcos, std::acos, GetVRegDouble, SetD);
177
buzbee78f1bdc2017-03-01 10:55:57 -0800178// java.lang.Math.atan(D)D
buzbee31afbec2017-03-14 15:30:19 -0700179UNARY_INTRINSIC(MterpMathAtan, std::atan, GetVRegDouble, SetD);
buzbee78f1bdc2017-03-01 10:55:57 -0800180
buzbeee667a3c2017-03-09 13:51:23 -0800181// java.lang.String.charAt(I)C
182static ALWAYS_INLINE bool MterpStringCharAt(ShadowFrame* shadow_frame,
183 const Instruction* inst,
184 uint16_t inst_data,
185 JValue* result_register)
186 REQUIRES_SHARED(Locks::mutator_lock_) {
187 uint32_t arg[Instruction::kMaxVarArgRegs] = {};
188 inst->GetVarArgs(arg, inst_data);
189 mirror::String* str = shadow_frame->GetVRegReference(arg[0])->AsString();
190 int length = str->GetLength();
191 int index = shadow_frame->GetVReg(arg[1]);
192 uint16_t res;
193 if (UNLIKELY(index < 0) || (index >= length)) {
194 return false; // Punt and let non-intrinsic version deal with the throw.
195 }
196 if (str->IsCompressed()) {
197 res = str->GetValueCompressed()[index];
198 } else {
199 res = str->GetValue()[index];
200 }
201 result_register->SetC(res);
202 return true;
203}
204
205// java.lang.String.compareTo(Ljava/lang/string)I
206static ALWAYS_INLINE bool MterpStringCompareTo(ShadowFrame* shadow_frame,
207 const Instruction* inst,
208 uint16_t inst_data,
209 JValue* result_register)
210 REQUIRES_SHARED(Locks::mutator_lock_) {
211 uint32_t arg[Instruction::kMaxVarArgRegs] = {};
212 inst->GetVarArgs(arg, inst_data);
213 mirror::String* str = shadow_frame->GetVRegReference(arg[0])->AsString();
214 mirror::Object* arg1 = shadow_frame->GetVRegReference(arg[1]);
215 if (arg1 == nullptr) {
216 return false;
217 }
218 result_register->SetI(str->CompareTo(arg1->AsString()));
219 return true;
220}
221
222#define STRING_INDEXOF_INTRINSIC(name, starting_pos) \
223static ALWAYS_INLINE bool Mterp##name(ShadowFrame* shadow_frame, \
224 const Instruction* inst, \
225 uint16_t inst_data, \
226 JValue* result_register) \
227 REQUIRES_SHARED(Locks::mutator_lock_) { \
228 uint32_t arg[Instruction::kMaxVarArgRegs] = {}; \
229 inst->GetVarArgs(arg, inst_data); \
230 mirror::String* str = shadow_frame->GetVRegReference(arg[0])->AsString(); \
231 int ch = shadow_frame->GetVReg(arg[1]); \
232 if (ch >= 0x10000) { \
233 /* Punt if supplementary char. */ \
234 return false; \
235 } \
236 result_register->SetI(str->FastIndexOf(ch, starting_pos)); \
237 return true; \
238}
239
240// java.lang.String.indexOf(I)I
241STRING_INDEXOF_INTRINSIC(StringIndexOf, 0);
242
243// java.lang.String.indexOf(II)I
244STRING_INDEXOF_INTRINSIC(StringIndexOfAfter, shadow_frame->GetVReg(arg[2]));
245
246#define SIMPLE_STRING_INTRINSIC(name, operation) \
247static ALWAYS_INLINE bool Mterp##name(ShadowFrame* shadow_frame, \
248 const Instruction* inst, \
249 uint16_t inst_data, \
250 JValue* result_register) \
251 REQUIRES_SHARED(Locks::mutator_lock_) { \
252 uint32_t arg[Instruction::kMaxVarArgRegs] = {}; \
253 inst->GetVarArgs(arg, inst_data); \
254 mirror::String* str = shadow_frame->GetVRegReference(arg[0])->AsString(); \
255 result_register->operation; \
256 return true; \
257}
258
259// java.lang.String.isEmpty()Z
260SIMPLE_STRING_INTRINSIC(StringIsEmpty, SetZ(str->GetLength() == 0))
261
262// java.lang.String.length()I
263SIMPLE_STRING_INTRINSIC(StringLength, SetI(str->GetLength()))
264
265// java.lang.String.getCharsNoCheck(II[CI)V
266static ALWAYS_INLINE bool MterpStringGetCharsNoCheck(ShadowFrame* shadow_frame,
267 const Instruction* inst,
268 uint16_t inst_data,
269 JValue* result_register ATTRIBUTE_UNUSED)
270 REQUIRES_SHARED(Locks::mutator_lock_) {
271 // Start, end & index already checked by caller - won't throw. Destination is uncompressed.
272 uint32_t arg[Instruction::kMaxVarArgRegs] = {};
273 inst->GetVarArgs(arg, inst_data);
274 mirror::String* str = shadow_frame->GetVRegReference(arg[0])->AsString();
275 int32_t start = shadow_frame->GetVReg(arg[1]);
276 int32_t end = shadow_frame->GetVReg(arg[2]);
277 int32_t index = shadow_frame->GetVReg(arg[4]);
278 mirror::CharArray* array = shadow_frame->GetVRegReference(arg[3])->AsCharArray();
279 uint16_t* dst = array->GetData() + index;
280 int32_t len = (end - start);
281 if (str->IsCompressed()) {
282 const uint8_t* src_8 = str->GetValueCompressed() + start;
283 for (int i = 0; i < len; i++) {
284 dst[i] = src_8[i];
285 }
286 } else {
287 uint16_t* src_16 = str->GetValue() + start;
288 memcpy(dst, src_16, len * sizeof(uint16_t));
289 }
290 return true;
291}
292
293// java.lang.String.equalsLjava/lang/Object;)Z
294static ALWAYS_INLINE bool MterpStringEquals(ShadowFrame* shadow_frame,
295 const Instruction* inst,
296 uint16_t inst_data,
297 JValue* result_register)
298 REQUIRES_SHARED(Locks::mutator_lock_) {
299 uint32_t arg[Instruction::kMaxVarArgRegs] = {};
300 inst->GetVarArgs(arg, inst_data);
301 mirror::String* str = shadow_frame->GetVRegReference(arg[0])->AsString();
302 mirror::Object* obj = shadow_frame->GetVRegReference(arg[1]);
303 bool res = false; // Assume not equal.
304 if ((obj != nullptr) && obj->IsString()) {
305 mirror::String* str2 = obj->AsString();
306 if (str->GetCount() == str2->GetCount()) {
307 // Length & compression status are same. Can use block compare.
308 void* bytes1;
309 void* bytes2;
310 int len = str->GetLength();
311 if (str->IsCompressed()) {
312 bytes1 = str->GetValueCompressed();
313 bytes2 = str2->GetValueCompressed();
314 } else {
315 len *= sizeof(uint16_t);
316 bytes1 = str->GetValue();
317 bytes2 = str2->GetValue();
318 }
319 res = (memcmp(bytes1, bytes2, len) == 0);
320 }
321 }
322 result_register->SetZ(res);
323 return true;
324}
325
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100326#define VARHANDLE_FENCE_INTRINSIC(name, std_memory_operation) \
327static ALWAYS_INLINE bool name(ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, \
328 const Instruction* inst ATTRIBUTE_UNUSED, \
329 uint16_t inst_data ATTRIBUTE_UNUSED, \
330 JValue* result_register ATTRIBUTE_UNUSED) \
331 REQUIRES_SHARED(Locks::mutator_lock_) { \
332 std::atomic_thread_fence(std_memory_operation); \
333 return true; \
Orion Hodson4a4610a2017-09-28 16:57:55 +0100334}
335
336// The VarHandle fence methods are static (unlike sun.misc.Unsafe versions).
337// The fences for the LoadLoadFence and StoreStoreFence are stronger
338// than strictly required, but the impact should be marginal.
339VARHANDLE_FENCE_INTRINSIC(MterpVarHandleFullFence, std::memory_order_seq_cst)
340VARHANDLE_FENCE_INTRINSIC(MterpVarHandleAcquireFence, std::memory_order_acquire)
341VARHANDLE_FENCE_INTRINSIC(MterpVarHandleReleaseFence, std::memory_order_release)
342VARHANDLE_FENCE_INTRINSIC(MterpVarHandleLoadLoadFence, std::memory_order_acquire)
343VARHANDLE_FENCE_INTRINSIC(MterpVarHandleStoreStoreFence, std::memory_order_release)
344
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100345#define METHOD_HANDLE_INVOKE_INTRINSIC(name) \
346static ALWAYS_INLINE bool Mterp##name(ShadowFrame* shadow_frame, \
347 const Instruction* inst, \
348 uint16_t inst_data, \
349 JValue* result) \
350 REQUIRES_SHARED(Locks::mutator_lock_) { \
351 if (inst->Opcode() == Instruction::INVOKE_POLYMORPHIC) { \
352 return DoInvokePolymorphic<false>(Thread::Current(), *shadow_frame, inst, inst_data, result); \
353 } else { \
354 return DoInvokePolymorphic<true>(Thread::Current(), *shadow_frame, inst, inst_data, result); \
355 } \
356}
357
358METHOD_HANDLE_INVOKE_INTRINSIC(MethodHandleInvokeExact)
359METHOD_HANDLE_INVOKE_INTRINSIC(MethodHandleInvoke)
360
361#define VAR_HANDLE_ACCESSOR_INTRINSIC(name) \
362static ALWAYS_INLINE bool Mterp##name(ShadowFrame* shadow_frame, \
363 const Instruction* inst, \
364 uint16_t inst_data, \
365 JValue* result) \
366 REQUIRES_SHARED(Locks::mutator_lock_) { \
367 return Do##name(Thread::Current(), *shadow_frame, inst, inst_data, result); \
368}
369
370VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleCompareAndExchange)
371VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleCompareAndExchangeAcquire)
372VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleCompareAndExchangeRelease)
373VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleCompareAndSet)
374VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGet);
375VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAcquire)
376VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndAdd)
377VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndAddAcquire)
378VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndAddRelease)
379VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseAnd)
380VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseAndAcquire)
381VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseAndRelease)
382VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseOr)
383VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseOrAcquire)
384VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseOrRelease)
385VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseXor)
386VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseXorAcquire)
387VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseXorRelease)
388VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndSet)
389VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndSetAcquire)
390VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndSetRelease)
391VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetOpaque)
392VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetVolatile)
393VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleSet)
394VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleSetOpaque)
395VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleSetRelease)
396VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleSetVolatile)
397VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSet)
398VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetAcquire)
399VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetPlain)
400VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetRelease)
401
buzbee31afbec2017-03-14 15:30:19 -0700402// Macro to help keep track of what's left to implement.
403#define UNIMPLEMENTED_CASE(name) \
404 case Intrinsics::k##name: \
405 res = false; \
406 break;
407
buzbee78f1bdc2017-03-01 10:55:57 -0800408#define INTRINSIC_CASE(name) \
409 case Intrinsics::k##name: \
410 res = Mterp##name(shadow_frame, inst, inst_data, result_register); \
411 break;
412
413bool MterpHandleIntrinsic(ShadowFrame* shadow_frame,
414 ArtMethod* const called_method,
415 const Instruction* inst,
416 uint16_t inst_data,
417 JValue* result_register)
418 REQUIRES_SHARED(Locks::mutator_lock_) {
419 Intrinsics intrinsic = static_cast<Intrinsics>(called_method->GetIntrinsic());
420 bool res = false; // Assume failure
421 switch (intrinsic) {
buzbee31afbec2017-03-14 15:30:19 -0700422 UNIMPLEMENTED_CASE(DoubleDoubleToRawLongBits /* (D)J */)
423 UNIMPLEMENTED_CASE(DoubleDoubleToLongBits /* (D)J */)
424 UNIMPLEMENTED_CASE(DoubleIsInfinite /* (D)Z */)
425 UNIMPLEMENTED_CASE(DoubleIsNaN /* (D)Z */)
426 UNIMPLEMENTED_CASE(DoubleLongBitsToDouble /* (J)D */)
427 UNIMPLEMENTED_CASE(FloatFloatToRawIntBits /* (F)I */)
428 UNIMPLEMENTED_CASE(FloatFloatToIntBits /* (F)I */)
429 UNIMPLEMENTED_CASE(FloatIsInfinite /* (F)Z */)
430 UNIMPLEMENTED_CASE(FloatIsNaN /* (F)Z */)
431 UNIMPLEMENTED_CASE(FloatIntBitsToFloat /* (I)F */)
432 INTRINSIC_CASE(IntegerReverse)
433 INTRINSIC_CASE(IntegerReverseBytes)
434 INTRINSIC_CASE(IntegerBitCount)
435 INTRINSIC_CASE(IntegerCompare)
436 INTRINSIC_CASE(IntegerHighestOneBit)
437 INTRINSIC_CASE(IntegerLowestOneBit)
438 INTRINSIC_CASE(IntegerNumberOfLeadingZeros)
439 INTRINSIC_CASE(IntegerNumberOfTrailingZeros)
440 INTRINSIC_CASE(IntegerRotateRight)
441 INTRINSIC_CASE(IntegerRotateLeft)
442 INTRINSIC_CASE(IntegerSignum)
443 INTRINSIC_CASE(LongReverse)
444 INTRINSIC_CASE(LongReverseBytes)
445 INTRINSIC_CASE(LongBitCount)
446 INTRINSIC_CASE(LongCompare)
447 INTRINSIC_CASE(LongHighestOneBit)
448 INTRINSIC_CASE(LongLowestOneBit)
449 INTRINSIC_CASE(LongNumberOfLeadingZeros)
450 INTRINSIC_CASE(LongNumberOfTrailingZeros)
451 INTRINSIC_CASE(LongRotateRight)
452 INTRINSIC_CASE(LongRotateLeft)
453 INTRINSIC_CASE(LongSignum)
454 INTRINSIC_CASE(ShortReverseBytes)
buzbee78f1bdc2017-03-01 10:55:57 -0800455 INTRINSIC_CASE(MathAbsDouble)
buzbee31afbec2017-03-14 15:30:19 -0700456 INTRINSIC_CASE(MathAbsFloat)
457 INTRINSIC_CASE(MathAbsLong)
458 INTRINSIC_CASE(MathAbsInt)
459 UNIMPLEMENTED_CASE(MathMinDoubleDouble /* (DD)D */)
460 UNIMPLEMENTED_CASE(MathMinFloatFloat /* (FF)F */)
461 INTRINSIC_CASE(MathMinLongLong)
462 INTRINSIC_CASE(MathMinIntInt)
463 UNIMPLEMENTED_CASE(MathMaxDoubleDouble /* (DD)D */)
464 UNIMPLEMENTED_CASE(MathMaxFloatFloat /* (FF)F */)
465 INTRINSIC_CASE(MathMaxLongLong)
466 INTRINSIC_CASE(MathMaxIntInt)
467 INTRINSIC_CASE(MathCos)
468 INTRINSIC_CASE(MathSin)
469 INTRINSIC_CASE(MathAcos)
470 INTRINSIC_CASE(MathAsin)
471 INTRINSIC_CASE(MathAtan)
472 UNIMPLEMENTED_CASE(MathAtan2 /* (DD)D */)
473 UNIMPLEMENTED_CASE(MathCbrt /* (D)D */)
474 UNIMPLEMENTED_CASE(MathCosh /* (D)D */)
475 UNIMPLEMENTED_CASE(MathExp /* (D)D */)
476 UNIMPLEMENTED_CASE(MathExpm1 /* (D)D */)
477 UNIMPLEMENTED_CASE(MathHypot /* (DD)D */)
478 UNIMPLEMENTED_CASE(MathLog /* (D)D */)
479 UNIMPLEMENTED_CASE(MathLog10 /* (D)D */)
480 UNIMPLEMENTED_CASE(MathNextAfter /* (DD)D */)
Vladimir Marko4d179872018-01-19 14:50:10 +0000481 UNIMPLEMENTED_CASE(MathPow /* (DD)D */)
buzbee31afbec2017-03-14 15:30:19 -0700482 UNIMPLEMENTED_CASE(MathSinh /* (D)D */)
483 INTRINSIC_CASE(MathTan)
484 UNIMPLEMENTED_CASE(MathTanh /* (D)D */)
buzbee78f1bdc2017-03-01 10:55:57 -0800485 INTRINSIC_CASE(MathSqrt)
486 INTRINSIC_CASE(MathCeil)
487 INTRINSIC_CASE(MathFloor)
buzbee31afbec2017-03-14 15:30:19 -0700488 UNIMPLEMENTED_CASE(MathRint /* (D)D */)
489 UNIMPLEMENTED_CASE(MathRoundDouble /* (D)J */)
490 UNIMPLEMENTED_CASE(MathRoundFloat /* (F)I */)
491 UNIMPLEMENTED_CASE(SystemArrayCopyChar /* ([CI[CII)V */)
492 UNIMPLEMENTED_CASE(SystemArrayCopy /* (Ljava/lang/Object;ILjava/lang/Object;II)V */)
493 UNIMPLEMENTED_CASE(ThreadCurrentThread /* ()Ljava/lang/Thread; */)
494 UNIMPLEMENTED_CASE(MemoryPeekByte /* (J)B */)
495 UNIMPLEMENTED_CASE(MemoryPeekIntNative /* (J)I */)
496 UNIMPLEMENTED_CASE(MemoryPeekLongNative /* (J)J */)
497 UNIMPLEMENTED_CASE(MemoryPeekShortNative /* (J)S */)
498 UNIMPLEMENTED_CASE(MemoryPokeByte /* (JB)V */)
499 UNIMPLEMENTED_CASE(MemoryPokeIntNative /* (JI)V */)
500 UNIMPLEMENTED_CASE(MemoryPokeLongNative /* (JJ)V */)
501 UNIMPLEMENTED_CASE(MemoryPokeShortNative /* (JS)V */)
buzbeee667a3c2017-03-09 13:51:23 -0800502 INTRINSIC_CASE(StringCharAt)
503 INTRINSIC_CASE(StringCompareTo)
buzbeee667a3c2017-03-09 13:51:23 -0800504 INTRINSIC_CASE(StringEquals)
505 INTRINSIC_CASE(StringGetCharsNoCheck)
buzbee31afbec2017-03-14 15:30:19 -0700506 INTRINSIC_CASE(StringIndexOf)
507 INTRINSIC_CASE(StringIndexOfAfter)
508 UNIMPLEMENTED_CASE(StringStringIndexOf /* (Ljava/lang/String;)I */)
509 UNIMPLEMENTED_CASE(StringStringIndexOfAfter /* (Ljava/lang/String;I)I */)
buzbeee667a3c2017-03-09 13:51:23 -0800510 INTRINSIC_CASE(StringIsEmpty)
511 INTRINSIC_CASE(StringLength)
buzbee31afbec2017-03-14 15:30:19 -0700512 UNIMPLEMENTED_CASE(StringNewStringFromBytes /* ([BIII)Ljava/lang/String; */)
513 UNIMPLEMENTED_CASE(StringNewStringFromChars /* (II[C)Ljava/lang/String; */)
514 UNIMPLEMENTED_CASE(StringNewStringFromString /* (Ljava/lang/String;)Ljava/lang/String; */)
515 UNIMPLEMENTED_CASE(StringBufferAppend /* (Ljava/lang/String;)Ljava/lang/StringBuffer; */)
516 UNIMPLEMENTED_CASE(StringBufferLength /* ()I */)
517 UNIMPLEMENTED_CASE(StringBufferToString /* ()Ljava/lang/String; */)
518 UNIMPLEMENTED_CASE(StringBuilderAppend /* (Ljava/lang/String;)Ljava/lang/StringBuilder; */)
519 UNIMPLEMENTED_CASE(StringBuilderLength /* ()I */)
520 UNIMPLEMENTED_CASE(StringBuilderToString /* ()Ljava/lang/String; */)
521 UNIMPLEMENTED_CASE(UnsafeCASInt /* (Ljava/lang/Object;JII)Z */)
522 UNIMPLEMENTED_CASE(UnsafeCASLong /* (Ljava/lang/Object;JJJ)Z */)
523 UNIMPLEMENTED_CASE(UnsafeCASObject /* (Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z */)
524 UNIMPLEMENTED_CASE(UnsafeGet /* (Ljava/lang/Object;J)I */)
525 UNIMPLEMENTED_CASE(UnsafeGetVolatile /* (Ljava/lang/Object;J)I */)
526 UNIMPLEMENTED_CASE(UnsafeGetObject /* (Ljava/lang/Object;J)Ljava/lang/Object; */)
527 UNIMPLEMENTED_CASE(UnsafeGetObjectVolatile /* (Ljava/lang/Object;J)Ljava/lang/Object; */)
528 UNIMPLEMENTED_CASE(UnsafeGetLong /* (Ljava/lang/Object;J)J */)
529 UNIMPLEMENTED_CASE(UnsafeGetLongVolatile /* (Ljava/lang/Object;J)J */)
530 UNIMPLEMENTED_CASE(UnsafePut /* (Ljava/lang/Object;JI)V */)
531 UNIMPLEMENTED_CASE(UnsafePutOrdered /* (Ljava/lang/Object;JI)V */)
532 UNIMPLEMENTED_CASE(UnsafePutVolatile /* (Ljava/lang/Object;JI)V */)
533 UNIMPLEMENTED_CASE(UnsafePutObject /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
534 UNIMPLEMENTED_CASE(UnsafePutObjectOrdered /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
535 UNIMPLEMENTED_CASE(UnsafePutObjectVolatile /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
536 UNIMPLEMENTED_CASE(UnsafePutLong /* (Ljava/lang/Object;JJ)V */)
537 UNIMPLEMENTED_CASE(UnsafePutLongOrdered /* (Ljava/lang/Object;JJ)V */)
538 UNIMPLEMENTED_CASE(UnsafePutLongVolatile /* (Ljava/lang/Object;JJ)V */)
539 UNIMPLEMENTED_CASE(UnsafeGetAndAddInt /* (Ljava/lang/Object;JI)I */)
540 UNIMPLEMENTED_CASE(UnsafeGetAndAddLong /* (Ljava/lang/Object;JJ)J */)
541 UNIMPLEMENTED_CASE(UnsafeGetAndSetInt /* (Ljava/lang/Object;JI)I */)
542 UNIMPLEMENTED_CASE(UnsafeGetAndSetLong /* (Ljava/lang/Object;JJ)J */)
543 UNIMPLEMENTED_CASE(UnsafeGetAndSetObject /* (Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object; */)
544 UNIMPLEMENTED_CASE(UnsafeLoadFence /* ()V */)
545 UNIMPLEMENTED_CASE(UnsafeStoreFence /* ()V */)
546 UNIMPLEMENTED_CASE(UnsafeFullFence /* ()V */)
547 UNIMPLEMENTED_CASE(ReferenceGetReferent /* ()Ljava/lang/Object; */)
548 UNIMPLEMENTED_CASE(IntegerValueOf /* (I)Ljava/lang/Integer; */)
Nicolas Geoffray365719c2017-03-08 13:11:50 +0000549 UNIMPLEMENTED_CASE(ThreadInterrupted /* ()Z */)
Orion Hodson4a4610a2017-09-28 16:57:55 +0100550 INTRINSIC_CASE(VarHandleFullFence)
551 INTRINSIC_CASE(VarHandleAcquireFence)
552 INTRINSIC_CASE(VarHandleReleaseFence)
553 INTRINSIC_CASE(VarHandleLoadLoadFence)
554 INTRINSIC_CASE(VarHandleStoreStoreFence)
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100555 INTRINSIC_CASE(MethodHandleInvokeExact)
556 INTRINSIC_CASE(MethodHandleInvoke)
557 INTRINSIC_CASE(VarHandleCompareAndExchange)
558 INTRINSIC_CASE(VarHandleCompareAndExchangeAcquire)
559 INTRINSIC_CASE(VarHandleCompareAndExchangeRelease)
560 INTRINSIC_CASE(VarHandleCompareAndSet)
561 INTRINSIC_CASE(VarHandleGet)
562 INTRINSIC_CASE(VarHandleGetAcquire)
563 INTRINSIC_CASE(VarHandleGetAndAdd)
564 INTRINSIC_CASE(VarHandleGetAndAddAcquire)
565 INTRINSIC_CASE(VarHandleGetAndAddRelease)
566 INTRINSIC_CASE(VarHandleGetAndBitwiseAnd)
567 INTRINSIC_CASE(VarHandleGetAndBitwiseAndAcquire)
568 INTRINSIC_CASE(VarHandleGetAndBitwiseAndRelease)
569 INTRINSIC_CASE(VarHandleGetAndBitwiseOr)
570 INTRINSIC_CASE(VarHandleGetAndBitwiseOrAcquire)
571 INTRINSIC_CASE(VarHandleGetAndBitwiseOrRelease)
572 INTRINSIC_CASE(VarHandleGetAndBitwiseXor)
573 INTRINSIC_CASE(VarHandleGetAndBitwiseXorAcquire)
574 INTRINSIC_CASE(VarHandleGetAndBitwiseXorRelease)
575 INTRINSIC_CASE(VarHandleGetAndSet)
576 INTRINSIC_CASE(VarHandleGetAndSetAcquire)
577 INTRINSIC_CASE(VarHandleGetAndSetRelease)
578 INTRINSIC_CASE(VarHandleGetOpaque)
579 INTRINSIC_CASE(VarHandleGetVolatile)
580 INTRINSIC_CASE(VarHandleSet)
581 INTRINSIC_CASE(VarHandleSetOpaque)
582 INTRINSIC_CASE(VarHandleSetRelease)
583 INTRINSIC_CASE(VarHandleSetVolatile)
584 INTRINSIC_CASE(VarHandleWeakCompareAndSet)
585 INTRINSIC_CASE(VarHandleWeakCompareAndSetAcquire)
586 INTRINSIC_CASE(VarHandleWeakCompareAndSetPlain)
587 INTRINSIC_CASE(VarHandleWeakCompareAndSetRelease)
buzbee31afbec2017-03-14 15:30:19 -0700588 case Intrinsics::kNone:
589 res = false;
buzbee78f1bdc2017-03-01 10:55:57 -0800590 break;
buzbee31afbec2017-03-14 15:30:19 -0700591 // Note: no default case to ensure we catch any newly added intrinsics.
buzbee78f1bdc2017-03-01 10:55:57 -0800592 }
593 return res;
594}
595
596} // namespace interpreter
597} // namespace art