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 "art_method-inl.h"
20#include "base/callee_save_type.h"
21#include "common_runtime_test.h"
22#include "quick/quick_method_frame_info.h"
23
24// asm_support.h declares tests next to the #defines. We use asm_support_check.h to (safely)
25// generate CheckAsmSupportOffsetsAndSizes using gtest's EXPECT for the tests. We also use the
26// RETURN_TYPE, HEADER and FOOTER defines from asm_support_check.h to try to ensure that any
27// tests are actually generated.
28
29// Let CheckAsmSupportOffsetsAndSizes return a size_t (the count).
30#define ASM_SUPPORT_CHECK_RETURN_TYPE size_t
31
32// Declare the counter that will be updated per test.
33#define ASM_SUPPORT_CHECK_HEADER size_t count = 0;
34
35// Use EXPECT_EQ for tests, and increment the counter.
36#define ADD_TEST_EQ(x, y) EXPECT_EQ(x, y); count++;
37
38// Return the counter at the end of CheckAsmSupportOffsetsAndSizes.
39#define ASM_SUPPORT_CHECK_FOOTER return count;
40
41// Generate CheckAsmSupportOffsetsAndSizes().
42#include "asm_support_check.h"
43
44namespace art {
45
46class ArchTest : public CommonRuntimeTest {
47 protected:
48  void SetUpRuntimeOptions(RuntimeOptions *options) OVERRIDE {
49    // Use 64-bit ISA for runtime setup to make method size potentially larger
50    // than necessary (rather than smaller) during CreateCalleeSaveMethod
51    options->push_back(std::make_pair("imageinstructionset", "x86_64"));
52  }
53
54  // Do not do any of the finalization. We don't want to run any code, we don't need the heap
55  // prepared, it actually will be a problem with setting the instruction set to x86_64 in
56  // SetUpRuntimeOptions.
57  void FinalizeSetup() OVERRIDE {
58    ASSERT_EQ(InstructionSet::kX86_64, Runtime::Current()->GetInstructionSet());
59  }
60
61  static void CheckFrameSize(InstructionSet isa, CalleeSaveType type, uint32_t save_size)
62      NO_THREAD_SAFETY_ANALYSIS {
63    Runtime* const runtime = Runtime::Current();
64    Thread* const self = Thread::Current();
65    ScopedObjectAccess soa(self);  // So we can create callee-save methods.
66
67    runtime->SetInstructionSet(isa);
68    ArtMethod* save_method = runtime->CreateCalleeSaveMethod();
69    runtime->SetCalleeSaveMethod(save_method, type);
70    QuickMethodFrameInfo frame_info =  runtime->GetRuntimeMethodFrameInfo(save_method);
71    EXPECT_EQ(frame_info.FrameSizeInBytes(), save_size) << "Expected and real size differs for "
72        << type << " core spills=" << std::hex << frame_info.CoreSpillMask() << " fp spills="
73        << frame_info.FpSpillMask() << std::dec;
74  }
75};
76
77TEST_F(ArchTest, CheckCommonOffsetsAndSizes) {
78  size_t test_count = CheckAsmSupportOffsetsAndSizes();
79  EXPECT_GT(test_count, 0u);
80}
81
82// Grab architecture specific constants.
83namespace arm {
84#include "arch/arm/asm_support_arm.h"
85static constexpr size_t kFrameSizeSaveAllCalleeSaves = FRAME_SIZE_SAVE_ALL_CALLEE_SAVES;
86#undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVES
87static constexpr size_t kFrameSizeSaveRefsOnly = FRAME_SIZE_SAVE_REFS_ONLY;
88#undef FRAME_SIZE_SAVE_REFS_ONLY
89static constexpr size_t kFrameSizeSaveRefsAndArgs = FRAME_SIZE_SAVE_REFS_AND_ARGS;
90#undef FRAME_SIZE_SAVE_REFS_AND_ARGS
91static constexpr size_t kFrameSizeSaveEverythingForClinit = FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT;
92#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT
93static constexpr size_t kFrameSizeSaveEverythingForSuspendCheck =
94    FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK;
95#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK
96static constexpr size_t kFrameSizeSaveEverything = FRAME_SIZE_SAVE_EVERYTHING;
97#undef FRAME_SIZE_SAVE_EVERYTHING
98#undef BAKER_MARK_INTROSPECTION_FIELD_LDR_NARROW_ENTRYPOINT_OFFSET
99#undef BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_WIDE_ENTRYPOINT_OFFSET
100#undef BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_NARROW_ENTRYPOINT_OFFSET
101#undef BAKER_MARK_INTROSPECTION_ARRAY_SWITCH_OFFSET
102#undef BAKER_MARK_INTROSPECTION_FIELD_LDR_WIDE_OFFSET
103#undef BAKER_MARK_INTROSPECTION_FIELD_LDR_NARROW_OFFSET
104#undef BAKER_MARK_INTROSPECTION_ARRAY_LDR_OFFSET
105#undef BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_WIDE_OFFSET
106#undef BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_NARROW_OFFSET
107}  // namespace arm
108
109namespace arm64 {
110#include "arch/arm64/asm_support_arm64.h"
111static constexpr size_t kFrameSizeSaveAllCalleeSaves = FRAME_SIZE_SAVE_ALL_CALLEE_SAVES;
112#undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVES
113static constexpr size_t kFrameSizeSaveRefsOnly = FRAME_SIZE_SAVE_REFS_ONLY;
114#undef FRAME_SIZE_SAVE_REFS_ONLY
115static constexpr size_t kFrameSizeSaveRefsAndArgs = FRAME_SIZE_SAVE_REFS_AND_ARGS;
116#undef FRAME_SIZE_SAVE_REFS_AND_ARGS
117static constexpr size_t kFrameSizeSaveEverythingForClinit = FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT;
118#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT
119static constexpr size_t kFrameSizeSaveEverythingForSuspendCheck =
120    FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK;
121#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK
122static constexpr size_t kFrameSizeSaveEverything = FRAME_SIZE_SAVE_EVERYTHING;
123#undef FRAME_SIZE_SAVE_EVERYTHING
124#undef BAKER_MARK_INTROSPECTION_ARRAY_SWITCH_OFFSET
125#undef BAKER_MARK_INTROSPECTION_GC_ROOT_ENTRYPOINT_OFFSET
126#undef BAKER_MARK_INTROSPECTION_FIELD_LDR_OFFSET
127#undef BAKER_MARK_INTROSPECTION_ARRAY_LDR_OFFSET
128#undef BAKER_MARK_INTROSPECTION_GC_ROOT_LDR_OFFSET
129}  // namespace arm64
130
131namespace mips {
132#include "arch/mips/asm_support_mips.h"
133static constexpr size_t kFrameSizeSaveAllCalleeSaves = FRAME_SIZE_SAVE_ALL_CALLEE_SAVES;
134#undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVES
135static constexpr size_t kFrameSizeSaveRefsOnly = FRAME_SIZE_SAVE_REFS_ONLY;
136#undef FRAME_SIZE_SAVE_REFS_ONLY
137static constexpr size_t kFrameSizeSaveRefsAndArgs = FRAME_SIZE_SAVE_REFS_AND_ARGS;
138#undef FRAME_SIZE_SAVE_REFS_AND_ARGS
139static constexpr size_t kFrameSizeSaveEverythingForClinit = FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT;
140#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT
141static constexpr size_t kFrameSizeSaveEverythingForSuspendCheck =
142    FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK;
143#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK
144static constexpr size_t kFrameSizeSaveEverything = FRAME_SIZE_SAVE_EVERYTHING;
145#undef FRAME_SIZE_SAVE_EVERYTHING
146#undef BAKER_MARK_INTROSPECTION_REGISTER_COUNT
147#undef BAKER_MARK_INTROSPECTION_FIELD_ARRAY_ENTRY_SIZE
148#undef BAKER_MARK_INTROSPECTION_GC_ROOT_ENTRIES_OFFSET
149#undef BAKER_MARK_INTROSPECTION_GC_ROOT_ENTRY_SIZE
150}  // namespace mips
151
152namespace mips64 {
153#include "arch/mips64/asm_support_mips64.h"
154static constexpr size_t kFrameSizeSaveAllCalleeSaves = FRAME_SIZE_SAVE_ALL_CALLEE_SAVES;
155#undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVES
156static constexpr size_t kFrameSizeSaveRefsOnly = FRAME_SIZE_SAVE_REFS_ONLY;
157#undef FRAME_SIZE_SAVE_REFS_ONLY
158static constexpr size_t kFrameSizeSaveRefsAndArgs = FRAME_SIZE_SAVE_REFS_AND_ARGS;
159#undef FRAME_SIZE_SAVE_REFS_AND_ARGS
160static constexpr size_t kFrameSizeSaveEverythingForClinit = FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT;
161#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT
162static constexpr size_t kFrameSizeSaveEverythingForSuspendCheck =
163    FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK;
164#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK
165static constexpr size_t kFrameSizeSaveEverything = FRAME_SIZE_SAVE_EVERYTHING;
166#undef FRAME_SIZE_SAVE_EVERYTHING
167#undef BAKER_MARK_INTROSPECTION_REGISTER_COUNT
168#undef BAKER_MARK_INTROSPECTION_FIELD_ARRAY_ENTRY_SIZE
169#undef BAKER_MARK_INTROSPECTION_GC_ROOT_ENTRIES_OFFSET
170#undef BAKER_MARK_INTROSPECTION_GC_ROOT_ENTRY_SIZE
171}  // namespace mips64
172
173namespace x86 {
174#include "arch/x86/asm_support_x86.h"
175static constexpr size_t kFrameSizeSaveAllCalleeSaves = FRAME_SIZE_SAVE_ALL_CALLEE_SAVES;
176#undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVES
177static constexpr size_t kFrameSizeSaveRefsOnly = FRAME_SIZE_SAVE_REFS_ONLY;
178#undef FRAME_SIZE_SAVE_REFS_ONLY
179static constexpr size_t kFrameSizeSaveRefsAndArgs = FRAME_SIZE_SAVE_REFS_AND_ARGS;
180#undef FRAME_SIZE_SAVE_REFS_AND_ARGS
181static constexpr size_t kFrameSizeSaveEverythingForClinit = FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT;
182#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT
183static constexpr size_t kFrameSizeSaveEverythingForSuspendCheck =
184    FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK;
185#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK
186static constexpr size_t kFrameSizeSaveEverything = FRAME_SIZE_SAVE_EVERYTHING;
187#undef FRAME_SIZE_SAVE_EVERYTHING
188}  // namespace x86
189
190namespace x86_64 {
191#include "arch/x86_64/asm_support_x86_64.h"
192static constexpr size_t kFrameSizeSaveAllCalleeSaves = FRAME_SIZE_SAVE_ALL_CALLEE_SAVES;
193#undef FRAME_SIZE_SAVE_ALL_CALLEE_SAVES
194static constexpr size_t kFrameSizeSaveRefsOnly = FRAME_SIZE_SAVE_REFS_ONLY;
195#undef FRAME_SIZE_SAVE_REFS_ONLY
196static constexpr size_t kFrameSizeSaveRefsAndArgs = FRAME_SIZE_SAVE_REFS_AND_ARGS;
197#undef FRAME_SIZE_SAVE_REFS_AND_ARGS
198static constexpr size_t kFrameSizeSaveEverythingForClinit = FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT;
199#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_CLINIT
200static constexpr size_t kFrameSizeSaveEverythingForSuspendCheck =
201    FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK;
202#undef FRAME_SIZE_SAVE_EVERYTHING_FOR_SUSPEND_CHECK
203static constexpr size_t kFrameSizeSaveEverything = FRAME_SIZE_SAVE_EVERYTHING;
204#undef FRAME_SIZE_SAVE_EVERYTHING
205}  // namespace x86_64
206
207// Check architecture specific constants are sound.
208#define TEST_ARCH(Arch, arch)                                       \
209  TEST_F(ArchTest, Arch) {                                          \
210    CheckFrameSize(InstructionSet::k##Arch,                         \
211                   CalleeSaveType::kSaveAllCalleeSaves,             \
212                   arch::kFrameSizeSaveAllCalleeSaves);             \
213    CheckFrameSize(InstructionSet::k##Arch,                         \
214                   CalleeSaveType::kSaveRefsOnly,                   \
215                   arch::kFrameSizeSaveRefsOnly);                   \
216    CheckFrameSize(InstructionSet::k##Arch,                         \
217                   CalleeSaveType::kSaveRefsAndArgs,                \
218                   arch::kFrameSizeSaveRefsAndArgs);                \
219    CheckFrameSize(InstructionSet::k##Arch,                         \
220                   CalleeSaveType::kSaveEverything,                 \
221                   arch::kFrameSizeSaveEverything);                 \
222    CheckFrameSize(InstructionSet::k##Arch,                         \
223                   CalleeSaveType::kSaveEverythingForClinit,        \
224                   arch::kFrameSizeSaveEverythingForClinit);        \
225    CheckFrameSize(InstructionSet::k##Arch,                         \
226                   CalleeSaveType::kSaveEverythingForSuspendCheck,  \
227                   arch::kFrameSizeSaveEverythingForSuspendCheck);  \
228  }
229TEST_ARCH(Arm, arm)
230TEST_ARCH(Arm64, arm64)
231TEST_ARCH(Mips, mips)
232TEST_ARCH(Mips64, mips64)
233TEST_ARCH(X86, x86)
234TEST_ARCH(X86_64, x86_64)
235
236}  // namespace art
237