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