• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2015 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 "unstarted_runtime_test.h"
18  
19  #include <limits>
20  #include <locale>
21  
22  #include "base/casts.h"
23  #include "base/memory_tool.h"
24  #include "base/pointer_size.h"
25  #include "class_linker.h"
26  #include "class_root-inl.h"
27  #include "common_runtime_test.h"
28  #include "common_throws.h"
29  #include "dex/descriptors_names.h"
30  #include "dex/dex_instruction.h"
31  #include "handle.h"
32  #include "handle_scope-inl.h"
33  #include "interpreter_common.h"
34  #include "mirror/array-alloc-inl.h"
35  #include "mirror/class-alloc-inl.h"
36  #include "mirror/class_loader.h"
37  #include "mirror/object-inl.h"
38  #include "mirror/object_array-alloc-inl.h"
39  #include "mirror/object_array-inl.h"
40  #include "mirror/string-inl.h"
41  #include "runtime.h"
42  #include "runtime_intrinsics.h"
43  #include "scoped_thread_state_change-inl.h"
44  #include "shadow_frame-inl.h"
45  #include "thread.h"
46  #include "unstarted_runtime_list.h"
47  
48  namespace art HIDDEN {
49  namespace interpreter {
50  
51  class UnstartedRuntimeTest : public UnstartedRuntimeTestBase {
52   protected:
53    // Helpers for ArrayCopy.
54    //
55    // Note: as we have to use handles, we use StackHandleScope to transfer data. Hardcode a size
56    //       of three everywhere. That is enough to test all cases.
57  
CreateObjectArray(Thread * self,ObjPtr<mirror::Class> component_type,const StackHandleScope<3> & data)58    static ObjPtr<mirror::ObjectArray<mirror::Object>> CreateObjectArray(
59        Thread* self,
60        ObjPtr<mirror::Class> component_type,
61        const StackHandleScope<3>& data)
62        REQUIRES_SHARED(Locks::mutator_lock_) {
63      Runtime* runtime = Runtime::Current();
64      ObjPtr<mirror::Class> array_type =
65          runtime->GetClassLinker()->FindArrayClass(self, component_type);
66      CHECK(array_type != nullptr);
67      ObjPtr<mirror::ObjectArray<mirror::Object>> result =
68          mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3);
69      CHECK(result != nullptr);
70      for (size_t i = 0; i < 3; ++i) {
71        result->Set(static_cast<int32_t>(i), data.GetReference(i));
72        CHECK(!self->IsExceptionPending());
73      }
74      return result;
75    }
76  
CheckObjectArray(ObjPtr<mirror::ObjectArray<mirror::Object>> array,const StackHandleScope<3> & data)77    static void CheckObjectArray(ObjPtr<mirror::ObjectArray<mirror::Object>> array,
78                                 const StackHandleScope<3>& data)
79        REQUIRES_SHARED(Locks::mutator_lock_) {
80      CHECK_EQ(array->GetLength(), 3);
81      CHECK_EQ(data.Size(), 3U);
82      for (size_t i = 0; i < 3; ++i) {
83        EXPECT_OBJ_PTR_EQ(data.GetReference(i), array->Get(static_cast<int32_t>(i))) << i;
84      }
85    }
86  
RunArrayCopy(Thread * self,ShadowFrame * tmp,bool expect_exception,ObjPtr<mirror::ObjectArray<mirror::Object>> src,int32_t src_pos,ObjPtr<mirror::ObjectArray<mirror::Object>> dst,int32_t dst_pos,int32_t length)87    void RunArrayCopy(Thread* self,
88                      ShadowFrame* tmp,
89                      bool expect_exception,
90                      ObjPtr<mirror::ObjectArray<mirror::Object>> src,
91                      int32_t src_pos,
92                      ObjPtr<mirror::ObjectArray<mirror::Object>> dst,
93                      int32_t dst_pos,
94                      int32_t length)
95        REQUIRES_SHARED(Locks::mutator_lock_) {
96      JValue result;
97      tmp->SetVRegReference(0, src);
98      tmp->SetVReg(1, src_pos);
99      tmp->SetVRegReference(2, dst);
100      tmp->SetVReg(3, dst_pos);
101      tmp->SetVReg(4, length);
102      UnstartedSystemArraycopy(self, tmp, &result, 0);
103      bool exception_pending = self->IsExceptionPending();
104      EXPECT_EQ(exception_pending, expect_exception);
105      if (exception_pending) {
106        self->ClearException();
107      }
108    }
109  
RunArrayCopy(Thread * self,ShadowFrame * tmp,bool expect_exception,ObjPtr<mirror::Class> src_component_class,ObjPtr<mirror::Class> dst_component_class,const StackHandleScope<3> & src_data,int32_t src_pos,const StackHandleScope<3> & dst_data,int32_t dst_pos,int32_t length,const StackHandleScope<3> & expected_result)110    void RunArrayCopy(Thread* self,
111                      ShadowFrame* tmp,
112                      bool expect_exception,
113                      ObjPtr<mirror::Class> src_component_class,
114                      ObjPtr<mirror::Class> dst_component_class,
115                      const StackHandleScope<3>& src_data,
116                      int32_t src_pos,
117                      const StackHandleScope<3>& dst_data,
118                      int32_t dst_pos,
119                      int32_t length,
120                      const StackHandleScope<3>& expected_result)
121        REQUIRES_SHARED(Locks::mutator_lock_) {
122      StackHandleScope<3> hs_misc(self);
123      Handle<mirror::Class> dst_component_handle(hs_misc.NewHandle(dst_component_class));
124  
125      Handle<mirror::ObjectArray<mirror::Object>> src_handle(
126          hs_misc.NewHandle(CreateObjectArray(self, src_component_class, src_data)));
127  
128      Handle<mirror::ObjectArray<mirror::Object>> dst_handle(
129          hs_misc.NewHandle(CreateObjectArray(self, dst_component_handle.Get(), dst_data)));
130  
131      RunArrayCopy(self,
132                   tmp,
133                   expect_exception,
134                   src_handle.Get(),
135                   src_pos,
136                   dst_handle.Get(),
137                   dst_pos,
138                   length);
139      CheckObjectArray(dst_handle.Get(), expected_result);
140    }
141  
TestCeilFloor(bool ceil,Thread * self,ShadowFrame * tmp,double const test_pairs[][2],size_t num_pairs)142    void TestCeilFloor(bool ceil,
143                       Thread* self,
144                       ShadowFrame* tmp,
145                       double const test_pairs[][2],
146                       size_t num_pairs)
147        REQUIRES_SHARED(Locks::mutator_lock_) {
148      for (size_t i = 0; i < num_pairs; ++i) {
149        tmp->SetVRegDouble(0, test_pairs[i][0]);
150  
151        JValue result;
152        if (ceil) {
153          UnstartedMathCeil(self, tmp, &result, 0);
154        } else {
155          UnstartedMathFloor(self, tmp, &result, 0);
156        }
157  
158        ASSERT_FALSE(self->IsExceptionPending());
159  
160        // We want precise results.
161        int64_t result_int64t = bit_cast<int64_t, double>(result.GetD());
162        int64_t expect_int64t = bit_cast<int64_t, double>(test_pairs[i][1]);
163        EXPECT_EQ(expect_int64t, result_int64t) << result.GetD() << " vs " << test_pairs[i][1];
164      }
165    }
166  };
167  
TEST_F(UnstartedRuntimeTest,MemoryPeekByte)168  TEST_F(UnstartedRuntimeTest, MemoryPeekByte) {
169    Thread* self = Thread::Current();
170  
171    ScopedObjectAccess soa(self);
172    constexpr const uint8_t base_array[] = "abcdefghijklmnop";
173    constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
174    const uint8_t* base_ptr = base_array;
175  
176    JValue result;
177    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
178  
179    for (int32_t i = 0; i < kBaseLen; ++i) {
180      tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
181  
182      UnstartedMemoryPeekByte(self, tmp.get(), &result, 0);
183  
184      EXPECT_EQ(result.GetB(), static_cast<int8_t>(base_array[i]));
185    }
186  }
187  
TEST_F(UnstartedRuntimeTest,MemoryPeekShort)188  TEST_F(UnstartedRuntimeTest, MemoryPeekShort) {
189    Thread* self = Thread::Current();
190  
191    ScopedObjectAccess soa(self);
192    constexpr const uint8_t base_array[] = "abcdefghijklmnop";
193    constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
194    const uint8_t* base_ptr = base_array;
195  
196    JValue result;
197    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
198  
199    int32_t adjusted_length = kBaseLen - sizeof(int16_t);
200    for (int32_t i = 0; i < adjusted_length; ++i) {
201      tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
202  
203      UnstartedMemoryPeekShort(self, tmp.get(), &result, 0);
204  
205      using unaligned_short __attribute__((__aligned__(1))) = int16_t;
206      const unaligned_short* short_ptr = reinterpret_cast<const unaligned_short*>(base_ptr + i);
207      EXPECT_EQ(result.GetS(), *short_ptr);
208    }
209  }
210  
TEST_F(UnstartedRuntimeTest,MemoryPeekInt)211  TEST_F(UnstartedRuntimeTest, MemoryPeekInt) {
212    Thread* self = Thread::Current();
213  
214    ScopedObjectAccess soa(self);
215    constexpr const uint8_t base_array[] = "abcdefghijklmnop";
216    constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
217    const uint8_t* base_ptr = base_array;
218  
219    JValue result;
220    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
221  
222    int32_t adjusted_length = kBaseLen - sizeof(int32_t);
223    for (int32_t i = 0; i < adjusted_length; ++i) {
224      tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
225  
226      UnstartedMemoryPeekInt(self, tmp.get(), &result, 0);
227  
228      using unaligned_int __attribute__((__aligned__(1))) = int32_t;
229      const unaligned_int* int_ptr = reinterpret_cast<const unaligned_int*>(base_ptr + i);
230      EXPECT_EQ(result.GetI(), *int_ptr);
231    }
232  }
233  
TEST_F(UnstartedRuntimeTest,MemoryPeekLong)234  TEST_F(UnstartedRuntimeTest, MemoryPeekLong) {
235    Thread* self = Thread::Current();
236  
237    ScopedObjectAccess soa(self);
238    constexpr const uint8_t base_array[] = "abcdefghijklmnop";
239    constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
240    const uint8_t* base_ptr = base_array;
241  
242    JValue result;
243    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
244  
245    int32_t adjusted_length = kBaseLen - sizeof(int64_t);
246    for (int32_t i = 0; i < adjusted_length; ++i) {
247      tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
248  
249      UnstartedMemoryPeekLong(self, tmp.get(), &result, 0);
250  
251      using unaligned_long __attribute__((__aligned__(1))) = int64_t;
252      const unaligned_long* long_ptr = reinterpret_cast<const unaligned_long*>(base_ptr + i);
253      EXPECT_EQ(result.GetJ(), *long_ptr);
254    }
255  }
256  
TEST_F(UnstartedRuntimeTest,StringGetCharsNoCheck)257  TEST_F(UnstartedRuntimeTest, StringGetCharsNoCheck) {
258    Thread* self = Thread::Current();
259  
260    ScopedObjectAccess soa(self);
261    StackHandleScope<2> hs(self);
262    // TODO: Actual UTF.
263    constexpr const char base_string[] = "abcdefghijklmnop";
264    Handle<mirror::String> h_test_string(hs.NewHandle(
265        mirror::String::AllocFromModifiedUtf8(self, base_string)));
266    constexpr int32_t kBaseLen = sizeof(base_string) / sizeof(char) - 1;
267    Handle<mirror::CharArray> h_char_array(hs.NewHandle(
268        mirror::CharArray::Alloc(self, kBaseLen)));
269    // A buffer so we can make sure we only modify the elements targetted.
270    uint16_t buf[kBaseLen];
271  
272    JValue result;
273    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
274  
275    for (int32_t start_index = 0; start_index < kBaseLen; ++start_index) {
276      for (int32_t count = 0; count <= kBaseLen; ++count) {
277        for (int32_t trg_offset = 0; trg_offset < kBaseLen; ++trg_offset) {
278          // Only do it when in bounds.
279          if (start_index + count <= kBaseLen && trg_offset + count <= kBaseLen) {
280            tmp->SetVRegReference(0, h_test_string.Get());
281            tmp->SetVReg(1, start_index);
282            tmp->SetVReg(2, count);
283            tmp->SetVRegReference(3, h_char_array.Get());
284            tmp->SetVReg(3, trg_offset);
285  
286            // Copy the char_array into buf.
287            memcpy(buf, h_char_array->GetData(), kBaseLen * sizeof(uint16_t));
288  
289            UnstartedStringCharAt(self, tmp.get(), &result, 0);
290  
291            uint16_t* data = h_char_array->GetData();
292  
293            bool success = true;
294  
295            // First segment should be unchanged.
296            for (int32_t i = 0; i < trg_offset; ++i) {
297              success = success && (data[i] == buf[i]);
298            }
299            // Second segment should be a copy.
300            for (int32_t i = trg_offset; i < trg_offset + count; ++i) {
301              success = success && (data[i] == buf[i - trg_offset + start_index]);
302            }
303            // Third segment should be unchanged.
304            for (int32_t i = trg_offset + count; i < kBaseLen; ++i) {
305              success = success && (data[i] == buf[i]);
306            }
307  
308            EXPECT_TRUE(success);
309          }
310        }
311      }
312    }
313  }
314  
TEST_F(UnstartedRuntimeTest,StringCharAt)315  TEST_F(UnstartedRuntimeTest, StringCharAt) {
316    Thread* self = Thread::Current();
317  
318    ScopedObjectAccess soa(self);
319    // TODO: Actual UTF.
320    constexpr const char* base_string = "abcdefghijklmnop";
321    int32_t base_len = static_cast<int32_t>(strlen(base_string));
322    ObjPtr<mirror::String> test_string = mirror::String::AllocFromModifiedUtf8(self, base_string);
323  
324    JValue result;
325    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
326  
327    for (int32_t i = 0; i < base_len; ++i) {
328      tmp->SetVRegReference(0, test_string);
329      tmp->SetVReg(1, i);
330  
331      UnstartedStringCharAt(self, tmp.get(), &result, 0);
332  
333      EXPECT_EQ(result.GetI(), base_string[i]);
334    }
335  }
336  
TEST_F(UnstartedRuntimeTest,StringInit)337  TEST_F(UnstartedRuntimeTest, StringInit) {
338    Thread* self = Thread::Current();
339    ScopedObjectAccess soa(self);
340    ObjPtr<mirror::Class> klass = GetClassRoot<mirror::String>();
341    ArtMethod* method =
342        klass->FindConstructor("(Ljava/lang/String;)V", class_linker_->GetImagePointerSize());
343    ASSERT_TRUE(method != nullptr);
344  
345    // create instruction data for invoke-direct {v0, v1} of method with fake index
346    uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 };
347  
348    JValue result;
349    UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, method, 0);
350    const char* base_string = "hello_world";
351    StackHandleScope<2> hs(self);
352    Handle<mirror::String> string_arg =
353        hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, base_string));
354    Handle<mirror::String> reference_empty_string =
355        hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, ""));
356    shadow_frame->SetVRegReference(0, reference_empty_string.Get());
357    shadow_frame->SetVRegReference(1, string_arg.Get());
358  
359    ArtMethod* factory = WellKnownClasses::StringInitToStringFactory(method);
360    interpreter::DoCall<false>(factory,
361                               self,
362                               *shadow_frame,
363                               Instruction::At(inst_data),
364                               inst_data[0],
365                               /* string_init= */ true,
366                               &result);
367    ObjPtr<mirror::String> string_result = down_cast<mirror::String*>(result.GetL());
368    EXPECT_EQ(string_arg->GetLength(), string_result->GetLength());
369  
370    if (string_arg->IsCompressed() && string_result->IsCompressed()) {
371      EXPECT_EQ(memcmp(string_arg->GetValueCompressed(), string_result->GetValueCompressed(),
372                       string_arg->GetLength() * sizeof(uint8_t)), 0);
373    } else if (!string_arg->IsCompressed() && !string_result->IsCompressed()) {
374      EXPECT_EQ(memcmp(string_arg->GetValue(), string_result->GetValue(),
375                       string_arg->GetLength() * sizeof(uint16_t)), 0);
376    } else {
377      bool equal = true;
378      for (int i = 0; i < string_arg->GetLength(); ++i) {
379        if (string_arg->CharAt(i) != string_result->CharAt(i)) {
380          equal = false;
381          break;
382        }
383      }
384      EXPECT_EQ(equal, true);
385    }
386  }
387  
388  // Tests the exceptions that should be checked before modifying the destination.
389  // (Doesn't check the object vs primitive case ATM.)
TEST_F(UnstartedRuntimeTest,SystemArrayCopyObjectArrayTestExceptions)390  TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTestExceptions) {
391    Thread* self = Thread::Current();
392    ScopedObjectAccess soa(self);
393    JValue result;
394    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
395  
396    // Note: all tests are not GC safe. Assume there's no GC running here with the few objects we
397    //       allocate.
398    StackHandleScope<3> hs_misc(self);
399    Handle<mirror::Class> object_class(hs_misc.NewHandle(GetClassRoot<mirror::Object>()));
400  
401    StackHandleScope<3> hs_data(self);
402    hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
403    hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
404    hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
405  
406    Handle<mirror::ObjectArray<mirror::Object>> array(
407        hs_misc.NewHandle(CreateObjectArray(self, object_class.Get(), hs_data)));
408  
409    RunArrayCopy(self, tmp.get(), true, array.Get(), -1, array.Get(), 0, 0);
410    RunArrayCopy(self, tmp.get(), true, array.Get(), 0, array.Get(), -1, 0);
411    RunArrayCopy(self, tmp.get(), true, array.Get(), 0, array.Get(), 0, -1);
412    RunArrayCopy(self, tmp.get(), true, array.Get(), 0, array.Get(), 0, 4);
413    RunArrayCopy(self, tmp.get(), true, array.Get(), 0, array.Get(), 1, 3);
414    RunArrayCopy(self, tmp.get(), true, array.Get(), 1, array.Get(), 0, 3);
415  
416    Handle<mirror::ObjectArray<mirror::Object>> class_as_array =
417        hs_misc.NewHandle(reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(object_class.Get()));
418    RunArrayCopy(self, tmp.get(), true, class_as_array.Get(), 0, array.Get(), 0, 0);
419    RunArrayCopy(self, tmp.get(), true, array.Get(), 0, class_as_array.Get(), 0, 0);
420  }
421  
TEST_F(UnstartedRuntimeTest,SystemArrayCopyObjectArrayTest)422  TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
423    Thread* self = Thread::Current();
424    ScopedObjectAccess soa(self);
425    JValue result;
426    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
427  
428    // Simple test:
429    // [1,2,3]{1 @ 2} into [4,5,6] = [4,2,6]
430    {
431      StackHandleScope<3> hs_src(self);
432      hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
433      hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
434      hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
435  
436      StackHandleScope<3> hs_dst(self);
437      hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
438      hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
439      hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
440  
441      StackHandleScope<3> hs_expected(self);
442      hs_expected.NewHandle(hs_dst.GetReference(0));
443      hs_expected.NewHandle(hs_dst.GetReference(1));
444      hs_expected.NewHandle(hs_src.GetReference(1));
445  
446      RunArrayCopy(self,
447                   tmp.get(),
448                   false,
449                   GetClassRoot<mirror::Object>(),
450                   GetClassRoot<mirror::Object>(),
451                   hs_src,
452                   1,
453                   hs_dst,
454                   2,
455                   1,
456                   hs_expected);
457    }
458  
459    // Simple test:
460    // [1,2,3]{1 @ 1} into [4,5,6] = [4,2,6]  (with dst String[])
461    {
462      StackHandleScope<3> hs_src(self);
463      hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
464      hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
465      hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
466  
467      StackHandleScope<3> hs_dst(self);
468      hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
469      hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
470      hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
471  
472      StackHandleScope<3> hs_expected(self);
473      hs_expected.NewHandle(hs_dst.GetReference(0));
474      hs_expected.NewHandle(hs_src.GetReference(1));
475      hs_expected.NewHandle(hs_dst.GetReference(2));
476  
477      RunArrayCopy(self,
478                   tmp.get(),
479                   false,
480                   GetClassRoot<mirror::Object>(),
481                   GetClassRoot<mirror::String>(),
482                   hs_src,
483                   1,
484                   hs_dst,
485                   1,
486                   1,
487                   hs_expected);
488    }
489  
490    // Simple test:
491    // [1,*,3] into [4,5,6] = [1,5,6] + exc
492    {
493      StackHandleScope<3> hs_src(self);
494      hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
495      hs_src.NewHandle(GetClassRoot<mirror::String>());
496      hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
497  
498      StackHandleScope<3> hs_dst(self);
499      hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
500      hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
501      hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
502  
503      StackHandleScope<3> hs_expected(self);
504      hs_expected.NewHandle(hs_src.GetReference(0));
505      hs_expected.NewHandle(hs_dst.GetReference(1));
506      hs_expected.NewHandle(hs_dst.GetReference(2));
507  
508      RunArrayCopy(self,
509                   tmp.get(),
510                   true,
511                   GetClassRoot<mirror::Object>(),
512                   GetClassRoot<mirror::String>(),
513                   hs_src,
514                   0,
515                   hs_dst,
516                   0,
517                   3,
518                   hs_expected);
519    }
520  }
521  
TEST_F(UnstartedRuntimeTest,IntegerParseIntTest)522  TEST_F(UnstartedRuntimeTest, IntegerParseIntTest) {
523    Thread* self = Thread::Current();
524    ScopedObjectAccess soa(self);
525  
526    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
527  
528    // Test string. Should be valid, and between minimal values of LONG_MIN and LONG_MAX (for all
529    // suffixes).
530    constexpr const char* test_string = "-2147483646";
531    constexpr int32_t test_values[] = {
532                  6,
533                 46,
534                646,
535               3646,
536              83646,
537             483646,
538            7483646,
539           47483646,
540          147483646,
541         2147483646,
542        -2147483646
543    };
544  
545    static_assert(arraysize(test_values) == 11U, "test_values");
546    CHECK_EQ(strlen(test_string), 11U);
547  
548    for (size_t i = 0; i <= 10; ++i) {
549      const char* test_value = &test_string[10 - i];
550  
551      StackHandleScope<1> hs_str(self);
552      Handle<mirror::String> h_str(
553          hs_str.NewHandle(mirror::String::AllocFromModifiedUtf8(self, test_value)));
554      ASSERT_NE(h_str.Get(), nullptr);
555      ASSERT_FALSE(self->IsExceptionPending());
556  
557      tmp->SetVRegReference(0, h_str.Get());
558  
559      JValue result;
560      UnstartedIntegerParseInt(self, tmp.get(), &result, 0);
561  
562      ASSERT_FALSE(self->IsExceptionPending());
563      EXPECT_EQ(result.GetI(), test_values[i]);
564    }
565  }
566  
567  // Right now the same as Integer.Parse
TEST_F(UnstartedRuntimeTest,LongParseLongTest)568  TEST_F(UnstartedRuntimeTest, LongParseLongTest) {
569    Thread* self = Thread::Current();
570    ScopedObjectAccess soa(self);
571  
572    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
573  
574    // Test string. Should be valid, and between minimal values of LONG_MIN and LONG_MAX (for all
575    // suffixes).
576    constexpr const char* test_string = "-2147483646";
577    constexpr int64_t test_values[] = {
578                  6,
579                 46,
580                646,
581               3646,
582              83646,
583             483646,
584            7483646,
585           47483646,
586          147483646,
587         2147483646,
588        -2147483646
589    };
590  
591    static_assert(arraysize(test_values) == 11U, "test_values");
592    CHECK_EQ(strlen(test_string), 11U);
593  
594    for (size_t i = 0; i <= 10; ++i) {
595      const char* test_value = &test_string[10 - i];
596  
597      StackHandleScope<1> hs_str(self);
598      Handle<mirror::String> h_str(
599          hs_str.NewHandle(mirror::String::AllocFromModifiedUtf8(self, test_value)));
600      ASSERT_NE(h_str.Get(), nullptr);
601      ASSERT_FALSE(self->IsExceptionPending());
602  
603      tmp->SetVRegReference(0, h_str.Get());
604  
605      JValue result;
606      UnstartedLongParseLong(self, tmp.get(), &result, 0);
607  
608      ASSERT_FALSE(self->IsExceptionPending());
609      EXPECT_EQ(result.GetJ(), test_values[i]);
610    }
611  }
612  
TEST_F(UnstartedRuntimeTest,Ceil)613  TEST_F(UnstartedRuntimeTest, Ceil) {
614    Thread* self = Thread::Current();
615    ScopedObjectAccess soa(self);
616  
617    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
618  
619    constexpr double nan = std::numeric_limits<double>::quiet_NaN();
620    constexpr double inf = std::numeric_limits<double>::infinity();
621    constexpr double ld1 = static_cast<double>((UINT64_C(1) << 53) - 1);
622    constexpr double ld2 = static_cast<double>(UINT64_C(1) << 55);
623    constexpr double test_pairs[][2] = {
624        { -0.0, -0.0 },
625        {  0.0,  0.0 },
626        { -0.5, -0.0 },
627        { -1.0, -1.0 },
628        {  0.5,  1.0 },
629        {  1.0,  1.0 },
630        {  nan,  nan },
631        {  inf,  inf },
632        { -inf, -inf },
633        {  ld1,  ld1 },
634        {  ld2,  ld2 }
635    };
636  
637    TestCeilFloor(/* ceil= */ true, self, tmp.get(), test_pairs, arraysize(test_pairs));
638  }
639  
TEST_F(UnstartedRuntimeTest,Floor)640  TEST_F(UnstartedRuntimeTest, Floor) {
641    Thread* self = Thread::Current();
642    ScopedObjectAccess soa(self);
643  
644    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
645  
646    constexpr double nan = std::numeric_limits<double>::quiet_NaN();
647    constexpr double inf = std::numeric_limits<double>::infinity();
648    constexpr double ld1 = static_cast<double>((UINT64_C(1) << 53) - 1);
649    constexpr double ld2 = static_cast<double>(UINT64_C(1) << 55);
650    constexpr double test_pairs[][2] = {
651        { -0.0, -0.0 },
652        {  0.0,  0.0 },
653        { -0.5, -1.0 },
654        { -1.0, -1.0 },
655        {  0.5,  0.0 },
656        {  1.0,  1.0 },
657        {  nan,  nan },
658        {  inf,  inf },
659        { -inf, -inf },
660        {  ld1,  ld1 },
661        {  ld2,  ld2 }
662    };
663  
664    TestCeilFloor(/* ceil= */ false, self, tmp.get(), test_pairs, arraysize(test_pairs));
665  }
666  
TEST_F(UnstartedRuntimeTest,ToLowerUpper)667  TEST_F(UnstartedRuntimeTest, ToLowerUpper) {
668    Thread* self = Thread::Current();
669    ScopedObjectAccess soa(self);
670  
671    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
672  
673    std::locale c_locale("C");
674  
675    // Check ASCII.
676    for (uint32_t i = 0; i < 128; ++i) {
677      bool c_upper = std::isupper(static_cast<char>(i), c_locale);
678      bool c_lower = std::islower(static_cast<char>(i), c_locale);
679      EXPECT_FALSE(c_upper && c_lower) << i;
680  
681      // Check toLowerCase.
682      {
683        JValue result;
684        tmp->SetVReg(0, static_cast<int32_t>(i));
685        UnstartedCharacterToLowerCase(self, tmp.get(), &result, 0);
686        ASSERT_FALSE(self->IsExceptionPending());
687        uint32_t lower_result = static_cast<uint32_t>(result.GetI());
688        if (c_lower) {
689          EXPECT_EQ(i, lower_result);
690        } else if (c_upper) {
691          EXPECT_EQ(static_cast<uint32_t>(std::tolower(static_cast<char>(i), c_locale)),
692                    lower_result);
693        } else {
694          EXPECT_EQ(i, lower_result);
695        }
696      }
697  
698      // Check toUpperCase.
699      {
700        JValue result2;
701        tmp->SetVReg(0, static_cast<int32_t>(i));
702        UnstartedCharacterToUpperCase(self, tmp.get(), &result2, 0);
703        ASSERT_FALSE(self->IsExceptionPending());
704        uint32_t upper_result = static_cast<uint32_t>(result2.GetI());
705        if (c_upper) {
706          EXPECT_EQ(i, upper_result);
707        } else if (c_lower) {
708          EXPECT_EQ(static_cast<uint32_t>(std::toupper(static_cast<char>(i), c_locale)),
709                    upper_result);
710        } else {
711          EXPECT_EQ(i, upper_result);
712        }
713      }
714    }
715  }
716  
TEST_F(UnstartedRuntimeTest,Sin)717  TEST_F(UnstartedRuntimeTest, Sin) {
718    Thread* self = Thread::Current();
719    ScopedObjectAccess soa(self);
720  
721    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
722  
723    // Test an important value, PI/6. That's the one we see in practice.
724    constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365);
725    tmp->SetVRegLong(0, static_cast<int64_t>(lvalue));
726  
727    JValue result;
728    UnstartedMathSin(self, tmp.get(), &result, 0);
729  
730    const uint64_t lresult = static_cast<uint64_t>(result.GetJ());
731    EXPECT_EQ(UINT64_C(0x3fdfffffffffffff), lresult);
732  }
733  
TEST_F(UnstartedRuntimeTest,Cos)734  TEST_F(UnstartedRuntimeTest, Cos) {
735    Thread* self = Thread::Current();
736    ScopedObjectAccess soa(self);
737  
738    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
739  
740    // Test an important value, PI/6. That's the one we see in practice.
741    constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365);
742    tmp->SetVRegLong(0, static_cast<int64_t>(lvalue));
743  
744    JValue result;
745    UnstartedMathCos(self, tmp.get(), &result, 0);
746  
747    const uint64_t lresult = static_cast<uint64_t>(result.GetJ());
748    EXPECT_EQ(UINT64_C(0x3febb67ae8584cab), lresult);
749  }
750  
TEST_F(UnstartedRuntimeTest,Pow)751  TEST_F(UnstartedRuntimeTest, Pow) {
752    Thread* self = Thread::Current();
753    ScopedObjectAccess soa(self);
754  
755    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
756  
757    // Test an important pair.
758    constexpr uint64_t lvalue1 = UINT64_C(0x4079000000000000);
759    constexpr uint64_t lvalue2 = UINT64_C(0xbfe6db6dc0000000);
760  
761    tmp->SetVRegLong(0, static_cast<int64_t>(lvalue1));
762    tmp->SetVRegLong(2, static_cast<int64_t>(lvalue2));
763  
764    JValue result;
765    UnstartedMathPow(self, tmp.get(), &result, 0);
766  
767    const uint64_t lresult = static_cast<uint64_t>(result.GetJ());
768    EXPECT_EQ(UINT64_C(0x3f8c5c51326aa7ee), lresult);
769  }
770  
TEST_F(UnstartedRuntimeTest,IsAnonymousClass)771  TEST_F(UnstartedRuntimeTest, IsAnonymousClass) {
772    Thread* self = Thread::Current();
773    ScopedObjectAccess soa(self);
774  
775    JValue result;
776    UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0);
777  
778    ObjPtr<mirror::Class> class_klass = GetClassRoot<mirror::Class>();
779    shadow_frame->SetVRegReference(0, class_klass);
780    UnstartedClassIsAnonymousClass(self, shadow_frame.get(), &result, 0);
781    EXPECT_EQ(result.GetZ(), 0);
782  
783    jobject class_loader = LoadDex("Nested");
784    StackHandleScope<1> hs(soa.Self());
785    Handle<mirror::ClassLoader> loader(
786        hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
787    ObjPtr<mirror::Class> c = class_linker_->FindClass(soa.Self(), "LNested$1;", loader);
788    ASSERT_TRUE(c != nullptr);
789    shadow_frame->SetVRegReference(0, c);
790    UnstartedClassIsAnonymousClass(self, shadow_frame.get(), &result, 0);
791    EXPECT_EQ(result.GetZ(), 1);
792  }
793  
TEST_F(UnstartedRuntimeTest,GetDeclaringClass)794  TEST_F(UnstartedRuntimeTest, GetDeclaringClass) {
795    Thread* self = Thread::Current();
796    ScopedObjectAccess soa(self);
797  
798    JValue result;
799    UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0);
800  
801    jobject class_loader = LoadDex("Nested");
802    StackHandleScope<4> hs(self);
803    Handle<mirror::ClassLoader> loader(
804        hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
805  
806    Handle<mirror::Class> nested_klass(hs.NewHandle(
807        class_linker_->FindClass(soa.Self(), "LNested;", loader)));
808    Handle<mirror::Class> inner_klass(hs.NewHandle(
809        class_linker_->FindClass(soa.Self(), "LNested$Inner;", loader)));
810    Handle<mirror::Class> anon_klass(hs.NewHandle(
811        class_linker_->FindClass(soa.Self(), "LNested$1;", loader)));
812  
813    shadow_frame->SetVRegReference(0, nested_klass.Get());
814    UnstartedClassGetDeclaringClass(self, shadow_frame.get(), &result, 0);
815    EXPECT_EQ(result.GetL(), nullptr);
816  
817    shadow_frame->SetVRegReference(0, inner_klass.Get());
818    UnstartedClassGetDeclaringClass(self, shadow_frame.get(), &result, 0);
819    EXPECT_EQ(result.GetL(), nested_klass.Get());
820  
821    shadow_frame->SetVRegReference(0, anon_klass.Get());
822    UnstartedClassGetDeclaringClass(self, shadow_frame.get(), &result, 0);
823    EXPECT_EQ(result.GetL(), nullptr);
824  }
825  
TEST_F(UnstartedRuntimeTest,ThreadLocalGet)826  TEST_F(UnstartedRuntimeTest, ThreadLocalGet) {
827    Thread* self = Thread::Current();
828    ScopedObjectAccess soa(self);
829  
830    JValue result;
831    UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0);
832  
833    StackHandleScope<1> hs(self);
834  
835    // Positive test. See that We get something for float conversion.
836    {
837      Handle<mirror::Class> floating_decimal = hs.NewHandle(
838          class_linker_->FindClass(self,
839                                   "Ljdk/internal/math/FloatingDecimal;",
840                                   ScopedNullHandle<mirror::ClassLoader>()));
841      ASSERT_TRUE(floating_decimal != nullptr);
842      ASSERT_TRUE(class_linker_->EnsureInitialized(self, floating_decimal, true, true));
843  
844      ArtMethod* caller_method = floating_decimal->FindClassMethod(
845          "getBinaryToASCIIBuffer",
846          "()Ljdk/internal/math/FloatingDecimal$BinaryToASCIIBuffer;",
847          class_linker_->GetImagePointerSize());
848      // floating_decimal->DumpClass(LOG_STREAM(ERROR), mirror::Class::kDumpClassFullDetail);
849      ASSERT_TRUE(caller_method != nullptr);
850      ASSERT_TRUE(caller_method->IsDirect());
851      ASSERT_TRUE(caller_method->GetDeclaringClass() == floating_decimal.Get());
852      UniqueDeoptShadowFramePtr caller_frame = CreateShadowFrame(10, caller_method, 0);
853      shadow_frame->SetLink(caller_frame.get());
854  
855      UnstartedThreadLocalGet(self, shadow_frame.get(), &result, 0);
856      EXPECT_TRUE(result.GetL() != nullptr);
857      EXPECT_FALSE(self->IsExceptionPending());
858  
859      shadow_frame->ClearLink();
860    }
861  }
862  
TEST_F(UnstartedRuntimeTest,FloatConversion)863  TEST_F(UnstartedRuntimeTest, FloatConversion) {
864    Thread* self = Thread::Current();
865    ScopedObjectAccess soa(self);
866  
867    StackHandleScope<1> hs(self);
868    Handle<mirror::Class> double_class = hs.NewHandle(
869            class_linker_->FindClass(self,
870                                     "Ljava/lang/Double;",
871                                     ScopedNullHandle<mirror::ClassLoader>()));
872    ASSERT_TRUE(double_class != nullptr);
873    ASSERT_TRUE(class_linker_->EnsureInitialized(self, double_class, true, true));
874  
875    ArtMethod* method = double_class->FindClassMethod("toString",
876                                                      "(D)Ljava/lang/String;",
877                                                      class_linker_->GetImagePointerSize());
878    ASSERT_TRUE(method != nullptr);
879    ASSERT_TRUE(method->IsDirect());
880    ASSERT_TRUE(method->GetDeclaringClass() == double_class.Get());
881  
882    // create instruction data for invoke-direct {v0, v1} of method with fake index
883    uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 };
884  
885    JValue result;
886    UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, method, 0);
887  
888    shadow_frame->SetVRegDouble(0, 1.23);
889    interpreter::DoCall<false>(method,
890                               self,
891                               *shadow_frame,
892                               Instruction::At(inst_data),
893                               inst_data[0],
894                               /* string_init= */ false,
895                               &result);
896    ObjPtr<mirror::String> string_result = down_cast<mirror::String*>(result.GetL());
897    ASSERT_TRUE(string_result != nullptr);
898  
899    std::string mod_utf = string_result->ToModifiedUtf8();
900    EXPECT_EQ("1.23", mod_utf);
901  }
902  
TEST_F(UnstartedRuntimeTest,LogManager)903  TEST_F(UnstartedRuntimeTest, LogManager) {
904    Thread* self = Thread::Current();
905    ScopedObjectAccess soa(self);
906  
907    StackHandleScope<1> hs(self);
908    Handle<mirror::Class> log_manager_class = hs.NewHandle(class_linker_->FindClass(
909        self, "Ljava/util/logging/LogManager;", ScopedNullHandle<mirror::ClassLoader>()));
910    ASSERT_TRUE(log_manager_class.Get() != nullptr);
911    ASSERT_TRUE(class_linker_->EnsureInitialized(self, log_manager_class, true, true));
912  }
913  
914  class UnstartedClassForNameTest : public UnstartedRuntimeTest {
915   public:
916    template <typename T>
RunTest(T && runner)917    void RunTest(T&& runner) {
918      Thread* self = Thread::Current();
919      ScopedObjectAccess soa(self);
920  
921      // Ensure that Class is initialized.
922      CHECK(GetClassRoot<mirror::Class>()->IsInitialized());
923  
924      // A selection of classes from different core classpath components.
925      constexpr const char* kTestCases[] = {
926          "java.net.CookieManager",  // From libcore.
927          "dalvik.system.ClassExt",  // From libart.
928      };
929  
930      JValue result;
931      UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0);
932  
933      for (const char* name : kTestCases) {
934        ObjPtr<mirror::String> name_string = mirror::String::AllocFromModifiedUtf8(self, name);
935        CHECK(name_string != nullptr);
936        CHECK(!self->IsExceptionPending());
937  
938        runner(self, shadow_frame.get(), name_string, &result);
939  
940        CHECK(!self->IsExceptionPending()) << name << " " << self->GetException()->Dump();
941        CHECK(result.GetL() != nullptr) << name;
942      }
943    }
944  };
945  
TEST_F(UnstartedClassForNameTest,ClassForName)946  TEST_F(UnstartedClassForNameTest, ClassForName) {
947    auto runner = [](Thread* self,
948                     ShadowFrame* shadow_frame,
949                     ObjPtr<mirror::String> name,
950                     JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
951      shadow_frame->SetVRegReference(0, name);
952      UnstartedClassForName(self, shadow_frame, result, 0);
953    };
954    RunTest(runner);
955  }
956  
TEST_F(UnstartedClassForNameTest,ClassForNameLong)957  TEST_F(UnstartedClassForNameTest, ClassForNameLong) {
958    auto runner = [](Thread* self,
959                     ShadowFrame* shadow_frame,
960                     ObjPtr<mirror::String> name,
961                     JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
962      shadow_frame->SetVRegReference(0, name);
963      shadow_frame->SetVReg(1, 0);
964      shadow_frame->SetVRegReference(2, nullptr);
965      UnstartedClassForNameLong(self, shadow_frame, result, 0);
966    };
967    RunTest(runner);
968  }
969  
TEST_F(UnstartedClassForNameTest,ClassForNameLongWithClassLoader)970  TEST_F(UnstartedClassForNameTest, ClassForNameLongWithClassLoader) {
971    Thread* self = Thread::Current();
972    ScopedObjectAccess soa(self);
973  
974    StackHandleScope<1> hs(self);
975    Handle<mirror::ClassLoader> boot_cp = hs.NewHandle(GetBootClassLoader());
976  
977    auto runner = [&](Thread* th,
978                      ShadowFrame* shadow_frame,
979                      ObjPtr<mirror::String> name,
980                      JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
981      shadow_frame->SetVRegReference(0, name);
982      shadow_frame->SetVReg(1, 0);
983      shadow_frame->SetVRegReference(2, boot_cp.Get());
984      UnstartedClassForNameLong(th, shadow_frame, result, 0);
985    };
986    RunTest(runner);
987  }
988  
TEST_F(UnstartedRuntimeTest,ClassGetSignatureAnnotation)989  TEST_F(UnstartedRuntimeTest, ClassGetSignatureAnnotation) {
990    Thread* self = Thread::Current();
991    ScopedObjectAccess soa(self);
992  
993    StackHandleScope<1> hs(self);
994    Handle<mirror::Class> list_class = hs.NewHandle(
995        class_linker_->FindClass(self,
996                                 "Ljava/util/List;",
997                                 ScopedNullHandle<mirror::ClassLoader>()));
998    ASSERT_TRUE(list_class.Get() != nullptr);
999    ASSERT_TRUE(class_linker_->EnsureInitialized(self, list_class, true, true));
1000  
1001    JValue result;
1002    UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0);
1003  
1004    shadow_frame->SetVRegReference(0, list_class.Get());
1005    UnstartedClassGetSignatureAnnotation(self, shadow_frame.get(), &result, 0);
1006    ASSERT_TRUE(result.GetL() != nullptr);
1007    ASSERT_FALSE(self->IsExceptionPending());
1008  
1009    ASSERT_TRUE(result.GetL()->IsObjectArray());
1010    ObjPtr<mirror::ObjectArray<mirror::Object>> array =
1011        result.GetL()->AsObjectArray<mirror::Object>();
1012    std::ostringstream oss;
1013    for (int32_t i = 0; i != array->GetLength(); ++i) {
1014      ObjPtr<mirror::Object> elem = array->Get(i);
1015      ASSERT_TRUE(elem != nullptr);
1016      ASSERT_TRUE(elem->IsString());
1017      oss << elem->AsString()->ToModifiedUtf8();
1018    }
1019    std::string output_string = oss.str();
1020    ASSERT_EQ(output_string,
1021              "<E:Ljava/lang/Object;>Ljava/lang/Object;Ljava/util/SequencedCollection<TE;>;"
1022              "Ljava/util/Collection<TE;>;");
1023  }
1024  
TEST_F(UnstartedRuntimeTest,ConstructorNewInstance0)1025  TEST_F(UnstartedRuntimeTest, ConstructorNewInstance0) {
1026    Thread* self = Thread::Current();
1027    ScopedObjectAccess soa(self);
1028  
1029    StackHandleScope<4> hs(self);
1030  
1031    // Get Throwable.
1032    Handle<mirror::Class> throw_class = hs.NewHandle(GetClassRoot<mirror::Throwable>());
1033    ASSERT_TRUE(class_linker_->EnsureInitialized(self, throw_class, true, true));
1034  
1035    // Get an input object.
1036    Handle<mirror::String> input = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "abd"));
1037  
1038    // Find the constructor.
1039    PointerSize pointer_size = class_linker_->GetImagePointerSize();
1040    ArtMethod* throw_cons = throw_class->FindConstructor("(Ljava/lang/String;)V", pointer_size);
1041    ASSERT_TRUE(throw_cons != nullptr);
1042    Handle<mirror::Constructor> cons = hs.NewHandle((pointer_size == PointerSize::k64)
1043        ? mirror::Constructor::CreateFromArtMethod<PointerSize::k64>(self, throw_cons)
1044        : mirror::Constructor::CreateFromArtMethod<PointerSize::k32>(self, throw_cons));
1045    ASSERT_TRUE(cons != nullptr);
1046  
1047    Handle<mirror::ObjectArray<mirror::Object>> args = hs.NewHandle(
1048        mirror::ObjectArray<mirror::Object>::Alloc(
1049            self, GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker_), 1));
1050    ASSERT_TRUE(args != nullptr);
1051    args->Set(0, input.Get());
1052  
1053    // OK, we're ready now.
1054    JValue result;
1055    UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0);
1056    shadow_frame->SetVRegReference(0, cons.Get());
1057    shadow_frame->SetVRegReference(1, args.Get());
1058    UnstartedConstructorNewInstance0(self, shadow_frame.get(), &result, 0);
1059  
1060    ASSERT_TRUE(result.GetL() != nullptr);
1061    ASSERT_FALSE(self->IsExceptionPending());
1062  
1063    // Should be a new object.
1064    ASSERT_NE(result.GetL(), input.Get());
1065    // Should be of type Throwable.
1066    ASSERT_OBJ_PTR_EQ(GetClassRoot<mirror::Throwable>(), result.GetL()->GetClass());
1067    // Should have the right string.
1068    ObjPtr<mirror::String> result_msg =
1069        reinterpret_cast<mirror::Throwable*>(result.GetL())->GetDetailMessage();
1070    EXPECT_OBJ_PTR_EQ(input.Get(), result_msg);
1071  }
1072  
TEST_F(UnstartedRuntimeTest,IdentityHashCode)1073  TEST_F(UnstartedRuntimeTest, IdentityHashCode) {
1074    Thread* self = Thread::Current();
1075    ScopedObjectAccess soa(self);
1076    UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0);
1077  
1078    JValue result;
1079    UnstartedSystemIdentityHashCode(self, tmp.get(), &result, 0);
1080  
1081    EXPECT_EQ(0, result.GetI());
1082    ASSERT_FALSE(self->IsExceptionPending());
1083  
1084    ObjPtr<mirror::String> str = mirror::String::AllocFromModifiedUtf8(self, "abd");
1085    tmp->SetVRegReference(0, str);
1086    UnstartedSystemIdentityHashCode(self, tmp.get(), &result, 0);
1087    EXPECT_NE(0, result.GetI());
1088    EXPECT_EQ(str->IdentityHashCode(), result.GetI());
1089    ASSERT_FALSE(self->IsExceptionPending());
1090  }
1091  
1092  }  // namespace interpreter
1093  }  // namespace art
1094