1 /*
2  * Copyright (C) 2014 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 <stdint.h>
18 
19 #include "common_runtime_test.h"
20 #include "mirror/art_method-inl.h"
21 #include "quick/quick_method_frame_info.h"
22 
23 namespace art {
24 
25 class ArchTest : public CommonRuntimeTest {
26  protected:
CheckFrameSize(InstructionSet isa,Runtime::CalleeSaveType type,uint32_t save_size)27   static void CheckFrameSize(InstructionSet isa, Runtime::CalleeSaveType type, uint32_t save_size)
28       NO_THREAD_SAFETY_ANALYSIS {
29     Runtime* r = Runtime::Current();
30 
31     Thread* t = Thread::Current();
32     t->TransitionFromSuspendedToRunnable();  // So we can create callee-save methods.
33 
34     r->SetInstructionSet(isa);
35     mirror::ArtMethod* save_method = r->CreateCalleeSaveMethod(type);
36     r->SetCalleeSaveMethod(save_method, type);
37     QuickMethodFrameInfo frame_info = save_method->GetQuickFrameInfo();
38     EXPECT_EQ(frame_info.FrameSizeInBytes(), save_size) << "Expected and real size differs for "
39         << type << " core spills=" << std::hex << frame_info.CoreSpillMask() << " fp spills="
40         << frame_info.FpSpillMask() << std::dec;
41 
42     t->TransitionFromRunnableToSuspended(ThreadState::kNative);  // So we can shut down.
43   }
44 };
45 
46 
TEST_F(ArchTest,ARM)47 TEST_F(ArchTest, ARM) {
48 #include "arch/arm/asm_support_arm.h"
49 #undef ART_RUNTIME_ARCH_ARM_ASM_SUPPORT_ARM_H_
50 
51 
52 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
53   CheckFrameSize(InstructionSet::kArm, Runtime::kSaveAll, FRAME_SIZE_SAVE_ALL_CALLEE_SAVE);
54 #else
55   LOG(WARNING) << "No frame size for SaveAll";
56 #endif
57 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
58   CheckFrameSize(InstructionSet::kArm, Runtime::kRefsOnly, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE);
59 #else
60   LOG(WARNING) << "No frame size for RefsOnly";
61 #endif
62 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
63   CheckFrameSize(InstructionSet::kArm, Runtime::kRefsAndArgs, FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE);
64 #else
65   LOG(WARNING) << "No frame size for RefsAndArgs";
66 #endif
67 
68 
69 #ifdef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
70 #undef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
71 #endif
72 #ifdef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
73 #undef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
74 #endif
75 #ifdef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
76 #undef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
77 #endif
78 #ifdef THREAD_SELF_OFFSET
79 #undef THREAD_SELF_OFFSET
80 #endif
81 #ifdef THREAD_CARD_TABLE_OFFSET
82 #undef THREAD_CARD_TABLE_OFFSET
83 #endif
84 #ifdef THREAD_EXCEPTION_OFFSET
85 #undef THREAD_EXCEPTION_OFFSET
86 #endif
87 #ifdef THREAD_ID_OFFSET
88 #undef THREAD_ID_OFFSET
89 #endif
90 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
91 #undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
92 #endif
93 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
94 #undef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
95 #endif
96 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
97 #undef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
98 #endif
99 #ifdef HEAP_REFERENCE_SIZE
100 #undef HEAP_REFERENCE_SIZE
101 #endif
102 }
103 
104 
TEST_F(ArchTest,ARM64)105 TEST_F(ArchTest, ARM64) {
106 #include "arch/arm64/asm_support_arm64.h"
107 #undef ART_RUNTIME_ARCH_ARM64_ASM_SUPPORT_ARM64_H_
108 
109 
110 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
111   CheckFrameSize(InstructionSet::kArm64, Runtime::kSaveAll, FRAME_SIZE_SAVE_ALL_CALLEE_SAVE);
112 #else
113   LOG(WARNING) << "No frame size for SaveAll";
114 #endif
115 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
116   CheckFrameSize(InstructionSet::kArm64, Runtime::kRefsOnly, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE);
117 #else
118   LOG(WARNING) << "No frame size for RefsOnly";
119 #endif
120 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
121   CheckFrameSize(InstructionSet::kArm64, Runtime::kRefsAndArgs, FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE);
122 #else
123   LOG(WARNING) << "No frame size for RefsAndArgs";
124 #endif
125 
126 
127 #ifdef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
128 #undef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
129 #endif
130 #ifdef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
131 #undef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
132 #endif
133 #ifdef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
134 #undef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
135 #endif
136 #ifdef THREAD_SELF_OFFSET
137 #undef THREAD_SELF_OFFSET
138 #endif
139 #ifdef THREAD_CARD_TABLE_OFFSET
140 #undef THREAD_CARD_TABLE_OFFSET
141 #endif
142 #ifdef THREAD_EXCEPTION_OFFSET
143 #undef THREAD_EXCEPTION_OFFSET
144 #endif
145 #ifdef THREAD_ID_OFFSET
146 #undef THREAD_ID_OFFSET
147 #endif
148 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
149 #undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
150 #endif
151 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
152 #undef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
153 #endif
154 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
155 #undef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
156 #endif
157 #ifdef HEAP_REFERENCE_SIZE
158 #undef HEAP_REFERENCE_SIZE
159 #endif
160 }
161 
162 
TEST_F(ArchTest,MIPS)163 TEST_F(ArchTest, MIPS) {
164 #include "arch/mips/asm_support_mips.h"
165 #undef ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_H_
166 
167 
168 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
169   CheckFrameSize(InstructionSet::kMips, Runtime::kSaveAll, FRAME_SIZE_SAVE_ALL_CALLEE_SAVE);
170 #else
171   LOG(WARNING) << "No frame size for SaveAll";
172 #endif
173 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
174   CheckFrameSize(InstructionSet::kMips, Runtime::kRefsOnly, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE);
175 #else
176   LOG(WARNING) << "No frame size for RefsOnly";
177 #endif
178 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
179   CheckFrameSize(InstructionSet::kMips, Runtime::kRefsAndArgs, FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE);
180 #else
181   LOG(WARNING) << "No frame size for RefsAndArgs";
182 #endif
183 
184 
185 #ifdef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
186 #undef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
187 #endif
188 #ifdef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
189 #undef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
190 #endif
191 #ifdef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
192 #undef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
193 #endif
194 #ifdef THREAD_SELF_OFFSET
195 #undef THREAD_SELF_OFFSET
196 #endif
197 #ifdef THREAD_CARD_TABLE_OFFSET
198 #undef THREAD_CARD_TABLE_OFFSET
199 #endif
200 #ifdef THREAD_EXCEPTION_OFFSET
201 #undef THREAD_EXCEPTION_OFFSET
202 #endif
203 #ifdef THREAD_ID_OFFSET
204 #undef THREAD_ID_OFFSET
205 #endif
206 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
207 #undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
208 #endif
209 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
210 #undef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
211 #endif
212 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
213 #undef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
214 #endif
215 #ifdef HEAP_REFERENCE_SIZE
216 #undef HEAP_REFERENCE_SIZE
217 #endif
218 }
219 
220 
TEST_F(ArchTest,X86)221 TEST_F(ArchTest, X86) {
222 #include "arch/x86/asm_support_x86.h"
223 #undef ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_H_
224 
225 
226 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
227   CheckFrameSize(InstructionSet::kX86, Runtime::kSaveAll, FRAME_SIZE_SAVE_ALL_CALLEE_SAVE);
228 #else
229   LOG(WARNING) << "No frame size for SaveAll";
230 #endif
231 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
232   CheckFrameSize(InstructionSet::kX86, Runtime::kRefsOnly, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE);
233 #else
234   LOG(WARNING) << "No frame size for RefsOnly";
235 #endif
236 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
237   CheckFrameSize(InstructionSet::kX86, Runtime::kRefsAndArgs, FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE);
238 #else
239   LOG(WARNING) << "No frame size for RefsAndArgs";
240 #endif
241 
242 
243 #ifdef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
244 #undef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
245 #endif
246 #ifdef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
247 #undef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
248 #endif
249 #ifdef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
250 #undef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
251 #endif
252 #ifdef THREAD_SELF_OFFSET
253 #undef THREAD_SELF_OFFSET
254 #endif
255 #ifdef THREAD_CARD_TABLE_OFFSET
256 #undef THREAD_CARD_TABLE_OFFSET
257 #endif
258 #ifdef THREAD_EXCEPTION_OFFSET
259 #undef THREAD_EXCEPTION_OFFSET
260 #endif
261 #ifdef THREAD_ID_OFFSET
262 #undef THREAD_ID_OFFSET
263 #endif
264 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
265 #undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
266 #endif
267 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
268 #undef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
269 #endif
270 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
271 #undef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
272 #endif
273 #ifdef HEAP_REFERENCE_SIZE
274 #undef HEAP_REFERENCE_SIZE
275 #endif
276 }
277 
278 
TEST_F(ArchTest,X86_64)279 TEST_F(ArchTest, X86_64) {
280 #include "arch/x86_64/asm_support_x86_64.h"
281 #undef ART_RUNTIME_ARCH_X86_64_ASM_SUPPORT_X86_64_H_
282 
283 
284 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
285   CheckFrameSize(InstructionSet::kX86_64, Runtime::kSaveAll, FRAME_SIZE_SAVE_ALL_CALLEE_SAVE);
286 #else
287   LOG(WARNING) << "No frame size for SaveAll";
288 #endif
289 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
290   CheckFrameSize(InstructionSet::kX86_64, Runtime::kRefsOnly, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE);
291 #else
292   LOG(WARNING) << "No frame size for RefsOnly";
293 #endif
294 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
295   CheckFrameSize(InstructionSet::kX86_64, Runtime::kRefsAndArgs, FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE);
296 #else
297   LOG(WARNING) << "No frame size for RefsAndArgs";
298 #endif
299 
300 
301 #ifdef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
302 #undef RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET
303 #endif
304 #ifdef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
305 #undef RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET
306 #endif
307 #ifdef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
308 #undef RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET
309 #endif
310 #ifdef THREAD_SELF_OFFSET
311 #undef THREAD_SELF_OFFSET
312 #endif
313 #ifdef THREAD_CARD_TABLE_OFFSET
314 #undef THREAD_CARD_TABLE_OFFSET
315 #endif
316 #ifdef THREAD_EXCEPTION_OFFSET
317 #undef THREAD_EXCEPTION_OFFSET
318 #endif
319 #ifdef THREAD_ID_OFFSET
320 #undef THREAD_ID_OFFSET
321 #endif
322 #ifdef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
323 #undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVE
324 #endif
325 #ifdef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
326 #undef FRAME_SIZE_REFS_ONLY_CALLEE_SAVE
327 #endif
328 #ifdef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
329 #undef FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE
330 #endif
331 #ifdef HEAP_REFERENCE_SIZE
332 #undef HEAP_REFERENCE_SIZE
333 #endif
334 }
335 
336 
337 // The following tests are all for the running architecture. So we get away
338 // with just including it and not undefining it every time.
339 
340 #if defined(__arm__)
341 #include "arch/arm/asm_support_arm.h"
342 #elif defined(__aarch64__)
343 #include "arch/arm64/asm_support_arm64.h"
344 #elif defined(__mips__)
345 #include "arch/mips/asm_support_mips.h"
346 #elif defined(__i386__)
347 #include "arch/x86/asm_support_x86.h"
348 #elif defined(__x86_64__)
349 #include "arch/x86_64/asm_support_x86_64.h"
350 #else
351   // This happens for the host test.
352 #ifdef __LP64__
353 #include "arch/x86_64/asm_support_x86_64.h"
354 #else
355 #include "arch/x86/asm_support_x86.h"
356 #endif
357 #endif
358 
359 
TEST_F(ArchTest,ThreadOffsets)360 TEST_F(ArchTest, ThreadOffsets) {
361   // Ugly hack, change when possible.
362 #ifdef __LP64__
363 #define POINTER_SIZE 8
364 #else
365 #define POINTER_SIZE 4
366 #endif
367 
368 #if defined(THREAD_SELF_OFFSET)
369   ThreadOffset<POINTER_SIZE> self_offset = Thread::SelfOffset<POINTER_SIZE>();
370   EXPECT_EQ(self_offset.Int32Value(), THREAD_SELF_OFFSET);
371 #else
372   LOG(INFO) << "No Thread Self Offset found.";
373 #endif
374 
375 #if defined(THREAD_CARD_TABLE_OFFSET)
376   ThreadOffset<POINTER_SIZE> card_offset = Thread::CardTableOffset<POINTER_SIZE>();
377   EXPECT_EQ(card_offset.Int32Value(), THREAD_CARD_TABLE_OFFSET);
378 #else
379   LOG(INFO) << "No Thread Card Table Offset found.";
380 #endif
381 
382 #if defined(THREAD_EXCEPTION_OFFSET)
383   ThreadOffset<POINTER_SIZE> exc_offset = Thread::ExceptionOffset<POINTER_SIZE>();
384     EXPECT_EQ(exc_offset.Int32Value(), THREAD_EXCEPTION_OFFSET);
385 #else
386   LOG(INFO) << "No Thread Exception Offset found.";
387 #endif
388 
389 #if defined(THREAD_ID_OFFSET)
390   ThreadOffset<POINTER_SIZE> id_offset = Thread::ThinLockIdOffset<POINTER_SIZE>();
391   EXPECT_EQ(id_offset.Int32Value(), THREAD_ID_OFFSET);
392 #else
393   LOG(INFO) << "No Thread ID Offset found.";
394 #endif
395 }
396 
397 
TEST_F(ArchTest,CalleeSaveMethodOffsets)398 TEST_F(ArchTest, CalleeSaveMethodOffsets) {
399 #if defined(RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET)
400   EXPECT_EQ(Runtime::GetCalleeSaveMethodOffset(Runtime::kSaveAll),
401             static_cast<size_t>(RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET));
402 #else
403   LOG(INFO) << "No Runtime Save-all Offset found.";
404 #endif
405 
406 #if defined(RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET)
407   EXPECT_EQ(Runtime::GetCalleeSaveMethodOffset(Runtime::kRefsOnly),
408             static_cast<size_t>(RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET));
409 #else
410   LOG(INFO) << "No Runtime Refs-only Offset found.";
411 #endif
412 
413 #if defined(RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET)
414   EXPECT_EQ(Runtime::GetCalleeSaveMethodOffset(Runtime::kRefsAndArgs),
415             static_cast<size_t>(RUNTIME_REF_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET));
416 #else
417   LOG(INFO) << "No Runtime Refs-and-Args Offset found.";
418 #endif
419 }
420 
421 
TEST_F(ArchTest,HeapReferenceSize)422 TEST_F(ArchTest, HeapReferenceSize) {
423 #if defined(HEAP_REFERENCE_SIZE)
424   EXPECT_EQ(sizeof(mirror::HeapReference<mirror::Object>),
425             static_cast<size_t>(HEAP_REFERENCE_SIZE));
426 #else
427   LOG(INFO) << "No expected HeapReference Size found.";
428 #endif
429 }
430 
TEST_F(ArchTest,StackReferenceSize)431 TEST_F(ArchTest, StackReferenceSize) {
432 #if defined(STACK_REFERENCE_SIZE)
433   EXPECT_EQ(sizeof(StackReference<mirror::Object>),
434             static_cast<size_t>(STACK_REFERENCE_SIZE));
435 #else
436   LOG(INFO) << "No expected StackReference Size #define found.";
437 #endif
438 }
439 
440 }  // namespace art
441