Home | History | Annotate | Download | only in interpreter
      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 "compiler/intrinsics_enum.h"
     20 #include "dex_instruction.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(I)I
     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_JJ_INTRINSIC(MterpLongRotateRight, (Rot<int64_t, false>), SetJ);
    120 
    121 // java.lang.Long.rotateLeft(JI)J
    122 BINARY_JJ_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
    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   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
    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   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)             \
    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   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   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
    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   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
    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   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 
    326 // Macro to help keep track of what's left to implement.
    327 #define UNIMPLEMENTED_CASE(name)    \
    328     case Intrinsics::k##name:       \
    329       res = false;                  \
    330       break;
    331 
    332 #define INTRINSIC_CASE(name)                                           \
    333     case Intrinsics::k##name:                                          \
    334       res = Mterp##name(shadow_frame, inst, inst_data, result_register); \
    335       break;
    336 
    337 bool MterpHandleIntrinsic(ShadowFrame* shadow_frame,
    338                           ArtMethod* const called_method,
    339                           const Instruction* inst,
    340                           uint16_t inst_data,
    341                           JValue* result_register)
    342     REQUIRES_SHARED(Locks::mutator_lock_) {
    343   Intrinsics intrinsic = static_cast<Intrinsics>(called_method->GetIntrinsic());
    344   bool res = false;  // Assume failure
    345   switch (intrinsic) {
    346     UNIMPLEMENTED_CASE(DoubleDoubleToRawLongBits /* (D)J */)
    347     UNIMPLEMENTED_CASE(DoubleDoubleToLongBits /* (D)J */)
    348     UNIMPLEMENTED_CASE(DoubleIsInfinite /* (D)Z */)
    349     UNIMPLEMENTED_CASE(DoubleIsNaN /* (D)Z */)
    350     UNIMPLEMENTED_CASE(DoubleLongBitsToDouble /* (J)D */)
    351     UNIMPLEMENTED_CASE(FloatFloatToRawIntBits /* (F)I */)
    352     UNIMPLEMENTED_CASE(FloatFloatToIntBits /* (F)I */)
    353     UNIMPLEMENTED_CASE(FloatIsInfinite /* (F)Z */)
    354     UNIMPLEMENTED_CASE(FloatIsNaN /* (F)Z */)
    355     UNIMPLEMENTED_CASE(FloatIntBitsToFloat /* (I)F */)
    356     INTRINSIC_CASE(IntegerReverse)
    357     INTRINSIC_CASE(IntegerReverseBytes)
    358     INTRINSIC_CASE(IntegerBitCount)
    359     INTRINSIC_CASE(IntegerCompare)
    360     INTRINSIC_CASE(IntegerHighestOneBit)
    361     INTRINSIC_CASE(IntegerLowestOneBit)
    362     INTRINSIC_CASE(IntegerNumberOfLeadingZeros)
    363     INTRINSIC_CASE(IntegerNumberOfTrailingZeros)
    364     INTRINSIC_CASE(IntegerRotateRight)
    365     INTRINSIC_CASE(IntegerRotateLeft)
    366     INTRINSIC_CASE(IntegerSignum)
    367     INTRINSIC_CASE(LongReverse)
    368     INTRINSIC_CASE(LongReverseBytes)
    369     INTRINSIC_CASE(LongBitCount)
    370     INTRINSIC_CASE(LongCompare)
    371     INTRINSIC_CASE(LongHighestOneBit)
    372     INTRINSIC_CASE(LongLowestOneBit)
    373     INTRINSIC_CASE(LongNumberOfLeadingZeros)
    374     INTRINSIC_CASE(LongNumberOfTrailingZeros)
    375     INTRINSIC_CASE(LongRotateRight)
    376     INTRINSIC_CASE(LongRotateLeft)
    377     INTRINSIC_CASE(LongSignum)
    378     INTRINSIC_CASE(ShortReverseBytes)
    379     INTRINSIC_CASE(MathAbsDouble)
    380     INTRINSIC_CASE(MathAbsFloat)
    381     INTRINSIC_CASE(MathAbsLong)
    382     INTRINSIC_CASE(MathAbsInt)
    383     UNIMPLEMENTED_CASE(MathMinDoubleDouble /* (DD)D */)
    384     UNIMPLEMENTED_CASE(MathMinFloatFloat /* (FF)F */)
    385     INTRINSIC_CASE(MathMinLongLong)
    386     INTRINSIC_CASE(MathMinIntInt)
    387     UNIMPLEMENTED_CASE(MathMaxDoubleDouble /* (DD)D */)
    388     UNIMPLEMENTED_CASE(MathMaxFloatFloat /* (FF)F */)
    389     INTRINSIC_CASE(MathMaxLongLong)
    390     INTRINSIC_CASE(MathMaxIntInt)
    391     INTRINSIC_CASE(MathCos)
    392     INTRINSIC_CASE(MathSin)
    393     INTRINSIC_CASE(MathAcos)
    394     INTRINSIC_CASE(MathAsin)
    395     INTRINSIC_CASE(MathAtan)
    396     UNIMPLEMENTED_CASE(MathAtan2 /* (DD)D */)
    397     UNIMPLEMENTED_CASE(MathCbrt /* (D)D */)
    398     UNIMPLEMENTED_CASE(MathCosh /* (D)D */)
    399     UNIMPLEMENTED_CASE(MathExp /* (D)D */)
    400     UNIMPLEMENTED_CASE(MathExpm1 /* (D)D */)
    401     UNIMPLEMENTED_CASE(MathHypot /* (DD)D */)
    402     UNIMPLEMENTED_CASE(MathLog /* (D)D */)
    403     UNIMPLEMENTED_CASE(MathLog10 /* (D)D */)
    404     UNIMPLEMENTED_CASE(MathNextAfter /* (DD)D */)
    405     UNIMPLEMENTED_CASE(MathSinh /* (D)D */)
    406     INTRINSIC_CASE(MathTan)
    407     UNIMPLEMENTED_CASE(MathTanh /* (D)D */)
    408     INTRINSIC_CASE(MathSqrt)
    409     INTRINSIC_CASE(MathCeil)
    410     INTRINSIC_CASE(MathFloor)
    411     UNIMPLEMENTED_CASE(MathRint /* (D)D */)
    412     UNIMPLEMENTED_CASE(MathRoundDouble /* (D)J */)
    413     UNIMPLEMENTED_CASE(MathRoundFloat /* (F)I */)
    414     UNIMPLEMENTED_CASE(SystemArrayCopyChar /* ([CI[CII)V */)
    415     UNIMPLEMENTED_CASE(SystemArrayCopy /* (Ljava/lang/Object;ILjava/lang/Object;II)V */)
    416     UNIMPLEMENTED_CASE(ThreadCurrentThread /* ()Ljava/lang/Thread; */)
    417     UNIMPLEMENTED_CASE(MemoryPeekByte /* (J)B */)
    418     UNIMPLEMENTED_CASE(MemoryPeekIntNative /* (J)I */)
    419     UNIMPLEMENTED_CASE(MemoryPeekLongNative /* (J)J */)
    420     UNIMPLEMENTED_CASE(MemoryPeekShortNative /* (J)S */)
    421     UNIMPLEMENTED_CASE(MemoryPokeByte /* (JB)V */)
    422     UNIMPLEMENTED_CASE(MemoryPokeIntNative /* (JI)V */)
    423     UNIMPLEMENTED_CASE(MemoryPokeLongNative /* (JJ)V */)
    424     UNIMPLEMENTED_CASE(MemoryPokeShortNative /* (JS)V */)
    425     INTRINSIC_CASE(StringCharAt)
    426     INTRINSIC_CASE(StringCompareTo)
    427     INTRINSIC_CASE(StringEquals)
    428     INTRINSIC_CASE(StringGetCharsNoCheck)
    429     INTRINSIC_CASE(StringIndexOf)
    430     INTRINSIC_CASE(StringIndexOfAfter)
    431     UNIMPLEMENTED_CASE(StringStringIndexOf /* (Ljava/lang/String;)I */)
    432     UNIMPLEMENTED_CASE(StringStringIndexOfAfter /* (Ljava/lang/String;I)I */)
    433     INTRINSIC_CASE(StringIsEmpty)
    434     INTRINSIC_CASE(StringLength)
    435     UNIMPLEMENTED_CASE(StringNewStringFromBytes /* ([BIII)Ljava/lang/String; */)
    436     UNIMPLEMENTED_CASE(StringNewStringFromChars /* (II[C)Ljava/lang/String; */)
    437     UNIMPLEMENTED_CASE(StringNewStringFromString /* (Ljava/lang/String;)Ljava/lang/String; */)
    438     UNIMPLEMENTED_CASE(StringBufferAppend /* (Ljava/lang/String;)Ljava/lang/StringBuffer; */)
    439     UNIMPLEMENTED_CASE(StringBufferLength /* ()I */)
    440     UNIMPLEMENTED_CASE(StringBufferToString /* ()Ljava/lang/String; */)
    441     UNIMPLEMENTED_CASE(StringBuilderAppend /* (Ljava/lang/String;)Ljava/lang/StringBuilder; */)
    442     UNIMPLEMENTED_CASE(StringBuilderLength /* ()I */)
    443     UNIMPLEMENTED_CASE(StringBuilderToString /* ()Ljava/lang/String; */)
    444     UNIMPLEMENTED_CASE(UnsafeCASInt /* (Ljava/lang/Object;JII)Z */)
    445     UNIMPLEMENTED_CASE(UnsafeCASLong /* (Ljava/lang/Object;JJJ)Z */)
    446     UNIMPLEMENTED_CASE(UnsafeCASObject /* (Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z */)
    447     UNIMPLEMENTED_CASE(UnsafeGet /* (Ljava/lang/Object;J)I */)
    448     UNIMPLEMENTED_CASE(UnsafeGetVolatile /* (Ljava/lang/Object;J)I */)
    449     UNIMPLEMENTED_CASE(UnsafeGetObject /* (Ljava/lang/Object;J)Ljava/lang/Object; */)
    450     UNIMPLEMENTED_CASE(UnsafeGetObjectVolatile /* (Ljava/lang/Object;J)Ljava/lang/Object; */)
    451     UNIMPLEMENTED_CASE(UnsafeGetLong /* (Ljava/lang/Object;J)J */)
    452     UNIMPLEMENTED_CASE(UnsafeGetLongVolatile /* (Ljava/lang/Object;J)J */)
    453     UNIMPLEMENTED_CASE(UnsafePut /* (Ljava/lang/Object;JI)V */)
    454     UNIMPLEMENTED_CASE(UnsafePutOrdered /* (Ljava/lang/Object;JI)V */)
    455     UNIMPLEMENTED_CASE(UnsafePutVolatile /* (Ljava/lang/Object;JI)V */)
    456     UNIMPLEMENTED_CASE(UnsafePutObject /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
    457     UNIMPLEMENTED_CASE(UnsafePutObjectOrdered /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
    458     UNIMPLEMENTED_CASE(UnsafePutObjectVolatile /* (Ljava/lang/Object;JLjava/lang/Object;)V */)
    459     UNIMPLEMENTED_CASE(UnsafePutLong /* (Ljava/lang/Object;JJ)V */)
    460     UNIMPLEMENTED_CASE(UnsafePutLongOrdered /* (Ljava/lang/Object;JJ)V */)
    461     UNIMPLEMENTED_CASE(UnsafePutLongVolatile /* (Ljava/lang/Object;JJ)V */)
    462     UNIMPLEMENTED_CASE(UnsafeGetAndAddInt /* (Ljava/lang/Object;JI)I */)
    463     UNIMPLEMENTED_CASE(UnsafeGetAndAddLong /* (Ljava/lang/Object;JJ)J */)
    464     UNIMPLEMENTED_CASE(UnsafeGetAndSetInt /* (Ljava/lang/Object;JI)I */)
    465     UNIMPLEMENTED_CASE(UnsafeGetAndSetLong /* (Ljava/lang/Object;JJ)J */)
    466     UNIMPLEMENTED_CASE(UnsafeGetAndSetObject /* (Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object; */)
    467     UNIMPLEMENTED_CASE(UnsafeLoadFence /* ()V */)
    468     UNIMPLEMENTED_CASE(UnsafeStoreFence /* ()V */)
    469     UNIMPLEMENTED_CASE(UnsafeFullFence /* ()V */)
    470     UNIMPLEMENTED_CASE(ReferenceGetReferent /* ()Ljava/lang/Object; */)
    471     UNIMPLEMENTED_CASE(IntegerValueOf /* (I)Ljava/lang/Integer; */)
    472     UNIMPLEMENTED_CASE(ThreadInterrupted /* ()Z */)
    473     case Intrinsics::kNone:
    474       res = false;
    475       break;
    476     // Note: no default case to ensure we catch any newly added intrinsics.
    477   }
    478   return res;
    479 }
    480 
    481 }  // namespace interpreter
    482 }  // namespace art
    483