blob: 34ab2779dca55a37a75b945024411789406833d9 [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
19#include "class_linker.h"
20#include "common_runtime_test.h"
21#include "handle.h"
22#include "handle_scope-inl.h"
23#include "mirror/class_loader.h"
24#include "mirror/string-inl.h"
25#include "runtime.h"
26#include "scoped_thread_state_change.h"
27#include "thread.h"
28
29namespace art {
30namespace interpreter {
31
32class UnstartedRuntimeTest : public CommonRuntimeTest {
33 protected:
34 // Re-expose all UnstartedRuntime implementations so we don't need to declare a million
35 // test friends.
36
37 // Methods that intercept available libcore implementations.
38#define UNSTARTED_DIRECT(Name, SigIgnored) \
39 static void Unstarted ## Name(Thread* self, \
40 ShadowFrame* shadow_frame, \
41 JValue* result, \
42 size_t arg_offset) \
43 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
44 interpreter::UnstartedRuntime::Unstarted ## Name(self, shadow_frame, result, arg_offset); \
45 }
46#include "unstarted_runtime_list.h"
47 UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
48#undef UNSTARTED_RUNTIME_DIRECT_LIST
49#undef UNSTARTED_RUNTIME_JNI_LIST
50#undef UNSTARTED_DIRECT
51
52 // Methods that are native.
53#define UNSTARTED_JNI(Name, SigIgnored) \
54 static void UnstartedJNI ## Name(Thread* self, \
55 mirror::ArtMethod* method, \
56 mirror::Object* receiver, \
57 uint32_t* args, \
58 JValue* result) \
59 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
60 interpreter::UnstartedRuntime::UnstartedJNI ## Name(self, method, receiver, args, result); \
61 }
62#include "unstarted_runtime_list.h"
63 UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
64#undef UNSTARTED_RUNTIME_DIRECT_LIST
65#undef UNSTARTED_RUNTIME_JNI_LIST
66#undef UNSTARTED_JNI
67};
68
69TEST_F(UnstartedRuntimeTest, MemoryPeekByte) {
70 Thread* self = Thread::Current();
71
72 ScopedObjectAccess soa(self);
73 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
74 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
75 const uint8_t* base_ptr = base_array;
76
77 JValue result;
78 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
79
80 for (int32_t i = 0; i < kBaseLen; ++i) {
81 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
82
83 UnstartedMemoryPeekByte(self, tmp, &result, 0);
84
85 EXPECT_EQ(result.GetB(), static_cast<int8_t>(base_array[i]));
86 }
87
88 ShadowFrame::DeleteDeoptimizedFrame(tmp);
89}
90
91TEST_F(UnstartedRuntimeTest, MemoryPeekShort) {
92 Thread* self = Thread::Current();
93
94 ScopedObjectAccess soa(self);
95 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
96 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
97 const uint8_t* base_ptr = base_array;
98
99 JValue result;
100 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
101
102 int32_t adjusted_length = kBaseLen - sizeof(int16_t);
103 for (int32_t i = 0; i < adjusted_length; ++i) {
104 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
105
106 UnstartedMemoryPeekShort(self, tmp, &result, 0);
107
108 typedef int16_t unaligned_short __attribute__ ((aligned (1)));
109 const unaligned_short* short_ptr = reinterpret_cast<const unaligned_short*>(base_ptr + i);
110 EXPECT_EQ(result.GetS(), *short_ptr);
111 }
112
113 ShadowFrame::DeleteDeoptimizedFrame(tmp);
114}
115
116TEST_F(UnstartedRuntimeTest, MemoryPeekInt) {
117 Thread* self = Thread::Current();
118
119 ScopedObjectAccess soa(self);
120 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
121 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
122 const uint8_t* base_ptr = base_array;
123
124 JValue result;
125 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
126
127 int32_t adjusted_length = kBaseLen - sizeof(int32_t);
128 for (int32_t i = 0; i < adjusted_length; ++i) {
129 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
130
131 UnstartedMemoryPeekInt(self, tmp, &result, 0);
132
133 typedef int32_t unaligned_int __attribute__ ((aligned (1)));
134 const unaligned_int* int_ptr = reinterpret_cast<const unaligned_int*>(base_ptr + i);
135 EXPECT_EQ(result.GetI(), *int_ptr);
136 }
137
138 ShadowFrame::DeleteDeoptimizedFrame(tmp);
139}
140
141TEST_F(UnstartedRuntimeTest, MemoryPeekLong) {
142 Thread* self = Thread::Current();
143
144 ScopedObjectAccess soa(self);
145 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
146 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
147 const uint8_t* base_ptr = base_array;
148
149 JValue result;
150 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
151
152 int32_t adjusted_length = kBaseLen - sizeof(int64_t);
153 for (int32_t i = 0; i < adjusted_length; ++i) {
154 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
155
156 UnstartedMemoryPeekLong(self, tmp, &result, 0);
157
158 typedef int64_t unaligned_long __attribute__ ((aligned (1)));
159 const unaligned_long* long_ptr = reinterpret_cast<const unaligned_long*>(base_ptr + i);
160 EXPECT_EQ(result.GetJ(), *long_ptr);
161 }
162
163 ShadowFrame::DeleteDeoptimizedFrame(tmp);
164}
165
166TEST_F(UnstartedRuntimeTest, StringGetCharsNoCheck) {
167 Thread* self = Thread::Current();
168
169 ScopedObjectAccess soa(self);
170 StackHandleScope<2> hs(self);
171 // TODO: Actual UTF.
172 constexpr const char base_string[] = "abcdefghijklmnop";
173 Handle<mirror::String> h_test_string(hs.NewHandle(
174 mirror::String::AllocFromModifiedUtf8(self, base_string)));
175 constexpr int32_t kBaseLen = sizeof(base_string) / sizeof(char) - 1;
176 Handle<mirror::CharArray> h_char_array(hs.NewHandle(
177 mirror::CharArray::Alloc(self, kBaseLen)));
178 // A buffer so we can make sure we only modify the elements targetted.
179 uint16_t buf[kBaseLen];
180
181 JValue result;
182 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
183
184 for (int32_t start_index = 0; start_index < kBaseLen; ++start_index) {
185 for (int32_t count = 0; count <= kBaseLen; ++count) {
186 for (int32_t trg_offset = 0; trg_offset < kBaseLen; ++trg_offset) {
187 // Only do it when in bounds.
188 if (start_index + count <= kBaseLen && trg_offset + count <= kBaseLen) {
189 tmp->SetVRegReference(0, h_test_string.Get());
190 tmp->SetVReg(1, start_index);
191 tmp->SetVReg(2, count);
192 tmp->SetVRegReference(3, h_char_array.Get());
193 tmp->SetVReg(3, trg_offset);
194
195 // Copy the char_array into buf.
196 memcpy(buf, h_char_array->GetData(), kBaseLen * sizeof(uint16_t));
197
198 UnstartedStringCharAt(self, tmp, &result, 0);
199
200 uint16_t* data = h_char_array->GetData();
201
202 bool success = true;
203
204 // First segment should be unchanged.
205 for (int32_t i = 0; i < trg_offset; ++i) {
206 success = success && (data[i] == buf[i]);
207 }
208 // Second segment should be a copy.
209 for (int32_t i = trg_offset; i < trg_offset + count; ++i) {
210 success = success && (data[i] == buf[i - trg_offset + start_index]);
211 }
212 // Third segment should be unchanged.
213 for (int32_t i = trg_offset + count; i < kBaseLen; ++i) {
214 success = success && (data[i] == buf[i]);
215 }
216
217 EXPECT_TRUE(success);
218 }
219 }
220 }
221 }
222
223 ShadowFrame::DeleteDeoptimizedFrame(tmp);
224}
225
226TEST_F(UnstartedRuntimeTest, StringCharAt) {
227 Thread* self = Thread::Current();
228
229 ScopedObjectAccess soa(self);
230 // TODO: Actual UTF.
231 constexpr const char* base_string = "abcdefghijklmnop";
232 int32_t base_len = static_cast<int32_t>(strlen(base_string));
233 mirror::String* test_string = mirror::String::AllocFromModifiedUtf8(self, base_string);
234
235 JValue result;
236 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
237
238 for (int32_t i = 0; i < base_len; ++i) {
239 tmp->SetVRegReference(0, test_string);
240 tmp->SetVReg(1, i);
241
242 UnstartedStringCharAt(self, tmp, &result, 0);
243
244 EXPECT_EQ(result.GetI(), base_string[i]);
245 }
246
247 ShadowFrame::DeleteDeoptimizedFrame(tmp);
248}
249
250} // namespace interpreter
251} // namespace art