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 
31 namespace art {
32 namespace interpreter {
33 
34 class 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_LOCKS_REQUIRED(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_LOCKS_REQUIRED(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 
TEST_F(UnstartedRuntimeTest,MemoryPeekByte)71 TEST_F(UnstartedRuntimeTest, MemoryPeekByte) {
72   Thread* self = Thread::Current();
73 
74   ScopedObjectAccess soa(self);
75   constexpr const uint8_t base_array[] = "abcdefghijklmnop";
76   constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
77   const uint8_t* base_ptr = base_array;
78 
79   JValue result;
80   ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
81 
82   for (int32_t i = 0; i < kBaseLen; ++i) {
83     tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
84 
85     UnstartedMemoryPeekByte(self, tmp, &result, 0);
86 
87     EXPECT_EQ(result.GetB(), static_cast<int8_t>(base_array[i]));
88   }
89 
90   ShadowFrame::DeleteDeoptimizedFrame(tmp);
91 }
92 
TEST_F(UnstartedRuntimeTest,MemoryPeekShort)93 TEST_F(UnstartedRuntimeTest, MemoryPeekShort) {
94   Thread* self = Thread::Current();
95 
96   ScopedObjectAccess soa(self);
97   constexpr const uint8_t base_array[] = "abcdefghijklmnop";
98   constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
99   const uint8_t* base_ptr = base_array;
100 
101   JValue result;
102   ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
103 
104   int32_t adjusted_length = kBaseLen - sizeof(int16_t);
105   for (int32_t i = 0; i < adjusted_length; ++i) {
106     tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
107 
108     UnstartedMemoryPeekShort(self, tmp, &result, 0);
109 
110     typedef int16_t unaligned_short __attribute__ ((aligned (1)));
111     const unaligned_short* short_ptr = reinterpret_cast<const unaligned_short*>(base_ptr + i);
112     EXPECT_EQ(result.GetS(), *short_ptr);
113   }
114 
115   ShadowFrame::DeleteDeoptimizedFrame(tmp);
116 }
117 
TEST_F(UnstartedRuntimeTest,MemoryPeekInt)118 TEST_F(UnstartedRuntimeTest, MemoryPeekInt) {
119   Thread* self = Thread::Current();
120 
121   ScopedObjectAccess soa(self);
122   constexpr const uint8_t base_array[] = "abcdefghijklmnop";
123   constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
124   const uint8_t* base_ptr = base_array;
125 
126   JValue result;
127   ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
128 
129   int32_t adjusted_length = kBaseLen - sizeof(int32_t);
130   for (int32_t i = 0; i < adjusted_length; ++i) {
131     tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
132 
133     UnstartedMemoryPeekInt(self, tmp, &result, 0);
134 
135     typedef int32_t unaligned_int __attribute__ ((aligned (1)));
136     const unaligned_int* int_ptr = reinterpret_cast<const unaligned_int*>(base_ptr + i);
137     EXPECT_EQ(result.GetI(), *int_ptr);
138   }
139 
140   ShadowFrame::DeleteDeoptimizedFrame(tmp);
141 }
142 
TEST_F(UnstartedRuntimeTest,MemoryPeekLong)143 TEST_F(UnstartedRuntimeTest, MemoryPeekLong) {
144   Thread* self = Thread::Current();
145 
146   ScopedObjectAccess soa(self);
147   constexpr const uint8_t base_array[] = "abcdefghijklmnop";
148   constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
149   const uint8_t* base_ptr = base_array;
150 
151   JValue result;
152   ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
153 
154   int32_t adjusted_length = kBaseLen - sizeof(int64_t);
155   for (int32_t i = 0; i < adjusted_length; ++i) {
156     tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
157 
158     UnstartedMemoryPeekLong(self, tmp, &result, 0);
159 
160     typedef int64_t unaligned_long __attribute__ ((aligned (1)));
161     const unaligned_long* long_ptr = reinterpret_cast<const unaligned_long*>(base_ptr + i);
162     EXPECT_EQ(result.GetJ(), *long_ptr);
163   }
164 
165   ShadowFrame::DeleteDeoptimizedFrame(tmp);
166 }
167 
TEST_F(UnstartedRuntimeTest,StringGetCharsNoCheck)168 TEST_F(UnstartedRuntimeTest, StringGetCharsNoCheck) {
169   Thread* self = Thread::Current();
170 
171   ScopedObjectAccess soa(self);
172   StackHandleScope<2> hs(self);
173   // TODO: Actual UTF.
174   constexpr const char base_string[] = "abcdefghijklmnop";
175   Handle<mirror::String> h_test_string(hs.NewHandle(
176       mirror::String::AllocFromModifiedUtf8(self, base_string)));
177   constexpr int32_t kBaseLen = sizeof(base_string) / sizeof(char) - 1;
178   Handle<mirror::CharArray> h_char_array(hs.NewHandle(
179       mirror::CharArray::Alloc(self, kBaseLen)));
180   // A buffer so we can make sure we only modify the elements targetted.
181   uint16_t buf[kBaseLen];
182 
183   JValue result;
184   ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
185 
186   for (int32_t start_index = 0; start_index < kBaseLen; ++start_index) {
187     for (int32_t count = 0; count <= kBaseLen; ++count) {
188       for (int32_t trg_offset = 0; trg_offset < kBaseLen; ++trg_offset) {
189         // Only do it when in bounds.
190         if (start_index + count <= kBaseLen && trg_offset + count <= kBaseLen) {
191           tmp->SetVRegReference(0, h_test_string.Get());
192           tmp->SetVReg(1, start_index);
193           tmp->SetVReg(2, count);
194           tmp->SetVRegReference(3, h_char_array.Get());
195           tmp->SetVReg(3, trg_offset);
196 
197           // Copy the char_array into buf.
198           memcpy(buf, h_char_array->GetData(), kBaseLen * sizeof(uint16_t));
199 
200           UnstartedStringCharAt(self, tmp, &result, 0);
201 
202           uint16_t* data = h_char_array->GetData();
203 
204           bool success = true;
205 
206           // First segment should be unchanged.
207           for (int32_t i = 0; i < trg_offset; ++i) {
208             success = success && (data[i] == buf[i]);
209           }
210           // Second segment should be a copy.
211           for (int32_t i = trg_offset; i < trg_offset + count; ++i) {
212             success = success && (data[i] == buf[i - trg_offset + start_index]);
213           }
214           // Third segment should be unchanged.
215           for (int32_t i = trg_offset + count; i < kBaseLen; ++i) {
216             success = success && (data[i] == buf[i]);
217           }
218 
219           EXPECT_TRUE(success);
220         }
221       }
222     }
223   }
224 
225   ShadowFrame::DeleteDeoptimizedFrame(tmp);
226 }
227 
TEST_F(UnstartedRuntimeTest,StringCharAt)228 TEST_F(UnstartedRuntimeTest, StringCharAt) {
229   Thread* self = Thread::Current();
230 
231   ScopedObjectAccess soa(self);
232   // TODO: Actual UTF.
233   constexpr const char* base_string = "abcdefghijklmnop";
234   int32_t base_len = static_cast<int32_t>(strlen(base_string));
235   mirror::String* test_string = mirror::String::AllocFromModifiedUtf8(self, base_string);
236 
237   JValue result;
238   ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
239 
240   for (int32_t i = 0; i < base_len; ++i) {
241     tmp->SetVRegReference(0, test_string);
242     tmp->SetVReg(1, i);
243 
244     UnstartedStringCharAt(self, tmp, &result, 0);
245 
246     EXPECT_EQ(result.GetI(), base_string[i]);
247   }
248 
249   ShadowFrame::DeleteDeoptimizedFrame(tmp);
250 }
251 
TEST_F(UnstartedRuntimeTest,StringInit)252 TEST_F(UnstartedRuntimeTest, StringInit) {
253   Thread* self = Thread::Current();
254   ScopedObjectAccess soa(self);
255   mirror::Class* klass = mirror::String::GetJavaLangString();
256   ArtMethod* method = klass->FindDeclaredDirectMethod("<init>", "(Ljava/lang/String;)V",
257                                                       sizeof(void*));
258 
259   // create instruction data for invoke-direct {v0, v1} of method with fake index
260   uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 };
261   const Instruction* inst = Instruction::At(inst_data);
262 
263   JValue result;
264   ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0);
265   const char* base_string = "hello_world";
266   mirror::String* string_arg = mirror::String::AllocFromModifiedUtf8(self, base_string);
267   mirror::String* reference_empty_string = mirror::String::AllocFromModifiedUtf8(self, "");
268   shadow_frame->SetVRegReference(0, reference_empty_string);
269   shadow_frame->SetVRegReference(1, string_arg);
270 
271   interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result);
272   mirror::String* string_result = reinterpret_cast<mirror::String*>(result.GetL());
273   EXPECT_EQ(string_arg->GetLength(), string_result->GetLength());
274   EXPECT_EQ(memcmp(string_arg->GetValue(), string_result->GetValue(),
275                    string_arg->GetLength() * sizeof(uint16_t)), 0);
276 
277   ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
278 }
279 
280 }  // namespace interpreter
281 }  // namespace art
282