141c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov/*
241c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov * Copyright (C) 2014 The Android Open Source Project
341c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov *
441c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov * Licensed under the Apache License, Version 2.0 (the "License");
541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov * you may not use this file except in compliance with the License.
641c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov * You may obtain a copy of the License at
741c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov *
841c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov *      http://www.apache.org/licenses/LICENSE-2.0
941c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov *
1041c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov * Unless required by applicable law or agreed to in writing, software
1141c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov * distributed under the License is distributed on an "AS IS" BASIS,
1241c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1341c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov * See the License for the specific language governing permissions and
1441c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov * limitations under the License.
1541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov */
1641c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
1741c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov#include <stdint.h>
1841c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
19e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h"
208228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe#include "base/callee_save_type.h"
2141c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov#include "callee_save_frame.h"
2241c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov#include "common_runtime_test.h"
2341c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov#include "quick/quick_method_frame_info.h"
2441c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
2541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalovnamespace art {
2641c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
2741c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalovclass QuickTrampolineEntrypointsTest : public CommonRuntimeTest {
2841c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov protected:
296d25419fa2dedbfcfea8b0a3066b064906c23b8aJeff Hao  void SetUpRuntimeOptions(RuntimeOptions *options) OVERRIDE {
306d25419fa2dedbfcfea8b0a3066b064906c23b8aJeff Hao    // Use 64-bit ISA for runtime setup to make method size potentially larger
316d25419fa2dedbfcfea8b0a3066b064906c23b8aJeff Hao    // than necessary (rather than smaller) during CreateCalleeSaveMethod
326d25419fa2dedbfcfea8b0a3066b064906c23b8aJeff Hao    options->push_back(std::make_pair("imageinstructionset", "x86_64"));
336d25419fa2dedbfcfea8b0a3066b064906c23b8aJeff Hao  }
346d25419fa2dedbfcfea8b0a3066b064906c23b8aJeff Hao
35a00f012660e9a4baa34c0ab96042f7146e9a6017Andreas Gampe  // Do not do any of the finalization. We don't want to run any code, we don't need the heap
36a00f012660e9a4baa34c0ab96042f7146e9a6017Andreas Gampe  // prepared, it actually will be a problem with setting the instruction set to x86_64 in
37a00f012660e9a4baa34c0ab96042f7146e9a6017Andreas Gampe  // SetUpRuntimeOptions.
38a00f012660e9a4baa34c0ab96042f7146e9a6017Andreas Gampe  void FinalizeSetup() OVERRIDE {
39a00f012660e9a4baa34c0ab96042f7146e9a6017Andreas Gampe    ASSERT_EQ(InstructionSet::kX86_64, Runtime::Current()->GetInstructionSet());
40a00f012660e9a4baa34c0ab96042f7146e9a6017Andreas Gampe  }
41a00f012660e9a4baa34c0ab96042f7146e9a6017Andreas Gampe
428228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe  static ArtMethod* CreateCalleeSaveMethod(InstructionSet isa, CalleeSaveType type)
4341c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov      NO_THREAD_SAFETY_ANALYSIS {
4441c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov    Runtime* r = Runtime::Current();
4541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
4641c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov    Thread* t = Thread::Current();
47f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier
48f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier    ScopedObjectAccess soa(t);
4941c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
5041c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov    r->SetInstructionSet(isa);
51e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* save_method = r->CreateCalleeSaveMethod();
5241c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov    r->SetCalleeSaveMethod(save_method, type);
5341c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
5441c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov    return save_method;
5541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov  }
5641c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
578228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe  static void CheckFrameSize(InstructionSet isa, CalleeSaveType type, uint32_t save_size)
5841c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov      NO_THREAD_SAFETY_ANALYSIS {
59e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* save_method = CreateCalleeSaveMethod(isa, type);
60524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    QuickMethodFrameInfo frame_info = Runtime::Current()->GetRuntimeMethodFrameInfo(save_method);
6141c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov    EXPECT_EQ(frame_info.FrameSizeInBytes(), save_size) << "Expected and real size differs for "
6241c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov        << type << " core spills=" << std::hex << frame_info.CoreSpillMask() << " fp spills="
6341c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov        << frame_info.FpSpillMask() << std::dec << " ISA " << isa;
6441c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov  }
6541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
668228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe  static void CheckPCOffset(InstructionSet isa, CalleeSaveType type, size_t pc_offset)
6741c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov      NO_THREAD_SAFETY_ANALYSIS {
68e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    ArtMethod* save_method = CreateCalleeSaveMethod(isa, type);
69524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    QuickMethodFrameInfo frame_info = Runtime::Current()->GetRuntimeMethodFrameInfo(save_method);
70524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray    EXPECT_EQ(frame_info.GetReturnPcOffset(), pc_offset)
716f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers        << "Expected and real pc offset differs for " << type
726f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers        << " core spills=" << std::hex << frame_info.CoreSpillMask()
736f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers        << " fp spills=" << frame_info.FpSpillMask() << std::dec << " ISA " << isa;
7441c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov  }
7541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov};
7641c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
7741c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov// Note: these tests are all runtime tests. They let the Runtime create the corresponding ArtMethod
7841c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov// and check against it. Technically we know and expect certain values, but the Runtime code is
7941c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov// not constexpr, so we cannot make this compile-time checks (and I want the Runtime code tested).
8041c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
8141c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov// This test ensures that kQuickCalleeSaveFrame_RefAndArgs_FrameSize is correct.
8241c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei ZavjalovTEST_F(QuickTrampolineEntrypointsTest, FrameSize) {
8341c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov  // We have to use a define here as the callee_save_frame.h functions are constexpr.
848228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe#define CHECK_FRAME_SIZE(isa)                                                        \
858228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe  CheckFrameSize(isa,                                                                \
868228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe                 CalleeSaveType::kSaveRefsAndArgs,                                   \
878228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe                 GetCalleeSaveFrameSize(isa, CalleeSaveType::kSaveRefsAndArgs));     \
888228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe  CheckFrameSize(isa,                                                                \
898228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe                 CalleeSaveType::kSaveRefsOnly,                                      \
908228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe                 GetCalleeSaveFrameSize(isa, CalleeSaveType::kSaveRefsOnly));        \
918228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe  CheckFrameSize(isa,                                                                \
928228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe                 CalleeSaveType::kSaveAllCalleeSaves,                                \
930a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                 GetCalleeSaveFrameSize(isa, CalleeSaveType::kSaveAllCalleeSaves));  \
940a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang  CheckFrameSize(isa,                                                                \
950a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                 CalleeSaveType::kSaveEverything,                                    \
960a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                 GetCalleeSaveFrameSize(isa, CalleeSaveType::kSaveEverything));      \
970a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang  CheckFrameSize(isa,                                                                \
980a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                 CalleeSaveType::kSaveEverythingForClinit,                           \
990a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                 GetCalleeSaveFrameSize(isa,                                         \
1000a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                                        CalleeSaveType::kSaveEverythingForClinit));  \
1010a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang  CheckFrameSize(isa,                                                                \
1020a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                 CalleeSaveType::kSaveEverythingForSuspendCheck,                     \
1030a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                 GetCalleeSaveFrameSize(                                             \
1040a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                     isa, CalleeSaveType::kSaveEverythingForSuspendCheck))
10541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
10633bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  CHECK_FRAME_SIZE(InstructionSet::kArm);
10733bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  CHECK_FRAME_SIZE(InstructionSet::kArm64);
10833bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  CHECK_FRAME_SIZE(InstructionSet::kMips);
10933bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  CHECK_FRAME_SIZE(InstructionSet::kMips64);
11033bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  CHECK_FRAME_SIZE(InstructionSet::kX86);
11133bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  CHECK_FRAME_SIZE(InstructionSet::kX86_64);
11241c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov}
11341c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
11441c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov// This test ensures that GetConstExprPointerSize is correct with respect to
11541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov// GetInstructionSetPointerSize.
11641c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei ZavjalovTEST_F(QuickTrampolineEntrypointsTest, PointerSize) {
11733bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  EXPECT_EQ(GetInstructionSetPointerSize(InstructionSet::kArm),
11833bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko            GetConstExprPointerSize(InstructionSet::kArm));
11933bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  EXPECT_EQ(GetInstructionSetPointerSize(InstructionSet::kArm64),
12033bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko            GetConstExprPointerSize(InstructionSet::kArm64));
12133bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  EXPECT_EQ(GetInstructionSetPointerSize(InstructionSet::kMips),
12233bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko            GetConstExprPointerSize(InstructionSet::kMips));
12333bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  EXPECT_EQ(GetInstructionSetPointerSize(InstructionSet::kMips64),
12433bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko            GetConstExprPointerSize(InstructionSet::kMips64));
12533bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  EXPECT_EQ(GetInstructionSetPointerSize(InstructionSet::kX86),
12633bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko            GetConstExprPointerSize(InstructionSet::kX86));
12733bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  EXPECT_EQ(GetInstructionSetPointerSize(InstructionSet::kX86_64),
12833bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko            GetConstExprPointerSize(InstructionSet::kX86_64));
12941c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov}
13041c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
13141c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov// This test ensures that the constexpr specialization of the return PC offset computation in
13241c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov// GetCalleeSavePCOffset is correct.
13341c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei ZavjalovTEST_F(QuickTrampolineEntrypointsTest, ReturnPC) {
13441c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov  // Ensure that the computation in callee_save_frame.h correct.
13541c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov  // Note: we can only check against the kRuntimeISA, because the ArtMethod computation uses
13613735955f39b3b304c37d2b2840663c131262c18Ian Rogers  // sizeof(void*), which is wrong when the target bitwidth is not the same as the host's.
1378228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe  CheckPCOffset(kRuntimeISA, CalleeSaveType::kSaveRefsAndArgs,
1388228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe                GetCalleeSaveReturnPcOffset(kRuntimeISA, CalleeSaveType::kSaveRefsAndArgs));
1398228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe  CheckPCOffset(kRuntimeISA, CalleeSaveType::kSaveRefsOnly,
1408228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe                GetCalleeSaveReturnPcOffset(kRuntimeISA, CalleeSaveType::kSaveRefsOnly));
1418228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe  CheckPCOffset(kRuntimeISA, CalleeSaveType::kSaveAllCalleeSaves,
1428228cdf4ad6322ec8133564aaa51f966d36c0f17Andreas Gampe                GetCalleeSaveReturnPcOffset(kRuntimeISA, CalleeSaveType::kSaveAllCalleeSaves));
1430a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang  CheckPCOffset(kRuntimeISA, CalleeSaveType::kSaveEverything,
1440a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                GetCalleeSaveReturnPcOffset(kRuntimeISA, CalleeSaveType::kSaveEverything));
1450a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang  CheckPCOffset(kRuntimeISA, CalleeSaveType::kSaveEverythingForClinit,
1460a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                GetCalleeSaveReturnPcOffset(kRuntimeISA, CalleeSaveType::kSaveEverythingForClinit));
1470a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang  CheckPCOffset(kRuntimeISA, CalleeSaveType::kSaveEverythingForSuspendCheck,
1480a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                GetCalleeSaveReturnPcOffset(kRuntimeISA,
1490a87a653a296854c9a0abacd9bb1557ee4c4d05dMingyao Yang                                            CalleeSaveType::kSaveEverythingForSuspendCheck));
15041c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov}
15141c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov
15241c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov}  // namespace art
153