blob: 1b5b665ed246a22633f725a5ffb786b8a46f236c [file] [log] [blame]
Andreas Gampe799681b2015-05-15 19:24:12 -07001/*
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.h"
18
Andreas Gampe89e3b482016-04-12 18:07:36 -070019#include <limits>
20
21#include "base/casts.h"
Andreas Gampe799681b2015-05-15 19:24:12 -070022#include "class_linker.h"
23#include "common_runtime_test.h"
Jeff Hao400ce002015-05-29 10:53:17 -070024#include "dex_instruction.h"
Andreas Gampe799681b2015-05-15 19:24:12 -070025#include "handle.h"
26#include "handle_scope-inl.h"
Jeff Hao400ce002015-05-29 10:53:17 -070027#include "interpreter/interpreter_common.h"
Andreas Gampe799681b2015-05-15 19:24:12 -070028#include "mirror/class_loader.h"
29#include "mirror/string-inl.h"
30#include "runtime.h"
31#include "scoped_thread_state_change.h"
32#include "thread.h"
33
34namespace art {
35namespace interpreter {
36
37class UnstartedRuntimeTest : public CommonRuntimeTest {
38 protected:
39 // Re-expose all UnstartedRuntime implementations so we don't need to declare a million
40 // test friends.
41
42 // Methods that intercept available libcore implementations.
43#define UNSTARTED_DIRECT(Name, SigIgnored) \
44 static void Unstarted ## Name(Thread* self, \
45 ShadowFrame* shadow_frame, \
46 JValue* result, \
47 size_t arg_offset) \
Mathieu Chartier90443472015-07-16 20:32:27 -070048 SHARED_REQUIRES(Locks::mutator_lock_) { \
Andreas Gampe799681b2015-05-15 19:24:12 -070049 interpreter::UnstartedRuntime::Unstarted ## Name(self, shadow_frame, result, arg_offset); \
50 }
51#include "unstarted_runtime_list.h"
52 UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
53#undef UNSTARTED_RUNTIME_DIRECT_LIST
54#undef UNSTARTED_RUNTIME_JNI_LIST
55#undef UNSTARTED_DIRECT
56
57 // Methods that are native.
Mathieu Chartiere401d142015-04-22 13:56:20 -070058#define UNSTARTED_JNI(Name, SigIgnored) \
Andreas Gampe799681b2015-05-15 19:24:12 -070059 static void UnstartedJNI ## Name(Thread* self, \
Mathieu Chartiere401d142015-04-22 13:56:20 -070060 ArtMethod* method, \
Andreas Gampe799681b2015-05-15 19:24:12 -070061 mirror::Object* receiver, \
62 uint32_t* args, \
63 JValue* result) \
Mathieu Chartier90443472015-07-16 20:32:27 -070064 SHARED_REQUIRES(Locks::mutator_lock_) { \
Andreas Gampe799681b2015-05-15 19:24:12 -070065 interpreter::UnstartedRuntime::UnstartedJNI ## Name(self, method, receiver, args, result); \
66 }
67#include "unstarted_runtime_list.h"
68 UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
69#undef UNSTARTED_RUNTIME_DIRECT_LIST
70#undef UNSTARTED_RUNTIME_JNI_LIST
71#undef UNSTARTED_JNI
Andreas Gampe85a098a2016-03-31 13:30:53 -070072
73 // Helpers for ArrayCopy.
74 //
75 // Note: as we have to use handles, we use StackHandleScope to transfer data. Hardcode a size
76 // of three everywhere. That is enough to test all cases.
77
78 static mirror::ObjectArray<mirror::Object>* CreateObjectArray(
79 Thread* self,
80 mirror::Class* component_type,
81 const StackHandleScope<3>& data)
82 SHARED_REQUIRES(Locks::mutator_lock_) {
83 Runtime* runtime = Runtime::Current();
84 mirror::Class* array_type = runtime->GetClassLinker()->FindArrayClass(self, &component_type);
85 CHECK(array_type != nullptr);
86 mirror::ObjectArray<mirror::Object>* result =
87 mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3);
88 CHECK(result != nullptr);
89 for (size_t i = 0; i < 3; ++i) {
90 result->Set(static_cast<int32_t>(i), data.GetReference(i));
91 CHECK(!self->IsExceptionPending());
92 }
93 return result;
94 }
95
96 static void CheckObjectArray(mirror::ObjectArray<mirror::Object>* array,
97 const StackHandleScope<3>& data)
98 SHARED_REQUIRES(Locks::mutator_lock_) {
99 CHECK_EQ(array->GetLength(), 3);
100 CHECK_EQ(data.NumberOfReferences(), 3U);
101 for (size_t i = 0; i < 3; ++i) {
102 EXPECT_EQ(data.GetReference(i), array->Get(static_cast<int32_t>(i))) << i;
103 }
104 }
105
106 void RunArrayCopy(Thread* self,
107 ShadowFrame* tmp,
108 bool expect_exception,
109 mirror::ObjectArray<mirror::Object>* src,
110 int32_t src_pos,
111 mirror::ObjectArray<mirror::Object>* dst,
112 int32_t dst_pos,
113 int32_t length)
114 SHARED_REQUIRES(Locks::mutator_lock_) {
115 JValue result;
116 tmp->SetVRegReference(0, src);
117 tmp->SetVReg(1, src_pos);
118 tmp->SetVRegReference(2, dst);
119 tmp->SetVReg(3, dst_pos);
120 tmp->SetVReg(4, length);
121 UnstartedSystemArraycopy(self, tmp, &result, 0);
122 bool exception_pending = self->IsExceptionPending();
123 EXPECT_EQ(exception_pending, expect_exception);
124 if (exception_pending) {
125 self->ClearException();
126 }
127 }
128
129 void RunArrayCopy(Thread* self,
130 ShadowFrame* tmp,
131 bool expect_exception,
132 mirror::Class* src_component_class,
133 mirror::Class* dst_component_class,
134 const StackHandleScope<3>& src_data,
135 int32_t src_pos,
136 const StackHandleScope<3>& dst_data,
137 int32_t dst_pos,
138 int32_t length,
139 const StackHandleScope<3>& expected_result)
140 SHARED_REQUIRES(Locks::mutator_lock_) {
141 StackHandleScope<3> hs_misc(self);
142 Handle<mirror::Class> dst_component_handle(hs_misc.NewHandle(dst_component_class));
143
144 Handle<mirror::ObjectArray<mirror::Object>> src_handle(
145 hs_misc.NewHandle(CreateObjectArray(self, src_component_class, src_data)));
146
147 Handle<mirror::ObjectArray<mirror::Object>> dst_handle(
148 hs_misc.NewHandle(CreateObjectArray(self, dst_component_handle.Get(), dst_data)));
149
150 RunArrayCopy(self,
151 tmp,
152 expect_exception,
153 src_handle.Get(),
154 src_pos,
155 dst_handle.Get(),
156 dst_pos,
157 length);
158 CheckObjectArray(dst_handle.Get(), expected_result);
159 }
Andreas Gampe89e3b482016-04-12 18:07:36 -0700160
161 void TestCeilFloor(bool ceil,
162 Thread* self,
163 ShadowFrame* tmp,
164 double const test_pairs[][2],
165 size_t num_pairs)
166 SHARED_REQUIRES(Locks::mutator_lock_) {
167 for (size_t i = 0; i < num_pairs; ++i) {
168 tmp->SetVRegDouble(0, test_pairs[i][0]);
169
170 JValue result;
171 if (ceil) {
172 UnstartedMathCeil(self, tmp, &result, 0);
173 } else {
174 UnstartedMathFloor(self, tmp, &result, 0);
175 }
176
177 ASSERT_FALSE(self->IsExceptionPending());
178
179 // We want precise results.
180 int64_t result_int64t = bit_cast<int64_t, double>(result.GetD());
181 int64_t expect_int64t = bit_cast<int64_t, double>(test_pairs[i][1]);
182 EXPECT_EQ(expect_int64t, result_int64t) << result.GetD() << " vs " << test_pairs[i][1];
183 }
184 }
Andreas Gampe799681b2015-05-15 19:24:12 -0700185};
186
187TEST_F(UnstartedRuntimeTest, MemoryPeekByte) {
188 Thread* self = Thread::Current();
189
190 ScopedObjectAccess soa(self);
191 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
192 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
193 const uint8_t* base_ptr = base_array;
194
195 JValue result;
196 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
197
198 for (int32_t i = 0; i < kBaseLen; ++i) {
199 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
200
201 UnstartedMemoryPeekByte(self, tmp, &result, 0);
202
203 EXPECT_EQ(result.GetB(), static_cast<int8_t>(base_array[i]));
204 }
205
206 ShadowFrame::DeleteDeoptimizedFrame(tmp);
207}
208
209TEST_F(UnstartedRuntimeTest, MemoryPeekShort) {
210 Thread* self = Thread::Current();
211
212 ScopedObjectAccess soa(self);
213 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
214 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
215 const uint8_t* base_ptr = base_array;
216
217 JValue result;
218 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
219
220 int32_t adjusted_length = kBaseLen - sizeof(int16_t);
221 for (int32_t i = 0; i < adjusted_length; ++i) {
222 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
223
224 UnstartedMemoryPeekShort(self, tmp, &result, 0);
225
226 typedef int16_t unaligned_short __attribute__ ((aligned (1)));
227 const unaligned_short* short_ptr = reinterpret_cast<const unaligned_short*>(base_ptr + i);
228 EXPECT_EQ(result.GetS(), *short_ptr);
229 }
230
231 ShadowFrame::DeleteDeoptimizedFrame(tmp);
232}
233
234TEST_F(UnstartedRuntimeTest, MemoryPeekInt) {
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 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
244
245 int32_t adjusted_length = kBaseLen - sizeof(int32_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 UnstartedMemoryPeekInt(self, tmp, &result, 0);
250
251 typedef int32_t unaligned_int __attribute__ ((aligned (1)));
252 const unaligned_int* int_ptr = reinterpret_cast<const unaligned_int*>(base_ptr + i);
253 EXPECT_EQ(result.GetI(), *int_ptr);
254 }
255
256 ShadowFrame::DeleteDeoptimizedFrame(tmp);
257}
258
259TEST_F(UnstartedRuntimeTest, MemoryPeekLong) {
260 Thread* self = Thread::Current();
261
262 ScopedObjectAccess soa(self);
263 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
264 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
265 const uint8_t* base_ptr = base_array;
266
267 JValue result;
268 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
269
270 int32_t adjusted_length = kBaseLen - sizeof(int64_t);
271 for (int32_t i = 0; i < adjusted_length; ++i) {
272 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
273
274 UnstartedMemoryPeekLong(self, tmp, &result, 0);
275
276 typedef int64_t unaligned_long __attribute__ ((aligned (1)));
277 const unaligned_long* long_ptr = reinterpret_cast<const unaligned_long*>(base_ptr + i);
278 EXPECT_EQ(result.GetJ(), *long_ptr);
279 }
280
281 ShadowFrame::DeleteDeoptimizedFrame(tmp);
282}
283
284TEST_F(UnstartedRuntimeTest, StringGetCharsNoCheck) {
285 Thread* self = Thread::Current();
286
287 ScopedObjectAccess soa(self);
288 StackHandleScope<2> hs(self);
289 // TODO: Actual UTF.
290 constexpr const char base_string[] = "abcdefghijklmnop";
291 Handle<mirror::String> h_test_string(hs.NewHandle(
292 mirror::String::AllocFromModifiedUtf8(self, base_string)));
293 constexpr int32_t kBaseLen = sizeof(base_string) / sizeof(char) - 1;
294 Handle<mirror::CharArray> h_char_array(hs.NewHandle(
295 mirror::CharArray::Alloc(self, kBaseLen)));
296 // A buffer so we can make sure we only modify the elements targetted.
297 uint16_t buf[kBaseLen];
298
299 JValue result;
300 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
301
302 for (int32_t start_index = 0; start_index < kBaseLen; ++start_index) {
303 for (int32_t count = 0; count <= kBaseLen; ++count) {
304 for (int32_t trg_offset = 0; trg_offset < kBaseLen; ++trg_offset) {
305 // Only do it when in bounds.
306 if (start_index + count <= kBaseLen && trg_offset + count <= kBaseLen) {
307 tmp->SetVRegReference(0, h_test_string.Get());
308 tmp->SetVReg(1, start_index);
309 tmp->SetVReg(2, count);
310 tmp->SetVRegReference(3, h_char_array.Get());
311 tmp->SetVReg(3, trg_offset);
312
313 // Copy the char_array into buf.
314 memcpy(buf, h_char_array->GetData(), kBaseLen * sizeof(uint16_t));
315
316 UnstartedStringCharAt(self, tmp, &result, 0);
317
318 uint16_t* data = h_char_array->GetData();
319
320 bool success = true;
321
322 // First segment should be unchanged.
323 for (int32_t i = 0; i < trg_offset; ++i) {
324 success = success && (data[i] == buf[i]);
325 }
326 // Second segment should be a copy.
327 for (int32_t i = trg_offset; i < trg_offset + count; ++i) {
328 success = success && (data[i] == buf[i - trg_offset + start_index]);
329 }
330 // Third segment should be unchanged.
331 for (int32_t i = trg_offset + count; i < kBaseLen; ++i) {
332 success = success && (data[i] == buf[i]);
333 }
334
335 EXPECT_TRUE(success);
336 }
337 }
338 }
339 }
340
341 ShadowFrame::DeleteDeoptimizedFrame(tmp);
342}
343
344TEST_F(UnstartedRuntimeTest, StringCharAt) {
345 Thread* self = Thread::Current();
346
347 ScopedObjectAccess soa(self);
348 // TODO: Actual UTF.
349 constexpr const char* base_string = "abcdefghijklmnop";
350 int32_t base_len = static_cast<int32_t>(strlen(base_string));
351 mirror::String* test_string = mirror::String::AllocFromModifiedUtf8(self, base_string);
352
353 JValue result;
354 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
355
356 for (int32_t i = 0; i < base_len; ++i) {
357 tmp->SetVRegReference(0, test_string);
358 tmp->SetVReg(1, i);
359
360 UnstartedStringCharAt(self, tmp, &result, 0);
361
362 EXPECT_EQ(result.GetI(), base_string[i]);
363 }
364
365 ShadowFrame::DeleteDeoptimizedFrame(tmp);
366}
367
Jeff Hao400ce002015-05-29 10:53:17 -0700368TEST_F(UnstartedRuntimeTest, StringInit) {
369 Thread* self = Thread::Current();
370 ScopedObjectAccess soa(self);
371 mirror::Class* klass = mirror::String::GetJavaLangString();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700372 ArtMethod* method = klass->FindDeclaredDirectMethod("<init>", "(Ljava/lang/String;)V",
373 sizeof(void*));
Jeff Hao400ce002015-05-29 10:53:17 -0700374
375 // create instruction data for invoke-direct {v0, v1} of method with fake index
376 uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 };
377 const Instruction* inst = Instruction::At(inst_data);
378
379 JValue result;
380 ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0);
381 const char* base_string = "hello_world";
382 mirror::String* string_arg = mirror::String::AllocFromModifiedUtf8(self, base_string);
383 mirror::String* reference_empty_string = mirror::String::AllocFromModifiedUtf8(self, "");
384 shadow_frame->SetVRegReference(0, reference_empty_string);
385 shadow_frame->SetVRegReference(1, string_arg);
386
387 interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result);
388 mirror::String* string_result = reinterpret_cast<mirror::String*>(result.GetL());
389 EXPECT_EQ(string_arg->GetLength(), string_result->GetLength());
390 EXPECT_EQ(memcmp(string_arg->GetValue(), string_result->GetValue(),
391 string_arg->GetLength() * sizeof(uint16_t)), 0);
392
393 ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
394}
395
Andreas Gampe85a098a2016-03-31 13:30:53 -0700396// Tests the exceptions that should be checked before modifying the destination.
397// (Doesn't check the object vs primitive case ATM.)
398TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTestExceptions) {
399 Thread* self = Thread::Current();
400 ScopedObjectAccess soa(self);
401 JValue result;
402 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
403
404 // Note: all tests are not GC safe. Assume there's no GC running here with the few objects we
405 // allocate.
406 StackHandleScope<2> hs_misc(self);
407 Handle<mirror::Class> object_class(
408 hs_misc.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
409
410 StackHandleScope<3> hs_data(self);
411 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
412 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
413 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
414
415 Handle<mirror::ObjectArray<mirror::Object>> array(
416 hs_misc.NewHandle(CreateObjectArray(self, object_class.Get(), hs_data)));
417
418 RunArrayCopy(self, tmp, true, array.Get(), -1, array.Get(), 0, 0);
419 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), -1, 0);
420 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, -1);
421 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, 4);
422 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 1, 3);
423 RunArrayCopy(self, tmp, true, array.Get(), 1, array.Get(), 0, 3);
424
425 mirror::ObjectArray<mirror::Object>* class_as_array =
426 reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(object_class.Get());
427 RunArrayCopy(self, tmp, true, class_as_array, 0, array.Get(), 0, 0);
428 RunArrayCopy(self, tmp, true, array.Get(), 0, class_as_array, 0, 0);
429
430 ShadowFrame::DeleteDeoptimizedFrame(tmp);
431}
432
433TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
434 Thread* self = Thread::Current();
435 ScopedObjectAccess soa(self);
436 JValue result;
437 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
438
439 StackHandleScope<1> hs_object(self);
440 Handle<mirror::Class> object_class(
441 hs_object.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
442
443 // Simple test:
444 // [1,2,3]{1 @ 2} into [4,5,6] = [4,2,6]
445 {
446 StackHandleScope<3> hs_src(self);
447 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
448 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
449 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
450
451 StackHandleScope<3> hs_dst(self);
452 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
453 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
454 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
455
456 StackHandleScope<3> hs_expected(self);
457 hs_expected.NewHandle(hs_dst.GetReference(0));
458 hs_expected.NewHandle(hs_dst.GetReference(1));
459 hs_expected.NewHandle(hs_src.GetReference(1));
460
461 RunArrayCopy(self,
462 tmp,
463 false,
464 object_class.Get(),
465 object_class.Get(),
466 hs_src,
467 1,
468 hs_dst,
469 2,
470 1,
471 hs_expected);
472 }
473
474 // Simple test:
475 // [1,2,3]{1 @ 1} into [4,5,6] = [4,2,6] (with dst String[])
476 {
477 StackHandleScope<3> hs_src(self);
478 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
479 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
480 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
481
482 StackHandleScope<3> hs_dst(self);
483 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
484 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
485 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
486
487 StackHandleScope<3> hs_expected(self);
488 hs_expected.NewHandle(hs_dst.GetReference(0));
489 hs_expected.NewHandle(hs_src.GetReference(1));
490 hs_expected.NewHandle(hs_dst.GetReference(2));
491
492 RunArrayCopy(self,
493 tmp,
494 false,
495 object_class.Get(),
496 mirror::String::GetJavaLangString(),
497 hs_src,
498 1,
499 hs_dst,
500 1,
501 1,
502 hs_expected);
503 }
504
505 // Simple test:
506 // [1,*,3] into [4,5,6] = [1,5,6] + exc
507 {
508 StackHandleScope<3> hs_src(self);
509 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
510 hs_src.NewHandle(mirror::String::GetJavaLangString());
511 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
512
513 StackHandleScope<3> hs_dst(self);
514 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
515 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
516 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
517
518 StackHandleScope<3> hs_expected(self);
519 hs_expected.NewHandle(hs_src.GetReference(0));
520 hs_expected.NewHandle(hs_dst.GetReference(1));
521 hs_expected.NewHandle(hs_dst.GetReference(2));
522
523 RunArrayCopy(self,
524 tmp,
525 true,
526 object_class.Get(),
527 mirror::String::GetJavaLangString(),
528 hs_src,
529 0,
530 hs_dst,
531 0,
532 3,
533 hs_expected);
534 }
535
536 ShadowFrame::DeleteDeoptimizedFrame(tmp);
537}
538
Andreas Gampe13fc1be2016-04-05 20:14:30 -0700539TEST_F(UnstartedRuntimeTest, IntegerParseIntTest) {
540 Thread* self = Thread::Current();
541 ScopedObjectAccess soa(self);
542
543 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
544
545 // Test string. Should be valid, and between minimal values of LONG_MIN and LONG_MAX (for all
546 // suffixes).
547 constexpr const char* test_string = "-2147483646";
548 constexpr int32_t test_values[] = {
549 6,
550 46,
551 646,
552 3646,
553 83646,
554 483646,
555 7483646,
556 47483646,
557 147483646,
558 2147483646,
559 -2147483646
560 };
561
562 static_assert(arraysize(test_values) == 11U, "test_values");
563 CHECK_EQ(strlen(test_string), 11U);
564
565 for (size_t i = 0; i <= 10; ++i) {
566 const char* test_value = &test_string[10 - i];
567
568 StackHandleScope<1> hs_str(self);
569 Handle<mirror::String> h_str(
570 hs_str.NewHandle(mirror::String::AllocFromModifiedUtf8(self, test_value)));
571 ASSERT_NE(h_str.Get(), nullptr);
572 ASSERT_FALSE(self->IsExceptionPending());
573
574 tmp->SetVRegReference(0, h_str.Get());
575
576 JValue result;
577 UnstartedIntegerParseInt(self, tmp, &result, 0);
578
579 ASSERT_FALSE(self->IsExceptionPending());
580 EXPECT_EQ(result.GetI(), test_values[i]);
581 }
582
583 ShadowFrame::DeleteDeoptimizedFrame(tmp);
584}
585
586// Right now the same as Integer.Parse
587TEST_F(UnstartedRuntimeTest, LongParseLongTest) {
588 Thread* self = Thread::Current();
589 ScopedObjectAccess soa(self);
590
591 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
592
593 // Test string. Should be valid, and between minimal values of LONG_MIN and LONG_MAX (for all
594 // suffixes).
595 constexpr const char* test_string = "-2147483646";
596 constexpr int64_t test_values[] = {
597 6,
598 46,
599 646,
600 3646,
601 83646,
602 483646,
603 7483646,
604 47483646,
605 147483646,
606 2147483646,
607 -2147483646
608 };
609
610 static_assert(arraysize(test_values) == 11U, "test_values");
611 CHECK_EQ(strlen(test_string), 11U);
612
613 for (size_t i = 0; i <= 10; ++i) {
614 const char* test_value = &test_string[10 - i];
615
616 StackHandleScope<1> hs_str(self);
617 Handle<mirror::String> h_str(
618 hs_str.NewHandle(mirror::String::AllocFromModifiedUtf8(self, test_value)));
619 ASSERT_NE(h_str.Get(), nullptr);
620 ASSERT_FALSE(self->IsExceptionPending());
621
622 tmp->SetVRegReference(0, h_str.Get());
623
624 JValue result;
625 UnstartedLongParseLong(self, tmp, &result, 0);
626
627 ASSERT_FALSE(self->IsExceptionPending());
628 EXPECT_EQ(result.GetJ(), test_values[i]);
629 }
630
631 ShadowFrame::DeleteDeoptimizedFrame(tmp);
632}
633
Andreas Gampe89e3b482016-04-12 18:07:36 -0700634TEST_F(UnstartedRuntimeTest, Ceil) {
635 Thread* self = Thread::Current();
636 ScopedObjectAccess soa(self);
637
638 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
639
640 constexpr double nan = std::numeric_limits<double>::quiet_NaN();
641 constexpr double inf = std::numeric_limits<double>::infinity();
642 constexpr double ld1 = static_cast<double>((UINT64_C(1) << 53) - 1);
643 constexpr double ld2 = static_cast<double>(UINT64_C(1) << 55);
644 constexpr double test_pairs[][2] = {
645 { -0.0, -0.0 },
646 { 0.0, 0.0 },
647 { -0.5, -0.0 },
648 { -1.0, -1.0 },
649 { 0.5, 1.0 },
650 { 1.0, 1.0 },
651 { nan, nan },
652 { inf, inf },
653 { -inf, -inf },
654 { ld1, ld1 },
655 { ld2, ld2 }
656 };
657
658 TestCeilFloor(true /* ceil */, self, tmp, test_pairs, arraysize(test_pairs));
659
660 ShadowFrame::DeleteDeoptimizedFrame(tmp);
661}
662
663TEST_F(UnstartedRuntimeTest, Floor) {
664 Thread* self = Thread::Current();
665 ScopedObjectAccess soa(self);
666
667 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
668
669 constexpr double nan = std::numeric_limits<double>::quiet_NaN();
670 constexpr double inf = std::numeric_limits<double>::infinity();
671 constexpr double ld1 = static_cast<double>((UINT64_C(1) << 53) - 1);
672 constexpr double ld2 = static_cast<double>(UINT64_C(1) << 55);
673 constexpr double test_pairs[][2] = {
674 { -0.0, -0.0 },
675 { 0.0, 0.0 },
676 { -0.5, -1.0 },
677 { -1.0, -1.0 },
678 { 0.5, 0.0 },
679 { 1.0, 1.0 },
680 { nan, nan },
681 { inf, inf },
682 { -inf, -inf },
683 { ld1, ld1 },
684 { ld2, ld2 }
685 };
686
687 TestCeilFloor(false /* floor */, self, tmp, test_pairs, arraysize(test_pairs));
688
689 ShadowFrame::DeleteDeoptimizedFrame(tmp);
690}
691
Andreas Gampe799681b2015-05-15 19:24:12 -0700692} // namespace interpreter
693} // namespace art