blob: ba751ec94c3295a55be9a9e4e8005ae39f73dd9c [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>
Andreas Gampe8ce9c302016-04-15 21:24:28 -070020#include <locale>
Andreas Gampe89e3b482016-04-12 18:07:36 -070021
22#include "base/casts.h"
Andreas Gampe542451c2016-07-26 09:02:02 -070023#include "base/enums.h"
Andreas Gampeb6795152016-04-21 17:23:31 -070024#include "base/memory_tool.h"
Andreas Gampe799681b2015-05-15 19:24:12 -070025#include "class_linker.h"
26#include "common_runtime_test.h"
Jeff Hao400ce002015-05-29 10:53:17 -070027#include "dex_instruction.h"
Andreas Gampe799681b2015-05-15 19:24:12 -070028#include "handle.h"
29#include "handle_scope-inl.h"
Jeff Hao400ce002015-05-29 10:53:17 -070030#include "interpreter/interpreter_common.h"
Andreas Gampe799681b2015-05-15 19:24:12 -070031#include "mirror/class_loader.h"
32#include "mirror/string-inl.h"
33#include "runtime.h"
34#include "scoped_thread_state_change.h"
35#include "thread.h"
Andreas Gampe8ce9c302016-04-15 21:24:28 -070036#include "transaction.h"
Andreas Gampe799681b2015-05-15 19:24:12 -070037
38namespace art {
39namespace interpreter {
40
41class UnstartedRuntimeTest : public CommonRuntimeTest {
42 protected:
43 // Re-expose all UnstartedRuntime implementations so we don't need to declare a million
44 // test friends.
45
46 // Methods that intercept available libcore implementations.
47#define UNSTARTED_DIRECT(Name, SigIgnored) \
48 static void Unstarted ## Name(Thread* self, \
49 ShadowFrame* shadow_frame, \
50 JValue* result, \
51 size_t arg_offset) \
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070052 REQUIRES_SHARED(Locks::mutator_lock_) { \
Andreas Gampe799681b2015-05-15 19:24:12 -070053 interpreter::UnstartedRuntime::Unstarted ## Name(self, shadow_frame, result, arg_offset); \
54 }
55#include "unstarted_runtime_list.h"
56 UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
57#undef UNSTARTED_RUNTIME_DIRECT_LIST
58#undef UNSTARTED_RUNTIME_JNI_LIST
59#undef UNSTARTED_DIRECT
60
61 // Methods that are native.
Mathieu Chartiere401d142015-04-22 13:56:20 -070062#define UNSTARTED_JNI(Name, SigIgnored) \
Andreas Gampe799681b2015-05-15 19:24:12 -070063 static void UnstartedJNI ## Name(Thread* self, \
Mathieu Chartiere401d142015-04-22 13:56:20 -070064 ArtMethod* method, \
Andreas Gampe799681b2015-05-15 19:24:12 -070065 mirror::Object* receiver, \
66 uint32_t* args, \
67 JValue* result) \
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070068 REQUIRES_SHARED(Locks::mutator_lock_) { \
Andreas Gampe799681b2015-05-15 19:24:12 -070069 interpreter::UnstartedRuntime::UnstartedJNI ## Name(self, method, receiver, args, result); \
70 }
71#include "unstarted_runtime_list.h"
72 UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
73#undef UNSTARTED_RUNTIME_DIRECT_LIST
74#undef UNSTARTED_RUNTIME_JNI_LIST
75#undef UNSTARTED_JNI
Andreas Gampe85a098a2016-03-31 13:30:53 -070076
77 // Helpers for ArrayCopy.
78 //
79 // Note: as we have to use handles, we use StackHandleScope to transfer data. Hardcode a size
80 // of three everywhere. That is enough to test all cases.
81
82 static mirror::ObjectArray<mirror::Object>* CreateObjectArray(
83 Thread* self,
84 mirror::Class* component_type,
85 const StackHandleScope<3>& data)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070086 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe85a098a2016-03-31 13:30:53 -070087 Runtime* runtime = Runtime::Current();
88 mirror::Class* array_type = runtime->GetClassLinker()->FindArrayClass(self, &component_type);
89 CHECK(array_type != nullptr);
90 mirror::ObjectArray<mirror::Object>* result =
91 mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3);
92 CHECK(result != nullptr);
93 for (size_t i = 0; i < 3; ++i) {
94 result->Set(static_cast<int32_t>(i), data.GetReference(i));
95 CHECK(!self->IsExceptionPending());
96 }
97 return result;
98 }
99
100 static void CheckObjectArray(mirror::ObjectArray<mirror::Object>* array,
101 const StackHandleScope<3>& data)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700102 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe85a098a2016-03-31 13:30:53 -0700103 CHECK_EQ(array->GetLength(), 3);
104 CHECK_EQ(data.NumberOfReferences(), 3U);
105 for (size_t i = 0; i < 3; ++i) {
106 EXPECT_EQ(data.GetReference(i), array->Get(static_cast<int32_t>(i))) << i;
107 }
108 }
109
110 void RunArrayCopy(Thread* self,
111 ShadowFrame* tmp,
112 bool expect_exception,
113 mirror::ObjectArray<mirror::Object>* src,
114 int32_t src_pos,
115 mirror::ObjectArray<mirror::Object>* dst,
116 int32_t dst_pos,
117 int32_t length)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700118 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe85a098a2016-03-31 13:30:53 -0700119 JValue result;
120 tmp->SetVRegReference(0, src);
121 tmp->SetVReg(1, src_pos);
122 tmp->SetVRegReference(2, dst);
123 tmp->SetVReg(3, dst_pos);
124 tmp->SetVReg(4, length);
125 UnstartedSystemArraycopy(self, tmp, &result, 0);
126 bool exception_pending = self->IsExceptionPending();
127 EXPECT_EQ(exception_pending, expect_exception);
128 if (exception_pending) {
129 self->ClearException();
130 }
131 }
132
133 void RunArrayCopy(Thread* self,
134 ShadowFrame* tmp,
135 bool expect_exception,
136 mirror::Class* src_component_class,
137 mirror::Class* dst_component_class,
138 const StackHandleScope<3>& src_data,
139 int32_t src_pos,
140 const StackHandleScope<3>& dst_data,
141 int32_t dst_pos,
142 int32_t length,
143 const StackHandleScope<3>& expected_result)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700144 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe85a098a2016-03-31 13:30:53 -0700145 StackHandleScope<3> hs_misc(self);
146 Handle<mirror::Class> dst_component_handle(hs_misc.NewHandle(dst_component_class));
147
148 Handle<mirror::ObjectArray<mirror::Object>> src_handle(
149 hs_misc.NewHandle(CreateObjectArray(self, src_component_class, src_data)));
150
151 Handle<mirror::ObjectArray<mirror::Object>> dst_handle(
152 hs_misc.NewHandle(CreateObjectArray(self, dst_component_handle.Get(), dst_data)));
153
154 RunArrayCopy(self,
155 tmp,
156 expect_exception,
157 src_handle.Get(),
158 src_pos,
159 dst_handle.Get(),
160 dst_pos,
161 length);
162 CheckObjectArray(dst_handle.Get(), expected_result);
163 }
Andreas Gampe89e3b482016-04-12 18:07:36 -0700164
165 void TestCeilFloor(bool ceil,
166 Thread* self,
167 ShadowFrame* tmp,
168 double const test_pairs[][2],
169 size_t num_pairs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700170 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe89e3b482016-04-12 18:07:36 -0700171 for (size_t i = 0; i < num_pairs; ++i) {
172 tmp->SetVRegDouble(0, test_pairs[i][0]);
173
174 JValue result;
175 if (ceil) {
176 UnstartedMathCeil(self, tmp, &result, 0);
177 } else {
178 UnstartedMathFloor(self, tmp, &result, 0);
179 }
180
181 ASSERT_FALSE(self->IsExceptionPending());
182
183 // We want precise results.
184 int64_t result_int64t = bit_cast<int64_t, double>(result.GetD());
185 int64_t expect_int64t = bit_cast<int64_t, double>(test_pairs[i][1]);
186 EXPECT_EQ(expect_int64t, result_int64t) << result.GetD() << " vs " << test_pairs[i][1];
187 }
188 }
Andreas Gampe8ce9c302016-04-15 21:24:28 -0700189
190 // Prepare for aborts. Aborts assume that the exception class is already resolved, as the
191 // loading code doesn't work under transactions.
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700192 void PrepareForAborts() REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe8ce9c302016-04-15 21:24:28 -0700193 mirror::Object* result = Runtime::Current()->GetClassLinker()->FindClass(
194 Thread::Current(),
195 Transaction::kAbortExceptionSignature,
196 ScopedNullHandle<mirror::ClassLoader>());
197 CHECK(result != nullptr);
198 }
Andreas Gampe799681b2015-05-15 19:24:12 -0700199};
200
201TEST_F(UnstartedRuntimeTest, MemoryPeekByte) {
202 Thread* self = Thread::Current();
203
204 ScopedObjectAccess soa(self);
205 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
206 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
207 const uint8_t* base_ptr = base_array;
208
209 JValue result;
210 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
211
212 for (int32_t i = 0; i < kBaseLen; ++i) {
213 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
214
215 UnstartedMemoryPeekByte(self, tmp, &result, 0);
216
217 EXPECT_EQ(result.GetB(), static_cast<int8_t>(base_array[i]));
218 }
219
220 ShadowFrame::DeleteDeoptimizedFrame(tmp);
221}
222
223TEST_F(UnstartedRuntimeTest, MemoryPeekShort) {
224 Thread* self = Thread::Current();
225
226 ScopedObjectAccess soa(self);
227 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
228 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
229 const uint8_t* base_ptr = base_array;
230
231 JValue result;
232 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
233
234 int32_t adjusted_length = kBaseLen - sizeof(int16_t);
235 for (int32_t i = 0; i < adjusted_length; ++i) {
236 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
237
238 UnstartedMemoryPeekShort(self, tmp, &result, 0);
239
240 typedef int16_t unaligned_short __attribute__ ((aligned (1)));
241 const unaligned_short* short_ptr = reinterpret_cast<const unaligned_short*>(base_ptr + i);
242 EXPECT_EQ(result.GetS(), *short_ptr);
243 }
244
245 ShadowFrame::DeleteDeoptimizedFrame(tmp);
246}
247
248TEST_F(UnstartedRuntimeTest, MemoryPeekInt) {
249 Thread* self = Thread::Current();
250
251 ScopedObjectAccess soa(self);
252 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
253 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
254 const uint8_t* base_ptr = base_array;
255
256 JValue result;
257 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
258
259 int32_t adjusted_length = kBaseLen - sizeof(int32_t);
260 for (int32_t i = 0; i < adjusted_length; ++i) {
261 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
262
263 UnstartedMemoryPeekInt(self, tmp, &result, 0);
264
265 typedef int32_t unaligned_int __attribute__ ((aligned (1)));
266 const unaligned_int* int_ptr = reinterpret_cast<const unaligned_int*>(base_ptr + i);
267 EXPECT_EQ(result.GetI(), *int_ptr);
268 }
269
270 ShadowFrame::DeleteDeoptimizedFrame(tmp);
271}
272
273TEST_F(UnstartedRuntimeTest, MemoryPeekLong) {
274 Thread* self = Thread::Current();
275
276 ScopedObjectAccess soa(self);
277 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
278 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
279 const uint8_t* base_ptr = base_array;
280
281 JValue result;
282 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
283
284 int32_t adjusted_length = kBaseLen - sizeof(int64_t);
285 for (int32_t i = 0; i < adjusted_length; ++i) {
286 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
287
288 UnstartedMemoryPeekLong(self, tmp, &result, 0);
289
290 typedef int64_t unaligned_long __attribute__ ((aligned (1)));
291 const unaligned_long* long_ptr = reinterpret_cast<const unaligned_long*>(base_ptr + i);
292 EXPECT_EQ(result.GetJ(), *long_ptr);
293 }
294
295 ShadowFrame::DeleteDeoptimizedFrame(tmp);
296}
297
298TEST_F(UnstartedRuntimeTest, StringGetCharsNoCheck) {
299 Thread* self = Thread::Current();
300
301 ScopedObjectAccess soa(self);
302 StackHandleScope<2> hs(self);
303 // TODO: Actual UTF.
304 constexpr const char base_string[] = "abcdefghijklmnop";
305 Handle<mirror::String> h_test_string(hs.NewHandle(
306 mirror::String::AllocFromModifiedUtf8(self, base_string)));
307 constexpr int32_t kBaseLen = sizeof(base_string) / sizeof(char) - 1;
308 Handle<mirror::CharArray> h_char_array(hs.NewHandle(
309 mirror::CharArray::Alloc(self, kBaseLen)));
310 // A buffer so we can make sure we only modify the elements targetted.
311 uint16_t buf[kBaseLen];
312
313 JValue result;
314 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
315
316 for (int32_t start_index = 0; start_index < kBaseLen; ++start_index) {
317 for (int32_t count = 0; count <= kBaseLen; ++count) {
318 for (int32_t trg_offset = 0; trg_offset < kBaseLen; ++trg_offset) {
319 // Only do it when in bounds.
320 if (start_index + count <= kBaseLen && trg_offset + count <= kBaseLen) {
321 tmp->SetVRegReference(0, h_test_string.Get());
322 tmp->SetVReg(1, start_index);
323 tmp->SetVReg(2, count);
324 tmp->SetVRegReference(3, h_char_array.Get());
325 tmp->SetVReg(3, trg_offset);
326
327 // Copy the char_array into buf.
328 memcpy(buf, h_char_array->GetData(), kBaseLen * sizeof(uint16_t));
329
330 UnstartedStringCharAt(self, tmp, &result, 0);
331
332 uint16_t* data = h_char_array->GetData();
333
334 bool success = true;
335
336 // First segment should be unchanged.
337 for (int32_t i = 0; i < trg_offset; ++i) {
338 success = success && (data[i] == buf[i]);
339 }
340 // Second segment should be a copy.
341 for (int32_t i = trg_offset; i < trg_offset + count; ++i) {
342 success = success && (data[i] == buf[i - trg_offset + start_index]);
343 }
344 // Third segment should be unchanged.
345 for (int32_t i = trg_offset + count; i < kBaseLen; ++i) {
346 success = success && (data[i] == buf[i]);
347 }
348
349 EXPECT_TRUE(success);
350 }
351 }
352 }
353 }
354
355 ShadowFrame::DeleteDeoptimizedFrame(tmp);
356}
357
358TEST_F(UnstartedRuntimeTest, StringCharAt) {
359 Thread* self = Thread::Current();
360
361 ScopedObjectAccess soa(self);
362 // TODO: Actual UTF.
363 constexpr const char* base_string = "abcdefghijklmnop";
364 int32_t base_len = static_cast<int32_t>(strlen(base_string));
365 mirror::String* test_string = mirror::String::AllocFromModifiedUtf8(self, base_string);
366
367 JValue result;
368 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
369
370 for (int32_t i = 0; i < base_len; ++i) {
371 tmp->SetVRegReference(0, test_string);
372 tmp->SetVReg(1, i);
373
374 UnstartedStringCharAt(self, tmp, &result, 0);
375
376 EXPECT_EQ(result.GetI(), base_string[i]);
377 }
378
379 ShadowFrame::DeleteDeoptimizedFrame(tmp);
380}
381
Jeff Hao400ce002015-05-29 10:53:17 -0700382TEST_F(UnstartedRuntimeTest, StringInit) {
383 Thread* self = Thread::Current();
384 ScopedObjectAccess soa(self);
385 mirror::Class* klass = mirror::String::GetJavaLangString();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700386 ArtMethod* method = klass->FindDeclaredDirectMethod("<init>", "(Ljava/lang/String;)V",
Andreas Gampe542451c2016-07-26 09:02:02 -0700387 kRuntimePointerSize);
Jeff Hao400ce002015-05-29 10:53:17 -0700388
389 // create instruction data for invoke-direct {v0, v1} of method with fake index
390 uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 };
391 const Instruction* inst = Instruction::At(inst_data);
392
393 JValue result;
394 ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0);
395 const char* base_string = "hello_world";
396 mirror::String* string_arg = mirror::String::AllocFromModifiedUtf8(self, base_string);
397 mirror::String* reference_empty_string = mirror::String::AllocFromModifiedUtf8(self, "");
398 shadow_frame->SetVRegReference(0, reference_empty_string);
399 shadow_frame->SetVRegReference(1, string_arg);
400
401 interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result);
402 mirror::String* string_result = reinterpret_cast<mirror::String*>(result.GetL());
403 EXPECT_EQ(string_arg->GetLength(), string_result->GetLength());
jessicahandojo3aaa37b2016-07-29 14:46:37 -0700404
405 if (string_arg->IsCompressed() && string_result->IsCompressed()) {
406 EXPECT_EQ(memcmp(string_arg->GetValueCompressed(), string_result->GetValueCompressed(),
407 string_arg->GetLength() * sizeof(uint8_t)), 0);
408 } else if (!string_arg->IsCompressed() && !string_result->IsCompressed()) {
409 EXPECT_EQ(memcmp(string_arg->GetValue(), string_result->GetValue(),
410 string_arg->GetLength() * sizeof(uint16_t)), 0);
411 } else {
412 bool equal = true;
413 for (int i = 0; i < string_arg->GetLength(); ++i) {
414 if (string_arg->CharAt(i) != string_result->CharAt(i)) {
415 equal = false;
416 break;
417 }
418 }
419 EXPECT_EQ(equal, true);
420 }
Jeff Hao400ce002015-05-29 10:53:17 -0700421
422 ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
423}
424
Andreas Gampe85a098a2016-03-31 13:30:53 -0700425// Tests the exceptions that should be checked before modifying the destination.
426// (Doesn't check the object vs primitive case ATM.)
427TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTestExceptions) {
428 Thread* self = Thread::Current();
429 ScopedObjectAccess soa(self);
430 JValue result;
431 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
432
433 // Note: all tests are not GC safe. Assume there's no GC running here with the few objects we
434 // allocate.
435 StackHandleScope<2> hs_misc(self);
436 Handle<mirror::Class> object_class(
437 hs_misc.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
438
439 StackHandleScope<3> hs_data(self);
440 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
441 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
442 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
443
444 Handle<mirror::ObjectArray<mirror::Object>> array(
445 hs_misc.NewHandle(CreateObjectArray(self, object_class.Get(), hs_data)));
446
447 RunArrayCopy(self, tmp, true, array.Get(), -1, array.Get(), 0, 0);
448 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), -1, 0);
449 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, -1);
450 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, 4);
451 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 1, 3);
452 RunArrayCopy(self, tmp, true, array.Get(), 1, array.Get(), 0, 3);
453
454 mirror::ObjectArray<mirror::Object>* class_as_array =
455 reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(object_class.Get());
456 RunArrayCopy(self, tmp, true, class_as_array, 0, array.Get(), 0, 0);
457 RunArrayCopy(self, tmp, true, array.Get(), 0, class_as_array, 0, 0);
458
459 ShadowFrame::DeleteDeoptimizedFrame(tmp);
460}
461
462TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
463 Thread* self = Thread::Current();
464 ScopedObjectAccess soa(self);
465 JValue result;
466 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
467
468 StackHandleScope<1> hs_object(self);
469 Handle<mirror::Class> object_class(
470 hs_object.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
471
472 // Simple test:
473 // [1,2,3]{1 @ 2} into [4,5,6] = [4,2,6]
474 {
475 StackHandleScope<3> hs_src(self);
476 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
477 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
478 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
479
480 StackHandleScope<3> hs_dst(self);
481 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
482 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
483 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
484
485 StackHandleScope<3> hs_expected(self);
486 hs_expected.NewHandle(hs_dst.GetReference(0));
487 hs_expected.NewHandle(hs_dst.GetReference(1));
488 hs_expected.NewHandle(hs_src.GetReference(1));
489
490 RunArrayCopy(self,
491 tmp,
492 false,
493 object_class.Get(),
494 object_class.Get(),
495 hs_src,
496 1,
497 hs_dst,
498 2,
499 1,
500 hs_expected);
501 }
502
503 // Simple test:
504 // [1,2,3]{1 @ 1} into [4,5,6] = [4,2,6] (with dst String[])
505 {
506 StackHandleScope<3> hs_src(self);
507 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
508 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
509 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
510
511 StackHandleScope<3> hs_dst(self);
512 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
513 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
514 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
515
516 StackHandleScope<3> hs_expected(self);
517 hs_expected.NewHandle(hs_dst.GetReference(0));
518 hs_expected.NewHandle(hs_src.GetReference(1));
519 hs_expected.NewHandle(hs_dst.GetReference(2));
520
521 RunArrayCopy(self,
522 tmp,
523 false,
524 object_class.Get(),
525 mirror::String::GetJavaLangString(),
526 hs_src,
527 1,
528 hs_dst,
529 1,
530 1,
531 hs_expected);
532 }
533
534 // Simple test:
535 // [1,*,3] into [4,5,6] = [1,5,6] + exc
536 {
537 StackHandleScope<3> hs_src(self);
538 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
539 hs_src.NewHandle(mirror::String::GetJavaLangString());
540 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
541
542 StackHandleScope<3> hs_dst(self);
543 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
544 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
545 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
546
547 StackHandleScope<3> hs_expected(self);
548 hs_expected.NewHandle(hs_src.GetReference(0));
549 hs_expected.NewHandle(hs_dst.GetReference(1));
550 hs_expected.NewHandle(hs_dst.GetReference(2));
551
552 RunArrayCopy(self,
553 tmp,
554 true,
555 object_class.Get(),
556 mirror::String::GetJavaLangString(),
557 hs_src,
558 0,
559 hs_dst,
560 0,
561 3,
562 hs_expected);
563 }
564
565 ShadowFrame::DeleteDeoptimizedFrame(tmp);
566}
567
Andreas Gampe13fc1be2016-04-05 20:14:30 -0700568TEST_F(UnstartedRuntimeTest, IntegerParseIntTest) {
569 Thread* self = Thread::Current();
570 ScopedObjectAccess soa(self);
571
572 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, 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 int32_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 UnstartedIntegerParseInt(self, tmp, &result, 0);
607
608 ASSERT_FALSE(self->IsExceptionPending());
609 EXPECT_EQ(result.GetI(), test_values[i]);
610 }
611
612 ShadowFrame::DeleteDeoptimizedFrame(tmp);
613}
614
615// Right now the same as Integer.Parse
616TEST_F(UnstartedRuntimeTest, LongParseLongTest) {
617 Thread* self = Thread::Current();
618 ScopedObjectAccess soa(self);
619
620 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
621
622 // Test string. Should be valid, and between minimal values of LONG_MIN and LONG_MAX (for all
623 // suffixes).
624 constexpr const char* test_string = "-2147483646";
625 constexpr int64_t test_values[] = {
626 6,
627 46,
628 646,
629 3646,
630 83646,
631 483646,
632 7483646,
633 47483646,
634 147483646,
635 2147483646,
636 -2147483646
637 };
638
639 static_assert(arraysize(test_values) == 11U, "test_values");
640 CHECK_EQ(strlen(test_string), 11U);
641
642 for (size_t i = 0; i <= 10; ++i) {
643 const char* test_value = &test_string[10 - i];
644
645 StackHandleScope<1> hs_str(self);
646 Handle<mirror::String> h_str(
647 hs_str.NewHandle(mirror::String::AllocFromModifiedUtf8(self, test_value)));
648 ASSERT_NE(h_str.Get(), nullptr);
649 ASSERT_FALSE(self->IsExceptionPending());
650
651 tmp->SetVRegReference(0, h_str.Get());
652
653 JValue result;
654 UnstartedLongParseLong(self, tmp, &result, 0);
655
656 ASSERT_FALSE(self->IsExceptionPending());
657 EXPECT_EQ(result.GetJ(), test_values[i]);
658 }
659
660 ShadowFrame::DeleteDeoptimizedFrame(tmp);
661}
662
Andreas Gampe89e3b482016-04-12 18:07:36 -0700663TEST_F(UnstartedRuntimeTest, Ceil) {
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, -0.0 },
677 { -1.0, -1.0 },
678 { 0.5, 1.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(true /* ceil */, self, tmp, test_pairs, arraysize(test_pairs));
688
689 ShadowFrame::DeleteDeoptimizedFrame(tmp);
690}
691
692TEST_F(UnstartedRuntimeTest, Floor) {
693 Thread* self = Thread::Current();
694 ScopedObjectAccess soa(self);
695
696 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
697
698 constexpr double nan = std::numeric_limits<double>::quiet_NaN();
699 constexpr double inf = std::numeric_limits<double>::infinity();
700 constexpr double ld1 = static_cast<double>((UINT64_C(1) << 53) - 1);
701 constexpr double ld2 = static_cast<double>(UINT64_C(1) << 55);
702 constexpr double test_pairs[][2] = {
703 { -0.0, -0.0 },
704 { 0.0, 0.0 },
705 { -0.5, -1.0 },
706 { -1.0, -1.0 },
707 { 0.5, 0.0 },
708 { 1.0, 1.0 },
709 { nan, nan },
710 { inf, inf },
711 { -inf, -inf },
712 { ld1, ld1 },
713 { ld2, ld2 }
714 };
715
716 TestCeilFloor(false /* floor */, self, tmp, test_pairs, arraysize(test_pairs));
717
718 ShadowFrame::DeleteDeoptimizedFrame(tmp);
719}
720
Andreas Gampe8ce9c302016-04-15 21:24:28 -0700721TEST_F(UnstartedRuntimeTest, ToLowerUpper) {
722 Thread* self = Thread::Current();
723 ScopedObjectAccess soa(self);
724
725 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
726
727 std::locale c_locale("C");
728
729 // Check ASCII.
730 for (uint32_t i = 0; i < 128; ++i) {
731 bool c_upper = std::isupper(static_cast<char>(i), c_locale);
732 bool c_lower = std::islower(static_cast<char>(i), c_locale);
733 EXPECT_FALSE(c_upper && c_lower) << i;
734
735 // Check toLowerCase.
736 {
737 JValue result;
738 tmp->SetVReg(0, static_cast<int32_t>(i));
739 UnstartedCharacterToLowerCase(self, tmp, &result, 0);
740 ASSERT_FALSE(self->IsExceptionPending());
741 uint32_t lower_result = static_cast<uint32_t>(result.GetI());
742 if (c_lower) {
743 EXPECT_EQ(i, lower_result);
744 } else if (c_upper) {
745 EXPECT_EQ(static_cast<uint32_t>(std::tolower(static_cast<char>(i), c_locale)),
746 lower_result);
747 } else {
748 EXPECT_EQ(i, lower_result);
749 }
750 }
751
752 // Check toUpperCase.
753 {
754 JValue result2;
755 tmp->SetVReg(0, static_cast<int32_t>(i));
756 UnstartedCharacterToUpperCase(self, tmp, &result2, 0);
757 ASSERT_FALSE(self->IsExceptionPending());
758 uint32_t upper_result = static_cast<uint32_t>(result2.GetI());
759 if (c_upper) {
760 EXPECT_EQ(i, upper_result);
761 } else if (c_lower) {
762 EXPECT_EQ(static_cast<uint32_t>(std::toupper(static_cast<char>(i), c_locale)),
763 upper_result);
764 } else {
765 EXPECT_EQ(i, upper_result);
766 }
767 }
768 }
769
770 // Check abort for other things. Can't test all.
771
772 PrepareForAborts();
773
774 for (uint32_t i = 128; i < 256; ++i) {
775 {
776 JValue result;
777 tmp->SetVReg(0, static_cast<int32_t>(i));
778 Transaction transaction;
779 Runtime::Current()->EnterTransactionMode(&transaction);
780 UnstartedCharacterToLowerCase(self, tmp, &result, 0);
781 Runtime::Current()->ExitTransactionMode();
782 ASSERT_TRUE(self->IsExceptionPending());
783 ASSERT_TRUE(transaction.IsAborted());
784 }
785 {
786 JValue result;
787 tmp->SetVReg(0, static_cast<int32_t>(i));
788 Transaction transaction;
789 Runtime::Current()->EnterTransactionMode(&transaction);
790 UnstartedCharacterToUpperCase(self, tmp, &result, 0);
791 Runtime::Current()->ExitTransactionMode();
792 ASSERT_TRUE(self->IsExceptionPending());
793 ASSERT_TRUE(transaction.IsAborted());
794 }
795 }
796 for (uint64_t i = 256; i <= std::numeric_limits<uint32_t>::max(); i <<= 1) {
797 {
798 JValue result;
799 tmp->SetVReg(0, static_cast<int32_t>(i));
800 Transaction transaction;
801 Runtime::Current()->EnterTransactionMode(&transaction);
802 UnstartedCharacterToLowerCase(self, tmp, &result, 0);
803 Runtime::Current()->ExitTransactionMode();
804 ASSERT_TRUE(self->IsExceptionPending());
805 ASSERT_TRUE(transaction.IsAborted());
806 }
807 {
808 JValue result;
809 tmp->SetVReg(0, static_cast<int32_t>(i));
810 Transaction transaction;
811 Runtime::Current()->EnterTransactionMode(&transaction);
812 UnstartedCharacterToUpperCase(self, tmp, &result, 0);
813 Runtime::Current()->ExitTransactionMode();
814 ASSERT_TRUE(self->IsExceptionPending());
815 ASSERT_TRUE(transaction.IsAborted());
816 }
817 }
818
819 ShadowFrame::DeleteDeoptimizedFrame(tmp);
820}
821
Andreas Gampeb8a00f92016-04-18 20:51:13 -0700822TEST_F(UnstartedRuntimeTest, Sin) {
823 Thread* self = Thread::Current();
824 ScopedObjectAccess soa(self);
825
826 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
827
828 // Test an important value, PI/6. That's the one we see in practice.
829 constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365);
830 tmp->SetVRegLong(0, static_cast<int64_t>(lvalue));
831
832 JValue result;
833 UnstartedMathSin(self, tmp, &result, 0);
834
835 const uint64_t lresult = static_cast<uint64_t>(result.GetJ());
836 EXPECT_EQ(UINT64_C(0x3fdfffffffffffff), lresult);
837
838 ShadowFrame::DeleteDeoptimizedFrame(tmp);
839}
840
841TEST_F(UnstartedRuntimeTest, Cos) {
842 Thread* self = Thread::Current();
843 ScopedObjectAccess soa(self);
844
845 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
846
847 // Test an important value, PI/6. That's the one we see in practice.
848 constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365);
849 tmp->SetVRegLong(0, static_cast<int64_t>(lvalue));
850
851 JValue result;
852 UnstartedMathCos(self, tmp, &result, 0);
853
854 const uint64_t lresult = static_cast<uint64_t>(result.GetJ());
855 EXPECT_EQ(UINT64_C(0x3febb67ae8584cab), lresult);
856
857 ShadowFrame::DeleteDeoptimizedFrame(tmp);
858}
859
860TEST_F(UnstartedRuntimeTest, Pow) {
Andreas Gampeb6795152016-04-21 17:23:31 -0700861 // Valgrind seems to get this wrong, actually. Disable for valgrind.
862 if (RUNNING_ON_MEMORY_TOOL != 0 && kMemoryToolIsValgrind) {
863 return;
864 }
865
Andreas Gampeb8a00f92016-04-18 20:51:13 -0700866 Thread* self = Thread::Current();
867 ScopedObjectAccess soa(self);
868
869 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
870
871 // Test an important pair.
872 constexpr uint64_t lvalue1 = UINT64_C(0x4079000000000000);
873 constexpr uint64_t lvalue2 = UINT64_C(0xbfe6db6dc0000000);
874
875 tmp->SetVRegLong(0, static_cast<int64_t>(lvalue1));
876 tmp->SetVRegLong(2, static_cast<int64_t>(lvalue2));
877
878 JValue result;
879 UnstartedMathPow(self, tmp, &result, 0);
880
881 const uint64_t lresult = static_cast<uint64_t>(result.GetJ());
882 EXPECT_EQ(UINT64_C(0x3f8c5c51326aa7ee), lresult);
883
884 ShadowFrame::DeleteDeoptimizedFrame(tmp);
885}
886
Andreas Gampe799681b2015-05-15 19:24:12 -0700887} // namespace interpreter
888} // namespace art