unstarted_runtime_test.cc revision 85a098af5fc8d2dd0e39d61c9f93fc6257d631c5
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.h"
18
19#include "class_linker.h"
20#include "common_runtime_test.h"
21#include "dex_instruction.h"
22#include "handle.h"
23#include "handle_scope-inl.h"
24#include "interpreter/interpreter_common.h"
25#include "mirror/class_loader.h"
26#include "mirror/string-inl.h"
27#include "runtime.h"
28#include "scoped_thread_state_change.h"
29#include "thread.h"
30
31namespace art {
32namespace interpreter {
33
34class UnstartedRuntimeTest : public CommonRuntimeTest {
35 protected:
36  // Re-expose all UnstartedRuntime implementations so we don't need to declare a million
37  // test friends.
38
39  // Methods that intercept available libcore implementations.
40#define UNSTARTED_DIRECT(Name, SigIgnored)                 \
41  static void Unstarted ## Name(Thread* self,              \
42                                ShadowFrame* shadow_frame, \
43                                JValue* result,            \
44                                size_t arg_offset)         \
45      SHARED_REQUIRES(Locks::mutator_lock_) {        \
46    interpreter::UnstartedRuntime::Unstarted ## Name(self, shadow_frame, result, arg_offset); \
47  }
48#include "unstarted_runtime_list.h"
49  UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
50#undef UNSTARTED_RUNTIME_DIRECT_LIST
51#undef UNSTARTED_RUNTIME_JNI_LIST
52#undef UNSTARTED_DIRECT
53
54  // Methods that are native.
55#define UNSTARTED_JNI(Name, SigIgnored)                       \
56  static void UnstartedJNI ## Name(Thread* self,              \
57                                   ArtMethod* method,         \
58                                   mirror::Object* receiver,  \
59                                   uint32_t* args,            \
60                                   JValue* result)            \
61      SHARED_REQUIRES(Locks::mutator_lock_) {           \
62    interpreter::UnstartedRuntime::UnstartedJNI ## Name(self, method, receiver, args, result); \
63  }
64#include "unstarted_runtime_list.h"
65  UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
66#undef UNSTARTED_RUNTIME_DIRECT_LIST
67#undef UNSTARTED_RUNTIME_JNI_LIST
68#undef UNSTARTED_JNI
69
70  // Helpers for ArrayCopy.
71  //
72  // Note: as we have to use handles, we use StackHandleScope to transfer data. Hardcode a size
73  //       of three everywhere. That is enough to test all cases.
74
75  static mirror::ObjectArray<mirror::Object>* CreateObjectArray(
76      Thread* self,
77      mirror::Class* component_type,
78      const StackHandleScope<3>& data)
79      SHARED_REQUIRES(Locks::mutator_lock_) {
80    Runtime* runtime = Runtime::Current();
81    mirror::Class* array_type = runtime->GetClassLinker()->FindArrayClass(self, &component_type);
82    CHECK(array_type != nullptr);
83    mirror::ObjectArray<mirror::Object>* result =
84        mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3);
85    CHECK(result != nullptr);
86    for (size_t i = 0; i < 3; ++i) {
87      result->Set(static_cast<int32_t>(i), data.GetReference(i));
88      CHECK(!self->IsExceptionPending());
89    }
90    return result;
91  }
92
93  static void CheckObjectArray(mirror::ObjectArray<mirror::Object>* array,
94                               const StackHandleScope<3>& data)
95      SHARED_REQUIRES(Locks::mutator_lock_) {
96    CHECK_EQ(array->GetLength(), 3);
97    CHECK_EQ(data.NumberOfReferences(), 3U);
98    for (size_t i = 0; i < 3; ++i) {
99      EXPECT_EQ(data.GetReference(i), array->Get(static_cast<int32_t>(i))) << i;
100    }
101  }
102
103  void RunArrayCopy(Thread* self,
104                    ShadowFrame* tmp,
105                    bool expect_exception,
106                    mirror::ObjectArray<mirror::Object>* src,
107                    int32_t src_pos,
108                    mirror::ObjectArray<mirror::Object>* dst,
109                    int32_t dst_pos,
110                    int32_t length)
111      SHARED_REQUIRES(Locks::mutator_lock_) {
112    JValue result;
113    tmp->SetVRegReference(0, src);
114    tmp->SetVReg(1, src_pos);
115    tmp->SetVRegReference(2, dst);
116    tmp->SetVReg(3, dst_pos);
117    tmp->SetVReg(4, length);
118    UnstartedSystemArraycopy(self, tmp, &result, 0);
119    bool exception_pending = self->IsExceptionPending();
120    EXPECT_EQ(exception_pending, expect_exception);
121    if (exception_pending) {
122      self->ClearException();
123    }
124  }
125
126  void RunArrayCopy(Thread* self,
127                    ShadowFrame* tmp,
128                    bool expect_exception,
129                    mirror::Class* src_component_class,
130                    mirror::Class* dst_component_class,
131                    const StackHandleScope<3>& src_data,
132                    int32_t src_pos,
133                    const StackHandleScope<3>& dst_data,
134                    int32_t dst_pos,
135                    int32_t length,
136                    const StackHandleScope<3>& expected_result)
137      SHARED_REQUIRES(Locks::mutator_lock_) {
138    StackHandleScope<3> hs_misc(self);
139    Handle<mirror::Class> dst_component_handle(hs_misc.NewHandle(dst_component_class));
140
141    Handle<mirror::ObjectArray<mirror::Object>> src_handle(
142        hs_misc.NewHandle(CreateObjectArray(self, src_component_class, src_data)));
143
144    Handle<mirror::ObjectArray<mirror::Object>> dst_handle(
145        hs_misc.NewHandle(CreateObjectArray(self, dst_component_handle.Get(), dst_data)));
146
147    RunArrayCopy(self,
148                 tmp,
149                 expect_exception,
150                 src_handle.Get(),
151                 src_pos,
152                 dst_handle.Get(),
153                 dst_pos,
154                 length);
155    CheckObjectArray(dst_handle.Get(), expected_result);
156  }
157};
158
159TEST_F(UnstartedRuntimeTest, MemoryPeekByte) {
160  Thread* self = Thread::Current();
161
162  ScopedObjectAccess soa(self);
163  constexpr const uint8_t base_array[] = "abcdefghijklmnop";
164  constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
165  const uint8_t* base_ptr = base_array;
166
167  JValue result;
168  ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
169
170  for (int32_t i = 0; i < kBaseLen; ++i) {
171    tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
172
173    UnstartedMemoryPeekByte(self, tmp, &result, 0);
174
175    EXPECT_EQ(result.GetB(), static_cast<int8_t>(base_array[i]));
176  }
177
178  ShadowFrame::DeleteDeoptimizedFrame(tmp);
179}
180
181TEST_F(UnstartedRuntimeTest, MemoryPeekShort) {
182  Thread* self = Thread::Current();
183
184  ScopedObjectAccess soa(self);
185  constexpr const uint8_t base_array[] = "abcdefghijklmnop";
186  constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
187  const uint8_t* base_ptr = base_array;
188
189  JValue result;
190  ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
191
192  int32_t adjusted_length = kBaseLen - sizeof(int16_t);
193  for (int32_t i = 0; i < adjusted_length; ++i) {
194    tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
195
196    UnstartedMemoryPeekShort(self, tmp, &result, 0);
197
198    typedef int16_t unaligned_short __attribute__ ((aligned (1)));
199    const unaligned_short* short_ptr = reinterpret_cast<const unaligned_short*>(base_ptr + i);
200    EXPECT_EQ(result.GetS(), *short_ptr);
201  }
202
203  ShadowFrame::DeleteDeoptimizedFrame(tmp);
204}
205
206TEST_F(UnstartedRuntimeTest, MemoryPeekInt) {
207  Thread* self = Thread::Current();
208
209  ScopedObjectAccess soa(self);
210  constexpr const uint8_t base_array[] = "abcdefghijklmnop";
211  constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
212  const uint8_t* base_ptr = base_array;
213
214  JValue result;
215  ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
216
217  int32_t adjusted_length = kBaseLen - sizeof(int32_t);
218  for (int32_t i = 0; i < adjusted_length; ++i) {
219    tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
220
221    UnstartedMemoryPeekInt(self, tmp, &result, 0);
222
223    typedef int32_t unaligned_int __attribute__ ((aligned (1)));
224    const unaligned_int* int_ptr = reinterpret_cast<const unaligned_int*>(base_ptr + i);
225    EXPECT_EQ(result.GetI(), *int_ptr);
226  }
227
228  ShadowFrame::DeleteDeoptimizedFrame(tmp);
229}
230
231TEST_F(UnstartedRuntimeTest, MemoryPeekLong) {
232  Thread* self = Thread::Current();
233
234  ScopedObjectAccess soa(self);
235  constexpr const uint8_t base_array[] = "abcdefghijklmnop";
236  constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
237  const uint8_t* base_ptr = base_array;
238
239  JValue result;
240  ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
241
242  int32_t adjusted_length = kBaseLen - sizeof(int64_t);
243  for (int32_t i = 0; i < adjusted_length; ++i) {
244    tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
245
246    UnstartedMemoryPeekLong(self, tmp, &result, 0);
247
248    typedef int64_t unaligned_long __attribute__ ((aligned (1)));
249    const unaligned_long* long_ptr = reinterpret_cast<const unaligned_long*>(base_ptr + i);
250    EXPECT_EQ(result.GetJ(), *long_ptr);
251  }
252
253  ShadowFrame::DeleteDeoptimizedFrame(tmp);
254}
255
256TEST_F(UnstartedRuntimeTest, StringGetCharsNoCheck) {
257  Thread* self = Thread::Current();
258
259  ScopedObjectAccess soa(self);
260  StackHandleScope<2> hs(self);
261  // TODO: Actual UTF.
262  constexpr const char base_string[] = "abcdefghijklmnop";
263  Handle<mirror::String> h_test_string(hs.NewHandle(
264      mirror::String::AllocFromModifiedUtf8(self, base_string)));
265  constexpr int32_t kBaseLen = sizeof(base_string) / sizeof(char) - 1;
266  Handle<mirror::CharArray> h_char_array(hs.NewHandle(
267      mirror::CharArray::Alloc(self, kBaseLen)));
268  // A buffer so we can make sure we only modify the elements targetted.
269  uint16_t buf[kBaseLen];
270
271  JValue result;
272  ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
273
274  for (int32_t start_index = 0; start_index < kBaseLen; ++start_index) {
275    for (int32_t count = 0; count <= kBaseLen; ++count) {
276      for (int32_t trg_offset = 0; trg_offset < kBaseLen; ++trg_offset) {
277        // Only do it when in bounds.
278        if (start_index + count <= kBaseLen && trg_offset + count <= kBaseLen) {
279          tmp->SetVRegReference(0, h_test_string.Get());
280          tmp->SetVReg(1, start_index);
281          tmp->SetVReg(2, count);
282          tmp->SetVRegReference(3, h_char_array.Get());
283          tmp->SetVReg(3, trg_offset);
284
285          // Copy the char_array into buf.
286          memcpy(buf, h_char_array->GetData(), kBaseLen * sizeof(uint16_t));
287
288          UnstartedStringCharAt(self, tmp, &result, 0);
289
290          uint16_t* data = h_char_array->GetData();
291
292          bool success = true;
293
294          // First segment should be unchanged.
295          for (int32_t i = 0; i < trg_offset; ++i) {
296            success = success && (data[i] == buf[i]);
297          }
298          // Second segment should be a copy.
299          for (int32_t i = trg_offset; i < trg_offset + count; ++i) {
300            success = success && (data[i] == buf[i - trg_offset + start_index]);
301          }
302          // Third segment should be unchanged.
303          for (int32_t i = trg_offset + count; i < kBaseLen; ++i) {
304            success = success && (data[i] == buf[i]);
305          }
306
307          EXPECT_TRUE(success);
308        }
309      }
310    }
311  }
312
313  ShadowFrame::DeleteDeoptimizedFrame(tmp);
314}
315
316TEST_F(UnstartedRuntimeTest, StringCharAt) {
317  Thread* self = Thread::Current();
318
319  ScopedObjectAccess soa(self);
320  // TODO: Actual UTF.
321  constexpr const char* base_string = "abcdefghijklmnop";
322  int32_t base_len = static_cast<int32_t>(strlen(base_string));
323  mirror::String* test_string = mirror::String::AllocFromModifiedUtf8(self, base_string);
324
325  JValue result;
326  ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
327
328  for (int32_t i = 0; i < base_len; ++i) {
329    tmp->SetVRegReference(0, test_string);
330    tmp->SetVReg(1, i);
331
332    UnstartedStringCharAt(self, tmp, &result, 0);
333
334    EXPECT_EQ(result.GetI(), base_string[i]);
335  }
336
337  ShadowFrame::DeleteDeoptimizedFrame(tmp);
338}
339
340TEST_F(UnstartedRuntimeTest, StringInit) {
341  Thread* self = Thread::Current();
342  ScopedObjectAccess soa(self);
343  mirror::Class* klass = mirror::String::GetJavaLangString();
344  ArtMethod* method = klass->FindDeclaredDirectMethod("<init>", "(Ljava/lang/String;)V",
345                                                      sizeof(void*));
346
347  // create instruction data for invoke-direct {v0, v1} of method with fake index
348  uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 };
349  const Instruction* inst = Instruction::At(inst_data);
350
351  JValue result;
352  ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0);
353  const char* base_string = "hello_world";
354  mirror::String* string_arg = mirror::String::AllocFromModifiedUtf8(self, base_string);
355  mirror::String* reference_empty_string = mirror::String::AllocFromModifiedUtf8(self, "");
356  shadow_frame->SetVRegReference(0, reference_empty_string);
357  shadow_frame->SetVRegReference(1, string_arg);
358
359  interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result);
360  mirror::String* string_result = reinterpret_cast<mirror::String*>(result.GetL());
361  EXPECT_EQ(string_arg->GetLength(), string_result->GetLength());
362  EXPECT_EQ(memcmp(string_arg->GetValue(), string_result->GetValue(),
363                   string_arg->GetLength() * sizeof(uint16_t)), 0);
364
365  ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
366}
367
368// Tests the exceptions that should be checked before modifying the destination.
369// (Doesn't check the object vs primitive case ATM.)
370TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTestExceptions) {
371  Thread* self = Thread::Current();
372  ScopedObjectAccess soa(self);
373  JValue result;
374  ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
375
376  // Note: all tests are not GC safe. Assume there's no GC running here with the few objects we
377  //       allocate.
378  StackHandleScope<2> hs_misc(self);
379  Handle<mirror::Class> object_class(
380      hs_misc.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
381
382  StackHandleScope<3> hs_data(self);
383  hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
384  hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
385  hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
386
387  Handle<mirror::ObjectArray<mirror::Object>> array(
388      hs_misc.NewHandle(CreateObjectArray(self, object_class.Get(), hs_data)));
389
390  RunArrayCopy(self, tmp, true, array.Get(), -1, array.Get(), 0, 0);
391  RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), -1, 0);
392  RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, -1);
393  RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, 4);
394  RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 1, 3);
395  RunArrayCopy(self, tmp, true, array.Get(), 1, array.Get(), 0, 3);
396
397  mirror::ObjectArray<mirror::Object>* class_as_array =
398      reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(object_class.Get());
399  RunArrayCopy(self, tmp, true, class_as_array, 0, array.Get(), 0, 0);
400  RunArrayCopy(self, tmp, true, array.Get(), 0, class_as_array, 0, 0);
401
402  ShadowFrame::DeleteDeoptimizedFrame(tmp);
403}
404
405TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
406  Thread* self = Thread::Current();
407  ScopedObjectAccess soa(self);
408  JValue result;
409  ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
410
411  StackHandleScope<1> hs_object(self);
412  Handle<mirror::Class> object_class(
413      hs_object.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
414
415  // Simple test:
416  // [1,2,3]{1 @ 2} into [4,5,6] = [4,2,6]
417  {
418    StackHandleScope<3> hs_src(self);
419    hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
420    hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
421    hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
422
423    StackHandleScope<3> hs_dst(self);
424    hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
425    hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
426    hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
427
428    StackHandleScope<3> hs_expected(self);
429    hs_expected.NewHandle(hs_dst.GetReference(0));
430    hs_expected.NewHandle(hs_dst.GetReference(1));
431    hs_expected.NewHandle(hs_src.GetReference(1));
432
433    RunArrayCopy(self,
434                 tmp,
435                 false,
436                 object_class.Get(),
437                 object_class.Get(),
438                 hs_src,
439                 1,
440                 hs_dst,
441                 2,
442                 1,
443                 hs_expected);
444  }
445
446  // Simple test:
447  // [1,2,3]{1 @ 1} into [4,5,6] = [4,2,6]  (with dst String[])
448  {
449    StackHandleScope<3> hs_src(self);
450    hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
451    hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
452    hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
453
454    StackHandleScope<3> hs_dst(self);
455    hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
456    hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
457    hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
458
459    StackHandleScope<3> hs_expected(self);
460    hs_expected.NewHandle(hs_dst.GetReference(0));
461    hs_expected.NewHandle(hs_src.GetReference(1));
462    hs_expected.NewHandle(hs_dst.GetReference(2));
463
464    RunArrayCopy(self,
465                 tmp,
466                 false,
467                 object_class.Get(),
468                 mirror::String::GetJavaLangString(),
469                 hs_src,
470                 1,
471                 hs_dst,
472                 1,
473                 1,
474                 hs_expected);
475  }
476
477  // Simple test:
478  // [1,*,3] into [4,5,6] = [1,5,6] + exc
479  {
480    StackHandleScope<3> hs_src(self);
481    hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
482    hs_src.NewHandle(mirror::String::GetJavaLangString());
483    hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
484
485    StackHandleScope<3> hs_dst(self);
486    hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
487    hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
488    hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
489
490    StackHandleScope<3> hs_expected(self);
491    hs_expected.NewHandle(hs_src.GetReference(0));
492    hs_expected.NewHandle(hs_dst.GetReference(1));
493    hs_expected.NewHandle(hs_dst.GetReference(2));
494
495    RunArrayCopy(self,
496                 tmp,
497                 true,
498                 object_class.Get(),
499                 mirror::String::GetJavaLangString(),
500                 hs_src,
501                 0,
502                 hs_dst,
503                 0,
504                 3,
505                 hs_expected);
506  }
507
508  ShadowFrame::DeleteDeoptimizedFrame(tmp);
509}
510
511}  // namespace interpreter
512}  // namespace art
513