1 /*
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 
17 #include "interpreter/interpreter_intrinsics.h"
18 
19 #include "dex/dex_instruction.h"
20 #include "intrinsics_enum.h"
21 #include "interpreter/interpreter_common.h"
22 
23 namespace art {
24 namespace interpreter {
25 
26 
27 #define BINARY_INTRINSIC(name, op, get1, get2, set)                 \
28 static 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;                                                      \
37 }
38 
39 #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)                  \
49 static 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 
60 
61 // java.lang.Integer.reverse(I)I
62 UNARY_INTRINSIC(MterpIntegerReverse, ReverseBits32, GetVReg, SetI);
63 
64 // java.lang.Integer.reverseBytes(I)I
65 UNARY_INTRINSIC(MterpIntegerReverseBytes, BSWAP, GetVReg, SetI);
66 
67 // java.lang.Integer.bitCount(I)I
68 UNARY_INTRINSIC(MterpIntegerBitCount, POPCOUNT, GetVReg, SetI);
69 
70 // java.lang.Integer.compare(II)I
71 BINARY_II_INTRINSIC(MterpIntegerCompare, Compare, SetI);
72 
73 // java.lang.Integer.highestOneBit(I)I
74 UNARY_INTRINSIC(MterpIntegerHighestOneBit, HighestOneBitValue, GetVReg, SetI);
75 
76 // java.lang.Integer.LowestOneBit(I)I
77 UNARY_INTRINSIC(MterpIntegerLowestOneBit, LowestOneBitValue, GetVReg, SetI);
78 
79 // java.lang.Integer.numberOfLeadingZeros(I)I
80 UNARY_INTRINSIC(MterpIntegerNumberOfLeadingZeros, JAVASTYLE_CLZ, GetVReg, SetI);
81 
82 // java.lang.Integer.numberOfTrailingZeros(I)I
83 UNARY_INTRINSIC(MterpIntegerNumberOfTrailingZeros, JAVASTYLE_CTZ, GetVReg, SetI);
84 
85 // java.lang.Integer.rotateRight(II)I
86 BINARY_II_INTRINSIC(MterpIntegerRotateRight, (Rot<int32_t, false>), SetI);
87 
88 // java.lang.Integer.rotateLeft(II)I
89 BINARY_II_INTRINSIC(MterpIntegerRotateLeft, (Rot<int32_t, true>), SetI);
90 
91 // java.lang.Integer.signum(I)I
92 UNARY_INTRINSIC(MterpIntegerSignum, Signum, GetVReg, SetI);
93 
94 // java.lang.Long.reverse(J)J
95 UNARY_INTRINSIC(MterpLongReverse, ReverseBits64, GetVRegLong, SetJ);
96 
97 // java.lang.Long.reverseBytes(J)J
98 UNARY_INTRINSIC(MterpLongReverseBytes, BSWAP, GetVRegLong, SetJ);
99 
100 // java.lang.Long.bitCount(J)I
101 UNARY_INTRINSIC(MterpLongBitCount, POPCOUNT, GetVRegLong, SetI);
102 
103 // java.lang.Long.compare(JJ)I
104 BINARY_JJ_INTRINSIC(MterpLongCompare, Compare, SetI);
105 
106 // java.lang.Long.highestOneBit(J)J
107 UNARY_INTRINSIC(MterpLongHighestOneBit, HighestOneBitValue, GetVRegLong, SetJ);
108 
109 // java.lang.Long.lowestOneBit(J)J
110 UNARY_INTRINSIC(MterpLongLowestOneBit, LowestOneBitValue, GetVRegLong, SetJ);
111 
112 // java.lang.Long.numberOfLeadingZeros(J)I
113 UNARY_INTRINSIC(MterpLongNumberOfLeadingZeros, JAVASTYLE_CLZ, GetVRegLong, SetJ);
114 
115 // java.lang.Long.numberOfTrailingZeros(J)I
116 UNARY_INTRINSIC(MterpLongNumberOfTrailingZeros, JAVASTYLE_CTZ, GetVRegLong, SetJ);
117 
118 // java.lang.Long.rotateRight(JI)J
119 BINARY_JI_INTRINSIC(MterpLongRotateRight, (Rot<int64_t, false>), SetJ);
120 
121 // java.lang.Long.rotateLeft(JI)J
122 BINARY_JI_INTRINSIC(MterpLongRotateLeft, (Rot<int64_t, true>), SetJ);
123 
124 // java.lang.Long.signum(J)I
125 UNARY_INTRINSIC(MterpLongSignum, Signum, GetVRegLong, SetI);
126 
127 // java.lang.Short.reverseBytes(S)S
128 UNARY_INTRINSIC(MterpShortReverseBytes, BSWAP, GetVRegShort, SetS);
129 
130 // java.lang.Math.min(II)I
131 BINARY_II_INTRINSIC(MterpMathMinIntInt, std::min, SetI);
132 
133 // java.lang.Math.min(JJ)J
134 BINARY_JJ_INTRINSIC(MterpMathMinLongLong, std::min, SetJ);
135 
136 // java.lang.Math.max(II)I
137 BINARY_II_INTRINSIC(MterpMathMaxIntInt, std::max, SetI);
138 
139 // java.lang.Math.max(JJ)J
140 BINARY_JJ_INTRINSIC(MterpMathMaxLongLong, std::max, SetJ);
141 
142 // java.lang.Math.abs(I)I
143 UNARY_INTRINSIC(MterpMathAbsInt, std::abs, GetVReg, SetI);
144 
145 // java.lang.Math.abs(J)J
146 UNARY_INTRINSIC(MterpMathAbsLong, std::abs, GetVRegLong, SetJ);
147 
148 // java.lang.Math.abs(F)F
149 UNARY_INTRINSIC(MterpMathAbsFloat, 0x7fffffff&, GetVReg, SetI);
150 
151 // java.lang.Math.abs(D)D
152 UNARY_INTRINSIC(MterpMathAbsDouble, INT64_C(0x7fffffffffffffff)&, GetVRegLong, SetJ);
153 
154 // java.lang.Math.sqrt(D)D
155 UNARY_INTRINSIC(MterpMathSqrt, std::sqrt, GetVRegDouble, SetD);
156 
157 // java.lang.Math.ceil(D)D
158 UNARY_INTRINSIC(MterpMathCeil, std::ceil, GetVRegDouble, SetD);
159 
160 // java.lang.Math.floor(D)D
161 UNARY_INTRINSIC(MterpMathFloor, std::floor, GetVRegDouble, SetD);
162 
163 // java.lang.Math.sin(D)D
164 UNARY_INTRINSIC(MterpMathSin, std::sin, GetVRegDouble, SetD);
165 
166 // java.lang.Math.cos(D)D
167 UNARY_INTRINSIC(MterpMathCos, std::cos, GetVRegDouble, SetD);
168 
169 // java.lang.Math.tan(D)D
170 UNARY_INTRINSIC(MterpMathTan, std::tan, GetVRegDouble, SetD);
171 
172 // java.lang.Math.asin(D)D
173 UNARY_INTRINSIC(MterpMathAsin, std::asin, GetVRegDouble, SetD);
174 
175 // java.lang.Math.acos(D)D
176 UNARY_INTRINSIC(MterpMathAcos, std::acos, GetVRegDouble, SetD);
177 
178 // java.lang.Math.atan(D)D
179 UNARY_INTRINSIC(MterpMathAtan, std::atan, GetVRegDouble, SetD);
180 
181 // java.lang.String.charAt(I)C
MterpStringCharAt(ShadowFrame * shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result_register)182 static 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   ObjPtr<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
MterpStringCompareTo(ShadowFrame * shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result_register)206 static 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   ObjPtr<mirror::String> str = shadow_frame->GetVRegReference(arg[0])->AsString();
214   ObjPtr<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)             \
223 static 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   ObjPtr<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
241 STRING_INDEXOF_INTRINSIC(StringIndexOf, 0);
242 
243 // java.lang.String.indexOf(II)I
244 STRING_INDEXOF_INTRINSIC(StringIndexOfAfter, shadow_frame->GetVReg(arg[2]));
245 
246 #define SIMPLE_STRING_INTRINSIC(name, operation)                 \
247 static 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   ObjPtr<mirror::String> str = shadow_frame->GetVRegReference(arg[0])->AsString(); \
255   result_register->operation;                                    \
256   return true;                                                   \
257 }
258 
259 // java.lang.String.isEmpty()Z
260 SIMPLE_STRING_INTRINSIC(StringIsEmpty, SetZ(str->GetLength() == 0))
261 
262 // java.lang.String.length()I
263 SIMPLE_STRING_INTRINSIC(StringLength, SetI(str->GetLength()))
264 
265 // java.lang.String.getCharsNoCheck(II[CI)V
MterpStringGetCharsNoCheck(ShadowFrame * shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result_register ATTRIBUTE_UNUSED)266 static 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   ObjPtr<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   ObjPtr<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
MterpStringEquals(ShadowFrame * shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result_register)294 static 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   ObjPtr<mirror::String> str = shadow_frame->GetVRegReference(arg[0])->AsString();
302   ObjPtr<mirror::Object> obj = shadow_frame->GetVRegReference(arg[1]);
303   bool res = false;  // Assume not equal.
304   if ((obj != nullptr) && obj->IsString()) {
305     ObjPtr<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 
326 #define VARHANDLE_FENCE_INTRINSIC(name, std_memory_operation)              \
327 static 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;                                                             \
334 }
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.
339 VARHANDLE_FENCE_INTRINSIC(MterpVarHandleFullFence, std::memory_order_seq_cst)
340 VARHANDLE_FENCE_INTRINSIC(MterpVarHandleAcquireFence, std::memory_order_acquire)
341 VARHANDLE_FENCE_INTRINSIC(MterpVarHandleReleaseFence, std::memory_order_release)
342 VARHANDLE_FENCE_INTRINSIC(MterpVarHandleLoadLoadFence, std::memory_order_acquire)
343 VARHANDLE_FENCE_INTRINSIC(MterpVarHandleStoreStoreFence, std::memory_order_release)
344 
345 #define METHOD_HANDLE_INVOKE_INTRINSIC(name)                                                      \
346 static 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 
358 METHOD_HANDLE_INVOKE_INTRINSIC(MethodHandleInvokeExact)
359 METHOD_HANDLE_INVOKE_INTRINSIC(MethodHandleInvoke)
360 
361 #define VAR_HANDLE_ACCESSOR_INTRINSIC(name)                                   \
362 static 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 
370 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleCompareAndExchange)
371 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleCompareAndExchangeAcquire)
372 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleCompareAndExchangeRelease)
373 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleCompareAndSet)
374 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGet);
375 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAcquire)
VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndAdd)376 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndAdd)
377 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndAddAcquire)
378 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndAddRelease)
379 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseAnd)
380 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseAndAcquire)
381 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseAndRelease)
382 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseOr)
383 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseOrAcquire)
384 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseOrRelease)
385 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseXor)
386 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseXorAcquire)
387 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndBitwiseXorRelease)
388 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndSet)
389 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndSetAcquire)
390 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetAndSetRelease)
391 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetOpaque)
392 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleGetVolatile)
393 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleSet)
394 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleSetOpaque)
395 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleSetRelease)
396 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleSetVolatile)
397 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSet)
398 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetAcquire)
399 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetPlain)
400 VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetRelease)
401 
402 static ALWAYS_INLINE bool MterpReachabilityFence(ShadowFrame* shadow_frame ATTRIBUTE_UNUSED,
403                                                  const Instruction* inst ATTRIBUTE_UNUSED,
404                                                  uint16_t inst_data ATTRIBUTE_UNUSED,
405                                                  JValue* result_register ATTRIBUTE_UNUSED)
406     REQUIRES_SHARED(Locks::mutator_lock_) {
407   // Do nothing; Its only purpose is to keep the argument reference live
408   // at preceding suspend points. That's automatic in the interpreter.
409   return true;
410 }
411 
412 // Macro to help keep track of what's left to implement.
413 #define UNIMPLEMENTED_CASE(name)    \
414     case Intrinsics::k##name:       \
415       res = false;                  \
416       break;
417 
418 #define INTRINSIC_CASE(name)                                           \
419     case Intrinsics::k##name:                                          \
420       res = Mterp##name(shadow_frame, inst, inst_data, result_register); \
421       break;
422 
MterpHandleIntrinsic(ShadowFrame * shadow_frame,ArtMethod * const called_method,const Instruction * inst,uint16_t inst_data,JValue * result_register)423 bool MterpHandleIntrinsic(ShadowFrame* shadow_frame,
424                           ArtMethod* const called_method,
425                           const Instruction* inst,
426                           uint16_t inst_data,
427                           JValue* result_register)
428     REQUIRES_SHARED(Locks::mutator_lock_) {
429   Intrinsics intrinsic = static_cast<Intrinsics>(called_method->GetIntrinsic());
430   bool res = false;  // Assume failure
431   switch (intrinsic) {
432     UNIMPLEMENTED_CASE(DoubleDoubleToRawLongBits /* (D)J */)
433     UNIMPLEMENTED_CASE(DoubleDoubleToLongBits /* (D)J */)
434     UNIMPLEMENTED_CASE(DoubleIsInfinite /* (D)Z */)
435     UNIMPLEMENTED_CASE(DoubleIsNaN /* (D)Z */)
436     UNIMPLEMENTED_CASE(DoubleLongBitsToDouble /* (J)D */)
437     UNIMPLEMENTED_CASE(FloatFloatToRawIntBits /* (F)I */)
438     UNIMPLEMENTED_CASE(FloatFloatToIntBits /* (F)I */)
439     UNIMPLEMENTED_CASE(FloatIsInfinite /* (F)Z */)
440     UNIMPLEMENTED_CASE(FloatIsNaN /* (F)Z */)
441     UNIMPLEMENTED_CASE(FloatIntBitsToFloat /* (I)F */)
442     INTRINSIC_CASE(IntegerReverse)
443     INTRINSIC_CASE(IntegerReverseBytes)
444     INTRINSIC_CASE(IntegerBitCount)
445     INTRINSIC_CASE(IntegerCompare)
446     INTRINSIC_CASE(IntegerHighestOneBit)
447     INTRINSIC_CASE(IntegerLowestOneBit)
448     INTRINSIC_CASE(IntegerNumberOfLeadingZeros)
449     INTRINSIC_CASE(IntegerNumberOfTrailingZeros)
450     INTRINSIC_CASE(IntegerRotateRight)
451     INTRINSIC_CASE(IntegerRotateLeft)
452     INTRINSIC_CASE(IntegerSignum)
453     INTRINSIC_CASE(LongReverse)
454     INTRINSIC_CASE(LongReverseBytes)
455     INTRINSIC_CASE(LongBitCount)
456     INTRINSIC_CASE(LongCompare)
457     INTRINSIC_CASE(LongHighestOneBit)
458     INTRINSIC_CASE(LongLowestOneBit)
459     INTRINSIC_CASE(LongNumberOfLeadingZeros)
460     INTRINSIC_CASE(LongNumberOfTrailingZeros)
461     INTRINSIC_CASE(LongRotateRight)
462     INTRINSIC_CASE(LongRotateLeft)
463     INTRINSIC_CASE(LongSignum)
464     INTRINSIC_CASE(ShortReverseBytes)
465     INTRINSIC_CASE(MathAbsDouble)
466     INTRINSIC_CASE(MathAbsFloat)
467     INTRINSIC_CASE(MathAbsLong)
468     INTRINSIC_CASE(MathAbsInt)
469     UNIMPLEMENTED_CASE(MathMinDoubleDouble /* (DD)D */)
470     UNIMPLEMENTED_CASE(MathMinFloatFloat /* (FF)F */)
471     INTRINSIC_CASE(MathMinLongLong)
472     INTRINSIC_CASE(MathMinIntInt)
473     UNIMPLEMENTED_CASE(MathMaxDoubleDouble /* (DD)D */)
474     UNIMPLEMENTED_CASE(MathMaxFloatFloat /* (FF)F */)
475     INTRINSIC_CASE(MathMaxLongLong)
476     INTRINSIC_CASE(MathMaxIntInt)
477     INTRINSIC_CASE(MathCos)
478     INTRINSIC_CASE(MathSin)
479     INTRINSIC_CASE(MathAcos)
480     INTRINSIC_CASE(MathAsin)
481     INTRINSIC_CASE(MathAtan)
482     UNIMPLEMENTED_CASE(MathAtan2 /* (DD)D */)
483     UNIMPLEMENTED_CASE(MathCbrt /* (D)D */)
484     UNIMPLEMENTED_CASE(MathCosh /* (D)D */)
485     UNIMPLEMENTED_CASE(MathExp /* (D)D */)
486     UNIMPLEMENTED_CASE(MathExpm1 /* (D)D */)
487     UNIMPLEMENTED_CASE(MathHypot /* (DD)D */)
488     UNIMPLEMENTED_CASE(MathLog /* (D)D */)
489     UNIMPLEMENTED_CASE(MathLog10 /* (D)D */)
490     UNIMPLEMENTED_CASE(MathNextAfter /* (DD)D */)
491     UNIMPLEMENTED_CASE(MathPow /* (DD)D */)
492     UNIMPLEMENTED_CASE(MathSinh /* (D)D */)
493     INTRINSIC_CASE(MathTan)
494     UNIMPLEMENTED_CASE(MathTanh /* (D)D */)
495     INTRINSIC_CASE(MathSqrt)
496     INTRINSIC_CASE(MathCeil)
497     INTRINSIC_CASE(MathFloor)
498     UNIMPLEMENTED_CASE(MathRint /* (D)D */)
499     UNIMPLEMENTED_CASE(MathRoundDouble /* (D)J */)
500     UNIMPLEMENTED_CASE(MathRoundFloat /* (F)I */)
501     UNIMPLEMENTED_CASE(SystemArrayCopyChar /* ([CI[CII)V */)
502     UNIMPLEMENTED_CASE(SystemArrayCopy /* (Ljava/lang/Object;ILjava/lang/Object;II)V */)
503     UNIMPLEMENTED_CASE(ThreadCurrentThread /* ()Ljava/lang/Thread; */)
504     UNIMPLEMENTED_CASE(MemoryPeekByte /* (J)B */)
505     UNIMPLEMENTED_CASE(MemoryPeekIntNative /* (J)I */)
506     UNIMPLEMENTED_CASE(MemoryPeekLongNative /* (J)J */)
507     UNIMPLEMENTED_CASE(MemoryPeekShortNative /* (J)S */)
508     UNIMPLEMENTED_CASE(MemoryPokeByte /* (JB)V */)
509     UNIMPLEMENTED_CASE(MemoryPokeIntNative /* (JI)V */)
510     UNIMPLEMENTED_CASE(MemoryPokeLongNative /* (JJ)V */)
511     UNIMPLEMENTED_CASE(MemoryPokeShortNative /* (JS)V */)
512     INTRINSIC_CASE(ReachabilityFence /* (Ljava/lang/Object;)V */)
513     INTRINSIC_CASE(StringCharAt)
514     INTRINSIC_CASE(StringCompareTo)
515     INTRINSIC_CASE(StringEquals)
516     INTRINSIC_CASE(StringGetCharsNoCheck)
517     INTRINSIC_CASE(StringIndexOf)
518     INTRINSIC_CASE(StringIndexOfAfter)
519     UNIMPLEMENTED_CASE(StringStringIndexOf /* (Ljava/lang/String;)I */)
520     UNIMPLEMENTED_CASE(StringStringIndexOfAfter /* (Ljava/lang/String;I)I */)
521     INTRINSIC_CASE(StringIsEmpty)
522     INTRINSIC_CASE(StringLength)
523     UNIMPLEMENTED_CASE(StringNewStringFromBytes /* ([BIII)Ljava/lang/String; */)
524     UNIMPLEMENTED_CASE(StringNewStringFromChars /* (II[C)Ljava/lang/String; */)
525     UNIMPLEMENTED_CASE(StringNewStringFromString /* (Ljava/lang/String;)Ljava/lang/String; */)
526     UNIMPLEMENTED_CASE(StringBufferAppend /* (Ljava/lang/String;)Ljava/lang/StringBuffer; */)
527     UNIMPLEMENTED_CASE(StringBufferLength /* ()I */)
528     UNIMPLEMENTED_CASE(StringBufferToString /* ()Ljava/lang/String; */)
529     UNIMPLEMENTED_CASE(
530         StringBuilderAppendObject /* (Ljava/lang/Object;)Ljava/lang/StringBuilder; */)
531     UNIMPLEMENTED_CASE(
532         StringBuilderAppendString /* (Ljava/lang/String;)Ljava/lang/StringBuilder; */)
533     UNIMPLEMENTED_CASE(
534         StringBuilderAppendCharSequence /* (Ljava/lang/CharSequence;)Ljava/lang/StringBuilder; */)
535     UNIMPLEMENTED_CASE(StringBuilderAppendCharArray /* ([C)Ljava/lang/StringBuilder; */)
536     UNIMPLEMENTED_CASE(StringBuilderAppendBoolean /* (Z)Ljava/lang/StringBuilder; */)
537     UNIMPLEMENTED_CASE(StringBuilderAppendChar /* (C)Ljava/lang/StringBuilder; */)
538     UNIMPLEMENTED_CASE(StringBuilderAppendInt /* (I)Ljava/lang/StringBuilder; */)
539     UNIMPLEMENTED_CASE(StringBuilderAppendLong /* (J)Ljava/lang/StringBuilder; */)
540     UNIMPLEMENTED_CASE(StringBuilderAppendFloat /* (F)Ljava/lang/StringBuilder; */)
541     UNIMPLEMENTED_CASE(StringBuilderAppendDouble /* (D)Ljava/lang/StringBuilder; */)
542     UNIMPLEMENTED_CASE(StringBuilderLength /* ()I */)
543     UNIMPLEMENTED_CASE(StringBuilderToString /* ()Ljava/lang/String; */)
544     UNIMPLEMENTED_CASE(UnsafeCASInt /* (Ljava/lang/Object;JII)Z */)
545     UNIMPLEMENTED_CASE(UnsafeCASLong /* (Ljava/lang/Object;JJJ)Z */)
546     UNIMPLEMENTED_CASE(UnsafeCASObject /* (Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z */)
547     UNIMPLEMENTED_CASE(UnsafeGet /* (Ljava/lang/Object;J)I */)
548     UNIMPLEMENTED_CASE(UnsafeGetVolatile /* (Ljava/lang/Object;J)I */)
549     UNIMPLEMENTED_CASE(UnsafeGetObject /* (Ljava/lang/Object;J)Ljava/lang/Object; */)
550     UNIMPLEMENTED_CASE(UnsafeGetObjectVolatile /* (Ljava/lang/Object;J)Ljava/lang/Object; */)
551     UNIMPLEMENTED_CASE(UnsafeGetLong /* (Ljava/lang/Object;J)J */)
552     UNIMPLEMENTED_CASE(UnsafeGetLongVolatile /* (Ljava/lang/Object;J)J */)
553     UNIMPLEMENTED_CASE(UnsafePut /* (Ljava/lang/Object;JI)V */)
554     UNIMPLEMENTED_CASE(UnsafePutOrdered /* (Ljava/lang/Object;JI)V */)
555     UNIMPLEMENTED_CASE(UnsafePutVolatile /* (Ljava/lang/Object;JI)V */)
556     UNIMPLEMENTED_CASE(UnsafePutObject /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
557     UNIMPLEMENTED_CASE(UnsafePutObjectOrdered /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
558     UNIMPLEMENTED_CASE(UnsafePutObjectVolatile /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
559     UNIMPLEMENTED_CASE(UnsafePutLong /* (Ljava/lang/Object;JJ)V */)
560     UNIMPLEMENTED_CASE(UnsafePutLongOrdered /* (Ljava/lang/Object;JJ)V */)
561     UNIMPLEMENTED_CASE(UnsafePutLongVolatile /* (Ljava/lang/Object;JJ)V */)
562     UNIMPLEMENTED_CASE(UnsafeGetAndAddInt /* (Ljava/lang/Object;JI)I */)
563     UNIMPLEMENTED_CASE(UnsafeGetAndAddLong /* (Ljava/lang/Object;JJ)J */)
564     UNIMPLEMENTED_CASE(UnsafeGetAndSetInt /* (Ljava/lang/Object;JI)I */)
565     UNIMPLEMENTED_CASE(UnsafeGetAndSetLong /* (Ljava/lang/Object;JJ)J */)
566     UNIMPLEMENTED_CASE(UnsafeGetAndSetObject /* (Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object; */)
567     UNIMPLEMENTED_CASE(UnsafeLoadFence /* ()V */)
568     UNIMPLEMENTED_CASE(UnsafeStoreFence /* ()V */)
569     UNIMPLEMENTED_CASE(UnsafeFullFence /* ()V */)
570     UNIMPLEMENTED_CASE(ReferenceGetReferent /* ()Ljava/lang/Object; */)
571     UNIMPLEMENTED_CASE(IntegerValueOf /* (I)Ljava/lang/Integer; */)
572     UNIMPLEMENTED_CASE(ThreadInterrupted /* ()Z */)
573     UNIMPLEMENTED_CASE(CRC32Update /* (II)I */)
574     UNIMPLEMENTED_CASE(CRC32UpdateBytes /* (I[BII)I */)
575     UNIMPLEMENTED_CASE(CRC32UpdateByteBuffer /* (IJII)I */)
576     UNIMPLEMENTED_CASE(FP16ToFloat /* (S)F */)
577     UNIMPLEMENTED_CASE(FP16ToHalf /* (F)S */)
578     UNIMPLEMENTED_CASE(FP16Floor /* (S)S */)
579     UNIMPLEMENTED_CASE(FP16Ceil /* (S)S */)
580     UNIMPLEMENTED_CASE(FP16Rint /* (S)S */)
581     UNIMPLEMENTED_CASE(FP16Greater /* (SS)Z */)
582     UNIMPLEMENTED_CASE(FP16GreaterEquals /* (SS)Z */)
583     UNIMPLEMENTED_CASE(FP16Less /* (SS)Z */)
584     UNIMPLEMENTED_CASE(FP16LessEquals /* (SS)Z */)
585     INTRINSIC_CASE(VarHandleFullFence)
586     INTRINSIC_CASE(VarHandleAcquireFence)
587     INTRINSIC_CASE(VarHandleReleaseFence)
588     INTRINSIC_CASE(VarHandleLoadLoadFence)
589     INTRINSIC_CASE(VarHandleStoreStoreFence)
590     INTRINSIC_CASE(MethodHandleInvokeExact)
591     INTRINSIC_CASE(MethodHandleInvoke)
592     INTRINSIC_CASE(VarHandleCompareAndExchange)
593     INTRINSIC_CASE(VarHandleCompareAndExchangeAcquire)
594     INTRINSIC_CASE(VarHandleCompareAndExchangeRelease)
595     INTRINSIC_CASE(VarHandleCompareAndSet)
596     INTRINSIC_CASE(VarHandleGet)
597     INTRINSIC_CASE(VarHandleGetAcquire)
598     INTRINSIC_CASE(VarHandleGetAndAdd)
599     INTRINSIC_CASE(VarHandleGetAndAddAcquire)
600     INTRINSIC_CASE(VarHandleGetAndAddRelease)
601     INTRINSIC_CASE(VarHandleGetAndBitwiseAnd)
602     INTRINSIC_CASE(VarHandleGetAndBitwiseAndAcquire)
603     INTRINSIC_CASE(VarHandleGetAndBitwiseAndRelease)
604     INTRINSIC_CASE(VarHandleGetAndBitwiseOr)
605     INTRINSIC_CASE(VarHandleGetAndBitwiseOrAcquire)
606     INTRINSIC_CASE(VarHandleGetAndBitwiseOrRelease)
607     INTRINSIC_CASE(VarHandleGetAndBitwiseXor)
608     INTRINSIC_CASE(VarHandleGetAndBitwiseXorAcquire)
609     INTRINSIC_CASE(VarHandleGetAndBitwiseXorRelease)
610     INTRINSIC_CASE(VarHandleGetAndSet)
611     INTRINSIC_CASE(VarHandleGetAndSetAcquire)
612     INTRINSIC_CASE(VarHandleGetAndSetRelease)
613     INTRINSIC_CASE(VarHandleGetOpaque)
614     INTRINSIC_CASE(VarHandleGetVolatile)
615     INTRINSIC_CASE(VarHandleSet)
616     INTRINSIC_CASE(VarHandleSetOpaque)
617     INTRINSIC_CASE(VarHandleSetRelease)
618     INTRINSIC_CASE(VarHandleSetVolatile)
619     INTRINSIC_CASE(VarHandleWeakCompareAndSet)
620     INTRINSIC_CASE(VarHandleWeakCompareAndSetAcquire)
621     INTRINSIC_CASE(VarHandleWeakCompareAndSetPlain)
622     INTRINSIC_CASE(VarHandleWeakCompareAndSetRelease)
623     case Intrinsics::kNone:
624       res = false;
625       break;
626     // Note: no default case to ensure we catch any newly added intrinsics.
627   }
628   return res;
629 }
630 
631 }  // namespace interpreter
632 }  // namespace art
633