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