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