1848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers/* 2848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * Copyright (C) 2012 The Android Open Source Project 3848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * 4848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * Licensed under the Apache License, Version 2.0 (the "License"); 5848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * you may not use this file except in compliance with the License. 6848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * You may obtain a copy of the License at 7848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * 8848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * http://www.apache.org/licenses/LICENSE-2.0 9848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * 10848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * Unless required by applicable law or agreed to in writing, software 11848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * distributed under the License is distributed on an "AS IS" BASIS, 12848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * See the License for the specific language governing permissions and 14848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers * limitations under the License. 15848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers */ 16848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 17e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h" 18848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#include "callee_save_frame.h" 19bd136a29f08486525d6abc7d0a0006ce5b4011c1Dragos Sbirlea#include "common_throws.h" 20848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#include "dex_file-inl.h" 21848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#include "dex_instruction-inl.h" 2298d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang#include "entrypoints/entrypoint_utils-inl.h" 236f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers#include "entrypoints/runtime_asm_entrypoints.h" 2483883d7fddf30fdb8b6903560fa1337ab991e74cIan Rogers#include "gc/accounting/card_table-inl.h" 25848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#include "interpreter/interpreter.h" 26796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray#include "linear_alloc.h" 27e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers#include "method_reference.h" 28848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#include "mirror/class-inl.h" 295f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier#include "mirror/dex_cache-inl.h" 30fc58af45e342ba9e18bbdf597f205a58ec731658Mathieu Chartier#include "mirror/method.h" 31848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#include "mirror/object-inl.h" 32848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#include "mirror/object_array-inl.h" 33524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "oat_quick_method_header.h" 34639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe#include "quick_exception_handler.h" 35848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#include "runtime.h" 3653b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers#include "scoped_thread_state_change.h" 37b30259251b22430fad12f1adeab671e4bf8f88f5Andreas Gampe#include "stack.h" 38eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi#include "debugger.h" 39848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 40848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogersnamespace art { 41848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 42848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame. 43848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogersclass QuickArgumentVisitor { 44936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // Number of bytes for each out register in the caller method's frame. 45936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers static constexpr size_t kBytesStackArgLocation = 4; 4641c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov // Frame size in bytes of a callee-save frame for RefsAndArgs. 4741c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_FrameSize = 4841c507a9dae44b8329a857da3d9810fab2e9ddc6Alexei Zavjalov GetCalleeSaveFrameSize(kRuntimeISA, Runtime::kRefsAndArgs); 49848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#if defined(__arm__) 50848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // The callee save frame is pointed to by SP. 51848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | argN | | 52848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | ... | | 53848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg4 | | 54848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg3 spill | | Caller's frame 55848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg2 spill | | 56848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg1 spill | | 57848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | Method* | --- 58848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | LR | 595667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // | ... | 4x6 bytes callee saves 605667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // | R3 | 615667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // | R2 | 625667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // | R1 | 635667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // | S15 | 645667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // | : | 655667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // | S0 | 665667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // | | 4x2 bytes padding 67848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | Method* | <- sp 683e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell static constexpr bool kSplitPairAcrossRegisterAndStack = kArm32QuickCodeUseSoftFloat; 6969c15d340e7e76821bbc5d4494d4cef383774deeNicolas Geoffray static constexpr bool kAlignPairRegister = !kArm32QuickCodeUseSoftFloat; 705667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu static constexpr bool kQuickSoftFloatAbi = kArm32QuickCodeUseSoftFloat; 715667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = !kArm32QuickCodeUseSoftFloat; 72ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr bool kQuickSkipOddFpRegisters = false; 735667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu static constexpr size_t kNumQuickGprArgs = 3; 745667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu static constexpr size_t kNumQuickFprArgs = kArm32QuickCodeUseSoftFloat ? 0 : 16; 751a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kGprFprLockstep = false; 76b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 77b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu arm::ArmCalleeSaveFpr1Offset(Runtime::kRefsAndArgs); // Offset of first FPR arg. 78b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 79b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu arm::ArmCalleeSaveGpr1Offset(Runtime::kRefsAndArgs); // Offset of first GPR arg. 80b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 81b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu arm::ArmCalleeSaveLrOffset(Runtime::kRefsAndArgs); // Offset of return address. 82936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers static size_t GprIndexToGprOffset(uint32_t gpr_index) { 8342fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA); 84936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 85b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#elif defined(__aarch64__) 86b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // The callee save frame is pointed to by SP. 87b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | argN | | 88b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | ... | | 89b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | arg4 | | 90b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | arg3 spill | | Caller's frame 91b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | arg2 spill | | 92b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | arg1 spill | | 93b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | Method* | --- 94b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | LR | 95b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu // | X29 | 96b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | : | 979bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu // | X20 | 98b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | X7 | 99b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | : | 100b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | X1 | 101b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu // | D7 | 102b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | : | 103b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | D0 | 104b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | | padding 105b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith // | Method* | <- sp 1063e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell static constexpr bool kSplitPairAcrossRegisterAndStack = false; 10769c15d340e7e76821bbc5d4494d4cef383774deeNicolas Geoffray static constexpr bool kAlignPairRegister = false; 108b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr bool kQuickSoftFloatAbi = false; // This is a hard float ABI. 1095667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false; 110ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr bool kQuickSkipOddFpRegisters = false; 111b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr size_t kNumQuickGprArgs = 7; // 7 arguments passed in GPRs. 112b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr size_t kNumQuickFprArgs = 8; // 8 arguments passed in FPRs. 1131a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kGprFprLockstep = false; 114b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 115b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu arm64::Arm64CalleeSaveFpr1Offset(Runtime::kRefsAndArgs); // Offset of first FPR arg. 116b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 117b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu arm64::Arm64CalleeSaveGpr1Offset(Runtime::kRefsAndArgs); // Offset of first GPR arg. 118b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 119b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu arm64::Arm64CalleeSaveLrOffset(Runtime::kRefsAndArgs); // Offset of return address. 120b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static size_t GprIndexToGprOffset(uint32_t gpr_index) { 12142fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA); 122b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith } 1231a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe#elif defined(__mips__) && !defined(__LP64__) 124848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // The callee save frame is pointed to by SP. 125848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | argN | | 126848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | ... | | 127848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg4 | | 128848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg3 spill | | Caller's frame 129848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg2 spill | | 130848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg1 spill | | 131848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | Method* | --- 132848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | RA | 133848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | ... | callee saves 134848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | A3 | arg3 135848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | A2 | arg2 136848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | A1 | arg1 137ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F15 | 138ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F14 | f_arg1 139ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F13 | 140ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F12 | f_arg0 141ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | | padding 142848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | A0/Method* | <- sp 143ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr bool kSplitPairAcrossRegisterAndStack = false; 144ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr bool kAlignPairRegister = true; 145ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr bool kQuickSoftFloatAbi = false; 1465667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false; 147ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr bool kQuickSkipOddFpRegisters = true; 148bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kNumQuickGprArgs = 3; // 3 arguments passed in GPRs. 149ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr size_t kNumQuickFprArgs = 4; // 2 arguments passed in FPRs. Floats can be passed 150ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // only in even numbered registers and each double 151ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // occupies two registers. 1521a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kGprFprLockstep = false; 153ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 16; // Offset of first FPR arg. 154ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 32; // Offset of first GPR arg. 155ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 76; // Offset of return address. 156936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers static size_t GprIndexToGprOffset(uint32_t gpr_index) { 15742fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA); 158936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 1591a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe#elif defined(__mips__) && defined(__LP64__) 1601a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // The callee save frame is pointed to by SP. 1611a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | argN | | 1621a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | ... | | 1631a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | arg4 | | 1641a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | arg3 spill | | Caller's frame 1651a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | arg2 spill | | 1661a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | arg1 spill | | 1671a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | Method* | --- 1681a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | RA | 1691a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | ... | callee saves 1701a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | A7 | arg7 1711a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | A6 | arg6 1721a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | A5 | arg5 1731a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | A4 | arg4 1741a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | A3 | arg3 1751a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | A2 | arg2 1761a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | A1 | arg1 177ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F19 | f_arg7 178ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F18 | f_arg6 179ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F17 | f_arg5 180ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F16 | f_arg4 181ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F15 | f_arg3 182ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F14 | f_arg2 183ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F13 | f_arg1 184ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // | F12 | f_arg0 1851a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | | padding 1861a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // | A0/Method* | <- sp 1871a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // NOTE: for Mip64, when A0 is skipped, F0 is also skipped. 188d18e083522e8148427c08a35034c10f63f61f31dDouglas Leung static constexpr bool kSplitPairAcrossRegisterAndStack = false; 1891a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kAlignPairRegister = false; 1901a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kQuickSoftFloatAbi = false; 1911a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false; 192ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr bool kQuickSkipOddFpRegisters = false; 1931a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr size_t kNumQuickGprArgs = 7; // 7 arguments passed in GPRs. 1941a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr size_t kNumQuickFprArgs = 7; // 7 arguments passed in FPRs. 1951a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kGprFprLockstep = true; 1961a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe 1971a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 24; // Offset of first FPR arg (F1). 1981a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 80; // Offset of first GPR arg (A1). 1991a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 200; // Offset of return address. 2001a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static size_t GprIndexToGprOffset(uint32_t gpr_index) { 2011a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA); 2021a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe } 203848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#elif defined(__i386__) 204848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // The callee save frame is pointed to by SP. 205848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | argN | | 206848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | ... | | 207848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg4 | | 208848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg3 spill | | Caller's frame 209848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg2 spill | | 210848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | arg1 spill | | 211848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | Method* | --- 212848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | Return | 213848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | EBP,ESI,EDI | callee saves 214848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | EBX | arg3 215848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | EDX | arg2 216848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | ECX | arg1 217966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell // | XMM3 | float arg 4 218966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell // | XMM2 | float arg 3 219966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell // | XMM1 | float arg 2 220966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell // | XMM0 | float arg 1 221848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // | EAX/Method* | <- sp 2223e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell static constexpr bool kSplitPairAcrossRegisterAndStack = false; 22369c15d340e7e76821bbc5d4494d4cef383774deeNicolas Geoffray static constexpr bool kAlignPairRegister = false; 224966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell static constexpr bool kQuickSoftFloatAbi = false; // This is a hard float ABI. 2255667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false; 226ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr bool kQuickSkipOddFpRegisters = false; 227bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kNumQuickGprArgs = 3; // 3 arguments passed in GPRs. 228966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell static constexpr size_t kNumQuickFprArgs = 4; // 4 arguments passed in FPRs. 2291a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kGprFprLockstep = false; 230966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 4; // Offset of first FPR arg. 231966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 4 + 4*8; // Offset of first GPR arg. 232966c3ae95d3c699ee9fbdbccc1acdaaf02325fafMark P Mendell static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 28 + 4*8; // Offset of return address. 233936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers static size_t GprIndexToGprOffset(uint32_t gpr_index) { 23442fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA); 235936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 236ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#elif defined(__x86_64__) 237936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // The callee save frame is pointed to by SP. 238936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | argN | | 239936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | ... | | 240936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | reg. arg spills | | Caller's frame 241936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | Method* | --- 242936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | Return | 243936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | R15 | callee save 244936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | R14 | callee save 245936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | R13 | callee save 246936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | R12 | callee save 247936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | R9 | arg5 248936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | R8 | arg4 249936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | RSI/R6 | arg1 250936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | RBP/R5 | callee save 251936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | RBX/R3 | callee save 252936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | RDX/R2 | arg2 253936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | RCX/R1 | arg3 254936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | XMM7 | float arg 8 255936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | XMM6 | float arg 7 256936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | XMM5 | float arg 6 257936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | XMM4 | float arg 5 258936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | XMM3 | float arg 4 259936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | XMM2 | float arg 3 260936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | XMM1 | float arg 2 261936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | XMM0 | float arg 1 262936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | Padding | 263936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // | RDI/Method* | <- sp 2643e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell static constexpr bool kSplitPairAcrossRegisterAndStack = false; 26569c15d340e7e76821bbc5d4494d4cef383774deeNicolas Geoffray static constexpr bool kAlignPairRegister = false; 266bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr bool kQuickSoftFloatAbi = false; // This is a hard float ABI. 2675667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false; 268ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic static constexpr bool kQuickSkipOddFpRegisters = false; 26958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko static constexpr size_t kNumQuickGprArgs = 5; // 5 arguments passed in GPRs. 27058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko static constexpr size_t kNumQuickFprArgs = 8; // 8 arguments passed in FPRs. 2711a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kGprFprLockstep = false; 272936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 16; // Offset of first FPR arg. 273c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 80 + 4*8; // Offset of first GPR arg. 274c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 168 + 4*8; // Offset of return address. 275936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers static size_t GprIndexToGprOffset(uint32_t gpr_index) { 276936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers switch (gpr_index) { 27742fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray case 0: return (4 * GetBytesPerGprSpillLocation(kRuntimeISA)); 27842fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray case 1: return (1 * GetBytesPerGprSpillLocation(kRuntimeISA)); 27942fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray case 2: return (0 * GetBytesPerGprSpillLocation(kRuntimeISA)); 28042fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray case 3: return (5 * GetBytesPerGprSpillLocation(kRuntimeISA)); 28142fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray case 4: return (6 * GetBytesPerGprSpillLocation(kRuntimeISA)); 282936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers default: 283c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe LOG(FATAL) << "Unexpected GPR index: " << gpr_index; 284c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return 0; 285936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 286936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 287848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#else 288848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#error "Unsupported architecture" 289848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers#endif 290848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 291936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers public: 292a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz // Special handling for proxy methods. Proxy methods are instance methods so the 293a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz // 'this' object is the 1st argument. They also have the same frame layout as the 294a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz // kRefAndArgs runtime method. Since 'this' is a reference, it is located in the 295a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz // 1st GPR. 296e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier static mirror::Object* GetProxyThisObject(ArtMethod** sp) 29790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 2983a0909248e04b22c3981cbf617bc2502ed5b6380Nicolas Geoffray CHECK((*sp)->IsProxyMethod()); 299a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz CHECK_GT(kNumQuickGprArgs, 0u); 300a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz constexpr uint32_t kThisGprIndex = 0u; // 'this' is in the 1st GPR. 301a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz size_t this_arg_offset = kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset + 302a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz GprIndexToGprOffset(kThisGprIndex); 303a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz uint8_t* this_arg_address = reinterpret_cast<uint8_t*>(sp) + this_arg_offset; 304a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz return reinterpret_cast<StackReference<mirror::Object>*>(this_arg_address)->AsMirrorPtr(); 305a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz } 306a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz 30790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier static ArtMethod* GetCallingMethod(ArtMethod** sp) SHARED_REQUIRES(Locks::mutator_lock_) { 308e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK((*sp)->IsCalleeSaveMethod()); 3097ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray return GetCalleeSaveMethodCaller(sp, Runtime::kRefsAndArgs); 3107ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray } 3117ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray 31290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier static ArtMethod* GetOuterMethod(ArtMethod** sp) SHARED_REQUIRES(Locks::mutator_lock_) { 313e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK((*sp)->IsCalleeSaveMethod()); 314d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray uint8_t* previous_sp = 315d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize; 316e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return *reinterpret_cast<ArtMethod**>(previous_sp); 317d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray } 318d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray 31990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier static uint32_t GetCallingDexPc(ArtMethod** sp) SHARED_REQUIRES(Locks::mutator_lock_) { 320e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK((*sp)->IsCalleeSaveMethod()); 321d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray const size_t callee_frame_size = GetCalleeSaveFrameSize(kRuntimeISA, Runtime::kRefsAndArgs); 322e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod** caller_sp = reinterpret_cast<ArtMethod**>( 323e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier reinterpret_cast<uintptr_t>(sp) + callee_frame_size); 324d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray uintptr_t outer_pc = QuickArgumentVisitor::GetCallingPc(sp); 325524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray const OatQuickMethodHeader* current_code = (*caller_sp)->GetOatQuickMethodHeader(outer_pc); 326524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray uintptr_t outer_pc_offset = current_code->NativeQuickPcOffset(outer_pc); 327d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray 328524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray if (current_code->IsOptimized()) { 329524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray CodeInfo code_info = current_code->GetOptimizedCodeInfo(); 33009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky CodeInfoEncoding encoding = code_info.ExtractEncoding(); 331f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset, encoding); 332d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray DCHECK(stack_map.IsValid()); 33309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (stack_map.HasInlineInfo(encoding.stack_map_encoding)) { 334f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map, encoding); 33561b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky return inline_info.GetDexPcAtDepth(encoding.inline_info_encoding, 33661b28a17d9b6e8e998103646e98e4a9772e11927David Srbecky inline_info.GetDepth(encoding.inline_info_encoding)-1); 337d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray } else { 33809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky return stack_map.GetDexPc(encoding.stack_map_encoding); 339d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray } 340d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray } else { 341524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray return current_code->ToDexPc(*caller_sp, outer_pc); 342d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray } 343848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 344848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 345936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // For the given quick ref and args quick frame, return the caller's PC. 34690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier static uintptr_t GetCallingPc(ArtMethod** sp) SHARED_REQUIRES(Locks::mutator_lock_) { 347e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK((*sp)->IsCalleeSaveMethod()); 34813735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* lr = reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_LrOffset; 349848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers return *reinterpret_cast<uintptr_t*>(lr); 350848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 351848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 352e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier QuickArgumentVisitor(ArtMethod** sp, bool is_static, const char* shorty, 35390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier uint32_t shorty_len) SHARED_REQUIRES(Locks::mutator_lock_) : 354c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe is_static_(is_static), shorty_(shorty), shorty_len_(shorty_len), 35513735955f39b3b304c37d2b2840663c131262c18Ian Rogers gpr_args_(reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset), 35613735955f39b3b304c37d2b2840663c131262c18Ian Rogers fpr_args_(reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset), 35713735955f39b3b304c37d2b2840663c131262c18Ian Rogers stack_args_(reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize 358e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier + sizeof(ArtMethod*)), // Skip ArtMethod*. 3595667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu gpr_index_(0), fpr_index_(0), fpr_double_index_(0), stack_index_(0), 3605667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu cur_type_(Primitive::kPrimVoid), is_split_long_or_double_(false) { 361575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe static_assert(kQuickSoftFloatAbi == (kNumQuickFprArgs == 0), 362575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe "Number of Quick FPR arguments unexpected"); 363575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe static_assert(!(kQuickSoftFloatAbi && kQuickDoubleRegAlignedFloatBackFilled), 364575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe "Double alignment unexpected"); 3655667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // For register alignment, we want to assume that counters(fpr_double_index_) are even if the 3665667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // next register is even. 367575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe static_assert(!kQuickDoubleRegAlignedFloatBackFilled || kNumQuickFprArgs % 2 == 0, 368575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe "Number of Quick FPR arguments not even"); 369e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*)); 3705667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 371848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 372848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers virtual ~QuickArgumentVisitor() {} 373848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 374848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers virtual void Visit() = 0; 375848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 376936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers Primitive::Type GetParamPrimitiveType() const { 377936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers return cur_type_; 378848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 379848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 38013735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* GetParamAddress() const { 381bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (!kQuickSoftFloatAbi) { 382936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers Primitive::Type type = GetParamPrimitiveType(); 383936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers if (UNLIKELY((type == Primitive::kPrimDouble) || (type == Primitive::kPrimFloat))) { 3845667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (type == Primitive::kPrimDouble && kQuickDoubleRegAlignedFloatBackFilled) { 3855667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (fpr_double_index_ + 2 < kNumQuickFprArgs + 1) { 3865667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu return fpr_args_ + (fpr_double_index_ * GetBytesPerFprSpillLocation(kRuntimeISA)); 3875667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 3885667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } else if (fpr_index_ + 1 < kNumQuickFprArgs + 1) { 38942fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray return fpr_args_ + (fpr_index_ * GetBytesPerFprSpillLocation(kRuntimeISA)); 390936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 3911dd61ba3081a52c3e2efdc78d64f5c134eea7895Vladimir Kostyukov return stack_args_ + (stack_index_ * kBytesStackArgLocation); 392936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 393936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 394bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (gpr_index_ < kNumQuickGprArgs) { 395936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers return gpr_args_ + GprIndexToGprOffset(gpr_index_); 396936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 397936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers return stack_args_ + (stack_index_ * kBytesStackArgLocation); 398848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 399848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 400848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers bool IsSplitLongOrDouble() const { 401e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if ((GetBytesPerGprSpillLocation(kRuntimeISA) == 4) || 402e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier (GetBytesPerFprSpillLocation(kRuntimeISA) == 4)) { 403936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers return is_split_long_or_double_; 404936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } else { 405936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers return false; // An optimization for when GPR and FPRs are 64bit. 406936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 407848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 408848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 409936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers bool IsParamAReference() const { 410848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers return GetParamPrimitiveType() == Primitive::kPrimNot; 411848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 412848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 413936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers bool IsParamALongOrDouble() const { 414848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers Primitive::Type type = GetParamPrimitiveType(); 415848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers return type == Primitive::kPrimLong || type == Primitive::kPrimDouble; 416848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 417848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 418848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint64_t ReadSplitLongParam() const { 419425f239c291d435f519a1cf4bdd9ccc9a2c0c070Nicolas Geoffray // The splitted long is always available through the stack. 420425f239c291d435f519a1cf4bdd9ccc9a2c0c070Nicolas Geoffray return *reinterpret_cast<uint64_t*>(stack_args_ 421425f239c291d435f519a1cf4bdd9ccc9a2c0c070Nicolas Geoffray + stack_index_ * kBytesStackArgLocation); 422848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 423848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 4241a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe void IncGprIndex() { 4251a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe gpr_index_++; 4261a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe if (kGprFprLockstep) { 4271a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe fpr_index_++; 4281a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe } 4291a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe } 4301a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe 4311a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe void IncFprIndex() { 4321a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe fpr_index_++; 4331a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe if (kGprFprLockstep) { 4341a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe gpr_index_++; 4351a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe } 4361a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe } 4371a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe 43890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void VisitArguments() SHARED_REQUIRES(Locks::mutator_lock_) { 4395667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // (a) 'stack_args_' should point to the first method's argument 4405667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // (b) whatever the argument type it is, the 'stack_index_' should 4415667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // be moved forward along with every visiting. 442936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers gpr_index_ = 0; 443936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers fpr_index_ = 0; 4445667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (kQuickDoubleRegAlignedFloatBackFilled) { 4455667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu fpr_double_index_ = 0; 4465667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 447936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers stack_index_ = 0; 448936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers if (!is_static_) { // Handle this. 449936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers cur_type_ = Primitive::kPrimNot; 450936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers is_split_long_or_double_ = false; 451848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers Visit(); 4525667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu stack_index_++; 453bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (kNumQuickGprArgs > 0) { 4541a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe IncGprIndex(); 455936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 456848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 457936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers for (uint32_t shorty_index = 1; shorty_index < shorty_len_; ++shorty_index) { 458936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers cur_type_ = Primitive::GetType(shorty_[shorty_index]); 459936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers switch (cur_type_) { 460936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers case Primitive::kPrimNot: 461936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers case Primitive::kPrimBoolean: 462936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers case Primitive::kPrimByte: 463936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers case Primitive::kPrimChar: 464936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers case Primitive::kPrimShort: 465936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers case Primitive::kPrimInt: 466936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers is_split_long_or_double_ = false; 467936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers Visit(); 4685667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu stack_index_++; 469bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (gpr_index_ < kNumQuickGprArgs) { 4701a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe IncGprIndex(); 471936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 472936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers break; 473936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers case Primitive::kPrimFloat: 474936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers is_split_long_or_double_ = false; 475936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers Visit(); 4765667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu stack_index_++; 477bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (kQuickSoftFloatAbi) { 478bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (gpr_index_ < kNumQuickGprArgs) { 4791a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe IncGprIndex(); 480936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 481936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } else { 4825667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (fpr_index_ + 1 < kNumQuickFprArgs + 1) { 4831a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe IncFprIndex(); 4845667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (kQuickDoubleRegAlignedFloatBackFilled) { 4855667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // Double should not overlap with float. 4865667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // For example, if fpr_index_ = 3, fpr_double_index_ should be at least 4. 4875667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu fpr_double_index_ = std::max(fpr_double_index_, RoundUp(fpr_index_, 2)); 4885667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // Float should not overlap with double. 4895667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (fpr_index_ % 2 == 0) { 4905667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu fpr_index_ = std::max(fpr_double_index_, fpr_index_); 4915667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 492ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic } else if (kQuickSkipOddFpRegisters) { 493ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic IncFprIndex(); 4945667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 495936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 496936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 497936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers break; 498936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers case Primitive::kPrimDouble: 499936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers case Primitive::kPrimLong: 500bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (kQuickSoftFloatAbi || (cur_type_ == Primitive::kPrimLong)) { 50169c15d340e7e76821bbc5d4494d4cef383774deeNicolas Geoffray if (cur_type_ == Primitive::kPrimLong && kAlignPairRegister && gpr_index_ == 0) { 502ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // Currently, this is only for ARM and MIPS, where the first available parameter 503ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // register is R1 (on ARM) or A1 (on MIPS). So we skip it, and use R2 (on ARM) or 504ff73498a5539d87424a964265e43765e788aec44Goran Jakovljevic // A2 (on MIPS) instead. 5051a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe IncGprIndex(); 50669c15d340e7e76821bbc5d4494d4cef383774deeNicolas Geoffray } 50742fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray is_split_long_or_double_ = (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) && 508bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe ((gpr_index_ + 1) == kNumQuickGprArgs); 5093e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell if (!kSplitPairAcrossRegisterAndStack && is_split_long_or_double_) { 5103e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell // We don't want to split this. Pass over this register. 5113e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell gpr_index_++; 5123e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell is_split_long_or_double_ = false; 5133e6a3bf797e49b7f449256455c7e522e888687d8Mark Mendell } 514936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers Visit(); 5155667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (kBytesStackArgLocation == 4) { 5165667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu stack_index_+= 2; 5175667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } else { 5185667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu CHECK_EQ(kBytesStackArgLocation, 8U); 5195667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu stack_index_++; 5201dd61ba3081a52c3e2efdc78d64f5c134eea7895Vladimir Kostyukov } 521bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (gpr_index_ < kNumQuickGprArgs) { 5221a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe IncGprIndex(); 52342fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray if (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) { 524bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (gpr_index_ < kNumQuickGprArgs) { 5251a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe IncGprIndex(); 526936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 527936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 528936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 529936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } else { 53042fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray is_split_long_or_double_ = (GetBytesPerFprSpillLocation(kRuntimeISA) == 4) && 5315667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu ((fpr_index_ + 1) == kNumQuickFprArgs) && !kQuickDoubleRegAlignedFloatBackFilled; 532936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers Visit(); 5331dd61ba3081a52c3e2efdc78d64f5c134eea7895Vladimir Kostyukov if (kBytesStackArgLocation == 4) { 5341dd61ba3081a52c3e2efdc78d64f5c134eea7895Vladimir Kostyukov stack_index_+= 2; 535936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } else { 5361dd61ba3081a52c3e2efdc78d64f5c134eea7895Vladimir Kostyukov CHECK_EQ(kBytesStackArgLocation, 8U); 5371dd61ba3081a52c3e2efdc78d64f5c134eea7895Vladimir Kostyukov stack_index_++; 538936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 5395667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (kQuickDoubleRegAlignedFloatBackFilled) { 5405667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (fpr_double_index_ + 2 < kNumQuickFprArgs + 1) { 5415667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu fpr_double_index_ += 2; 5425667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // Float should not overlap with double. 5435667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (fpr_index_ % 2 == 0) { 5445667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu fpr_index_ = std::max(fpr_double_index_, fpr_index_); 5455667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 5465667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 5475667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } else if (fpr_index_ + 1 < kNumQuickFprArgs + 1) { 5481a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe IncFprIndex(); 5495667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (GetBytesPerFprSpillLocation(kRuntimeISA) == 4) { 5505667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu if (fpr_index_ + 1 < kNumQuickFprArgs + 1) { 5511a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe IncFprIndex(); 5525667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 5535667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 5545667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu } 555936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 556936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers break; 557936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers default: 558936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers LOG(FATAL) << "Unexpected type: " << cur_type_ << " in " << shorty_; 559936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers } 560848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 561848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 562848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 563c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe protected: 564848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const bool is_static_; 565848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const char* const shorty_; 566848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const uint32_t shorty_len_; 567c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 568c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe private: 56913735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* const gpr_args_; // Address of GPR arguments in callee save frame. 57013735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* const fpr_args_; // Address of FPR arguments in callee save frame. 57113735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* const stack_args_; // Address of stack arguments in caller's frame. 572936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers uint32_t gpr_index_; // Index into spilled GPRs. 5735667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // Index into spilled FPRs. 5745667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // In case kQuickDoubleRegAlignedFloatBackFilled, it may index a hole while fpr_double_index_ 5755667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // holds a higher register number. 5765667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu uint32_t fpr_index_; 5775667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // Index into spilled FPRs for aligned double. 5785667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // Only used when kQuickDoubleRegAlignedFloatBackFilled. Next available double register indexed in 5795667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu // terms of singles, may be behind fpr_index. 5805667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu uint32_t fpr_double_index_; 581936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers uint32_t stack_index_; // Index into arguments on the stack. 582936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers // The current type of argument during VisitArguments. 583936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers Primitive::Type cur_type_; 584848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Does a 64bit parameter straddle the register and stack arguments? 585848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers bool is_split_long_or_double_; 586848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers}; 587848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 588a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz// Returns the 'this' object of a proxy method. This function is only used by StackVisitor. It 589a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz// allows to use the QuickArgumentVisitor constants without moving all the code in its own module. 590e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierextern "C" mirror::Object* artQuickGetProxyThisObject(ArtMethod** sp) 59190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 592a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz return QuickArgumentVisitor::GetProxyThisObject(sp); 593a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz} 594a836bc9760419af4a515f96c66100a39e865f3b9Sebastien Hertz 595848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// Visits arguments on the stack placing them into the shadow frame. 596bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampeclass BuildQuickShadowFrameVisitor FINAL : public QuickArgumentVisitor { 597848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers public: 598e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier BuildQuickShadowFrameVisitor(ArtMethod** sp, bool is_static, const char* shorty, 599e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint32_t shorty_len, ShadowFrame* sf, size_t first_arg_reg) : 600c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe QuickArgumentVisitor(sp, is_static, shorty, shorty_len), sf_(sf), cur_reg_(first_arg_reg) {} 601848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 60290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void Visit() SHARED_REQUIRES(Locks::mutator_lock_) OVERRIDE; 603848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 604848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers private: 605936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers ShadowFrame* const sf_; 606936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers uint32_t cur_reg_; 607848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 608bd136a29f08486525d6abc7d0a0006ce5b4011c1Dragos Sbirlea DISALLOW_COPY_AND_ASSIGN(BuildQuickShadowFrameVisitor); 609848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers}; 610848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 611c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampevoid BuildQuickShadowFrameVisitor::Visit() { 6129758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers Primitive::Type type = GetParamPrimitiveType(); 6139758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers switch (type) { 6149758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimLong: // Fall-through. 6159758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimDouble: 6169758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers if (IsSplitLongOrDouble()) { 6179758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers sf_->SetVRegLong(cur_reg_, ReadSplitLongParam()); 6189758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } else { 6199758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers sf_->SetVRegLong(cur_reg_, *reinterpret_cast<jlong*>(GetParamAddress())); 6209758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 6219758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers ++cur_reg_; 6229758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 6239758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimNot: { 6249758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers StackReference<mirror::Object>* stack_ref = 6259758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress()); 6269758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers sf_->SetVRegReference(cur_reg_, stack_ref->AsMirrorPtr()); 6279758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 6289758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 6299758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimBoolean: // Fall-through. 6309758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimByte: // Fall-through. 6319758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimChar: // Fall-through. 6329758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimShort: // Fall-through. 6339758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimInt: // Fall-through. 6349758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimFloat: 6359758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers sf_->SetVReg(cur_reg_, *reinterpret_cast<jint*>(GetParamAddress())); 6369758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 6379758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimVoid: 6389758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers LOG(FATAL) << "UNREACHABLE"; 6392c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers UNREACHABLE(); 6409758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 6419758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers ++cur_reg_; 6429758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers} 6439758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers 644e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierextern "C" uint64_t artQuickToInterpreterBridge(ArtMethod* method, Thread* self, ArtMethod** sp) 64590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 646848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Ensure we don't get thread suspension until the object arguments are safely in the shadow 647848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // frame. 6481d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers ScopedQuickEntrypointChecks sqec(self); 649848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 6509139e008abe30b7beaf4afd6533228a1dd9b202cAlex Light if (UNLIKELY(!method->IsInvokable())) { 6519139e008abe30b7beaf4afd6533228a1dd9b202cAlex Light method->ThrowInvocationTimeError(); 652848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers return 0; 653639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe } 654639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 655639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe JValue tmp_value; 656639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe ShadowFrame* deopt_frame = self->PopStackedShadowFrame( 657639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe StackedShadowFrameType::kSingleFrameDeoptimizationShadowFrame, false); 658639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe ManagedStack fragment; 659639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 660639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe DCHECK(!method->IsNative()) << PrettyMethod(method); 661639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe uint32_t shorty_len = 0; 662e9dd04f633fcffc485f8d74861f39f66fc8bc522Alex Light ArtMethod* non_proxy_method = method->GetInterfaceMethodIfProxy(sizeof(void*)); 663e9dd04f633fcffc485f8d74861f39f66fc8bc522Alex Light const DexFile::CodeItem* code_item = non_proxy_method->GetCodeItem(); 664e9dd04f633fcffc485f8d74861f39f66fc8bc522Alex Light DCHECK(code_item != nullptr) << PrettyMethod(method); 665639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe const char* shorty = non_proxy_method->GetShorty(&shorty_len); 666639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 667639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe JValue result; 668639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 669639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe if (deopt_frame != nullptr) { 670639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Coming from single-frame deopt. 671639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 672639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe if (kIsDebugBuild) { 673639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Sanity-check: are the methods as expected? We check that the last shadow frame (the bottom 674639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // of the call-stack) corresponds to the called method. 675639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe ShadowFrame* linked = deopt_frame; 676639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe while (linked->GetLink() != nullptr) { 677639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe linked = linked->GetLink(); 678639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe } 679639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe CHECK_EQ(method, linked->GetMethod()) << PrettyMethod(method) << " " 680639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe << PrettyMethod(linked->GetMethod()); 681639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe } 682639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 683639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe if (VLOG_IS_ON(deopt)) { 684639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Print out the stack to verify that it was a single-frame deopt. 685639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe LOG(INFO) << "Continue-ing from deopt. Stack is:"; 686639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe QuickExceptionHandler::DumpFramesWithType(self, true); 687639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe } 688639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 689639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe mirror::Throwable* pending_exception = nullptr; 69073be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray bool from_code = false; 69173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray self->PopDeoptimizationContext(&result, &pending_exception, /* out */ &from_code); 69273be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray CHECK(from_code); 693639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 694639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Push a transition back into managed code onto the linked list in thread. 695639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe self->PushManagedStackFragment(&fragment); 696639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 697639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Ensure that the stack is still in order. 698639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe if (kIsDebugBuild) { 699639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe class DummyStackVisitor : public StackVisitor { 700639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe public: 701639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe explicit DummyStackVisitor(Thread* self_in) SHARED_REQUIRES(Locks::mutator_lock_) 702639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe : StackVisitor(self_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {} 703639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 704639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe bool VisitFrame() OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { 705639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Nothing to do here. In a debug build, SanityCheckFrame will do the work in the walking 706639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // logic. Just always say we want to continue. 707639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe return true; 708639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe } 709639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe }; 710639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe DummyStackVisitor dsv(self); 711639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe dsv.WalkStack(); 712639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe } 713639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 714639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Restore the exception that was pending before deoptimization then interpret the 715639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // deoptimized frames. 716639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe if (pending_exception != nullptr) { 717639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe self->SetException(pending_exception); 718639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe } 71973be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray interpreter::EnterInterpreterFromDeoptimize(self, deopt_frame, from_code, &result); 720848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } else { 721c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe const char* old_cause = self->StartAssertNoThreadSuspension( 722c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe "Building interpreter shadow frame"); 723848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint16_t num_regs = code_item->registers_size_; 724c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // No last shadow coming from quick. 725b30259251b22430fad12f1adeab671e4bf8f88f5Andreas Gampe ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr = 72603ec930faded5bbfa096533ce60b6893847922dbAndreas Gampe CREATE_SHADOW_FRAME(num_regs, /* link */ nullptr, method, /* dex pc */ 0); 727b30259251b22430fad12f1adeab671e4bf8f88f5Andreas Gampe ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get(); 728848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_; 729bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier BuildQuickShadowFrameVisitor shadow_frame_builder(sp, method->IsStatic(), shorty, shorty_len, 730936b37f3a7f224d990a36b2ec66782a4462180d6Ian Rogers shadow_frame, first_arg_reg); 731848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers shadow_frame_builder.VisitArguments(); 732e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers const bool needs_initialization = 733e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers method->IsStatic() && !method->GetDeclaringClass()->IsInitialized(); 734848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Push a transition back into managed code onto the linked list in thread. 735848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers self->PushManagedStackFragment(&fragment); 736848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers self->PushShadowFrame(shadow_frame); 737848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers self->EndAssertNoThreadSuspension(old_cause); 738848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 739e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers if (needs_initialization) { 740848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Ensure static method's class is initialized. 741e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers StackHandleScope<1> hs(self); 742e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers Handle<mirror::Class> h_class(hs.NewHandle(shadow_frame->GetMethod()->GetDeclaringClass())); 7437b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) { 744e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99Ian Rogers DCHECK(Thread::Current()->IsExceptionPending()) << PrettyMethod(shadow_frame->GetMethod()); 745848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers self->PopManagedStackFragment(fragment); 746848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers return 0; 747848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 748848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 749eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi 750639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe result = interpreter::EnterInterpreterFromEntryPoint(self, code_item, shadow_frame); 751848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 752639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 753639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Pop transition. 754639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe self->PopManagedStackFragment(fragment); 755639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 756639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Request a stack deoptimization if needed 757639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe ArtMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp); 758639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe if (UNLIKELY(Dbg::IsForcedInterpreterNeededForUpcall(self, caller))) { 759639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Push the context of the deoptimization stack so we can restore the return value and the 760639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // exception before executing the deoptimized frames. 76173be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray self->PushDeoptimizationContext( 76273be1e8f8609708f6624bb297c9628de44fd8b6fNicolas Geoffray result, shorty[0] == 'L', /* from_code */ false, self->GetException()); 763639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 764639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // Set special exception to cause deoptimization. 765639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe self->SetException(Thread::GetDeoptimizationException()); 766639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe } 767639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe 768639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe // No need to restore the args since the method has already been run by the interpreter. 769639bdd13993644a267f177f8f5936496bda65e2bAndreas Gampe return result.GetJ(); 770848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers} 771848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 772848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// Visits arguments on the stack placing them into the args vector, Object* arguments are converted 773848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// to jobjects. 774bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampeclass BuildQuickArgumentVisitor FINAL : public QuickArgumentVisitor { 775848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers public: 776e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier BuildQuickArgumentVisitor(ArtMethod** sp, bool is_static, const char* shorty, uint32_t shorty_len, 777cf4035a4c41ccfcc3e89a0cee25f5218a11b0705Andreas Gampe ScopedObjectAccessUnchecked* soa, std::vector<jvalue>* args) : 778c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa), args_(args) {} 779848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 78090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void Visit() SHARED_REQUIRES(Locks::mutator_lock_) OVERRIDE; 781848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 78290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void FixupReferences() SHARED_REQUIRES(Locks::mutator_lock_); 7835275bcbf35c2362a10607670e59edbfdfc80a758Mathieu Chartier 784848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers private: 7859758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers ScopedObjectAccessUnchecked* const soa_; 7869758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers std::vector<jvalue>* const args_; 7875275bcbf35c2362a10607670e59edbfdfc80a758Mathieu Chartier // References which we must update when exiting in case the GC moved the objects. 788700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::vector<std::pair<jobject, StackReference<mirror::Object>*>> references_; 7899758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers 790848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DISALLOW_COPY_AND_ASSIGN(BuildQuickArgumentVisitor); 791848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers}; 792848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 7939758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogersvoid BuildQuickArgumentVisitor::Visit() { 7949758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers jvalue val; 7959758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers Primitive::Type type = GetParamPrimitiveType(); 7969758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers switch (type) { 7979758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimNot: { 7989758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers StackReference<mirror::Object>* stack_ref = 7999758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress()); 8009758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers val.l = soa_->AddLocalReference<jobject>(stack_ref->AsMirrorPtr()); 8019758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers references_.push_back(std::make_pair(val.l, stack_ref)); 8029758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 8039758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 8049758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimLong: // Fall-through. 8059758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimDouble: 8069758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers if (IsSplitLongOrDouble()) { 8079758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers val.j = ReadSplitLongParam(); 8089758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } else { 8099758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers val.j = *reinterpret_cast<jlong*>(GetParamAddress()); 8109758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 8119758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 8129758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimBoolean: // Fall-through. 8139758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimByte: // Fall-through. 8149758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimChar: // Fall-through. 8159758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimShort: // Fall-through. 8169758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimInt: // Fall-through. 8179758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimFloat: 8189758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers val.i = *reinterpret_cast<jint*>(GetParamAddress()); 8199758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 8209758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimVoid: 8219758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers LOG(FATAL) << "UNREACHABLE"; 8222c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers UNREACHABLE(); 8239758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 8249758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers args_->push_back(val); 8259758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers} 8269758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers 8279758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogersvoid BuildQuickArgumentVisitor::FixupReferences() { 8289758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers // Fixup any references which may have changed. 8299758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers for (const auto& pair : references_) { 8309758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers pair.second->Assign(soa_->Decode<mirror::Object*>(pair.first)); 8315f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier soa_->Env()->DeleteLocalRef(pair.first); 8329758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 8339758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers} 8349758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers 835848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method 836848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// which is responsible for recording callee save registers. We explicitly place into jobjects the 837848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a 838848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// field within the proxy object, which will box the primitive arguments and deal with error cases. 839e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierextern "C" uint64_t artQuickProxyInvokeHandler( 840e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* proxy_method, mirror::Object* receiver, Thread* self, ArtMethod** sp) 84190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 8423a0909248e04b22c3981cbf617bc2502ed5b6380Nicolas Geoffray DCHECK(proxy_method->IsProxyMethod()) << PrettyMethod(proxy_method); 8433a0909248e04b22c3981cbf617bc2502ed5b6380Nicolas Geoffray DCHECK(receiver->GetClass()->IsProxyClass()) << PrettyMethod(proxy_method); 844848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Ensure we don't get thread suspension until the object arguments are safely in jobjects. 845848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const char* old_cause = 846848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments"); 847848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Register the top of the managed stack, making stack crawlable. 848e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK_EQ((*sp), proxy_method) << PrettyMethod(proxy_method); 849848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers self->VerifyStack(); 850848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Start new JNI local reference state. 851848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers JNIEnvExt* env = self->GetJniEnv(); 852848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers ScopedObjectAccessUnchecked soa(env); 853848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers ScopedJniEnvLocalRefState env_state(env); 854848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Create local ref. copies of proxy method and the receiver. 855848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver); 856848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 857848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Placing arguments into args vector and remove the receiver. 858e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy(sizeof(void*)); 859bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier CHECK(!non_proxy_method->IsStatic()) << PrettyMethod(proxy_method) << " " 860c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe << PrettyMethod(non_proxy_method); 861848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers std::vector<jvalue> args; 862bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier uint32_t shorty_len = 0; 863e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier const char* shorty = non_proxy_method->GetShorty(&shorty_len); 864bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier BuildQuickArgumentVisitor local_ref_visitor(sp, false, shorty, shorty_len, &soa, &args); 865d3633d52e5d21beea73c2e902c043cf96b70df74Brian Carlstrom 866848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers local_ref_visitor.VisitArguments(); 867d3633d52e5d21beea73c2e902c043cf96b70df74Brian Carlstrom DCHECK_GT(args.size(), 0U) << PrettyMethod(proxy_method); 868848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers args.erase(args.begin()); 869848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 870848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Convert proxy method into expected interface method. 871e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* interface_method = proxy_method->FindOverriddenMethod(sizeof(void*)); 872e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers DCHECK(interface_method != nullptr) << PrettyMethod(proxy_method); 873848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method); 874fc58af45e342ba9e18bbdf597f205a58ec731658Mathieu Chartier self->EndAssertNoThreadSuspension(old_cause); 875fc58af45e342ba9e18bbdf597f205a58ec731658Mathieu Chartier jobject interface_method_jobj = soa.AddLocalReference<jobject>( 876fc58af45e342ba9e18bbdf597f205a58ec731658Mathieu Chartier mirror::Method::CreateFromArtMethod(soa.Self(), interface_method)); 877848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 878848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code 879848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // that performs allocations. 880bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier JValue result = InvokeProxyInvocationHandler(soa, shorty, rcvr_jobj, interface_method_jobj, args); 8815275bcbf35c2362a10607670e59edbfdfc80a758Mathieu Chartier // Restore references which might have moved. 8825275bcbf35c2362a10607670e59edbfdfc80a758Mathieu Chartier local_ref_visitor.FixupReferences(); 883848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers return result.GetJ(); 884848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers} 885848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 886848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// Read object references held in arguments from quick frames and place in a JNI local references, 887848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// so they don't get garbage collected. 888bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampeclass RememberForGcArgumentVisitor FINAL : public QuickArgumentVisitor { 889848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers public: 890e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier RememberForGcArgumentVisitor(ArtMethod** sp, bool is_static, const char* shorty, 891e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint32_t shorty_len, ScopedObjectAccessUnchecked* soa) : 892c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa) {} 893848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 89490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void Visit() SHARED_REQUIRES(Locks::mutator_lock_) OVERRIDE; 89507d447bebe6cc358e05ef041db84a5095a69e4f1Mathieu Chartier 89690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void FixupReferences() SHARED_REQUIRES(Locks::mutator_lock_); 897848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 898848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers private: 8999758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers ScopedObjectAccessUnchecked* const soa_; 9005275bcbf35c2362a10607670e59edbfdfc80a758Mathieu Chartier // References which we must update when exiting in case the GC moved the objects. 901c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe std::vector<std::pair<jobject, StackReference<mirror::Object>*> > references_; 902c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 903590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DISALLOW_COPY_AND_ASSIGN(RememberForGcArgumentVisitor); 904848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers}; 905848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 9069758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogersvoid RememberForGcArgumentVisitor::Visit() { 9079758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers if (IsParamAReference()) { 9089758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers StackReference<mirror::Object>* stack_ref = 9099758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress()); 9109758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers jobject reference = 9119758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers soa_->AddLocalReference<jobject>(stack_ref->AsMirrorPtr()); 9129758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers references_.push_back(std::make_pair(reference, stack_ref)); 9139758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 9149758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers} 9159758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers 9169758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogersvoid RememberForGcArgumentVisitor::FixupReferences() { 9179758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers // Fixup any references which may have changed. 9189758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers for (const auto& pair : references_) { 9199758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers pair.second->Assign(soa_->Decode<mirror::Object*>(pair.first)); 9205f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier soa_->Env()->DeleteLocalRef(pair.first); 9219758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 9229758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers} 9239758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers 924848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers// Lazily resolve a method for quick. Called by stub code. 925e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierextern "C" const void* artQuickResolutionTrampoline( 926e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* called, mirror::Object* receiver, Thread* self, ArtMethod** sp) 92790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 9283b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe // The resolution trampoline stashes the resolved method into the callee-save frame to transport 9293b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe // it. Thus, when exiting, the stack cannot be verified (as the resolved method most likely 9303b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe // does not have the same stack layout as the callee-save method). 9313b45ef277e4a5f7e0314d5df7ef82e480156ba75Andreas Gampe ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false); 932848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Start new JNI local reference state 933bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe JNIEnvExt* env = self->GetJniEnv(); 934848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers ScopedObjectAccessUnchecked soa(env); 935848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers ScopedJniEnvLocalRefState env_state(env); 936bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe const char* old_cause = self->StartAssertNoThreadSuspension("Quick method resolution set up"); 937848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 938848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Compute details about the called method (avoid GCs) 939848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers ClassLinker* linker = Runtime::Current()->GetClassLinker(); 940848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers InvokeType invoke_type; 941e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers MethodReference called_method(nullptr, 0); 942e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers const bool called_method_known_on_entry = !called->IsRuntimeMethod(); 943e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* caller = nullptr; 944e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers if (!called_method_known_on_entry) { 9457ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray caller = QuickArgumentVisitor::GetCallingMethod(sp); 9467ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp); 947848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const DexFile::CodeItem* code; 948e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers called_method.dex_file = caller->GetDexFile(); 949bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier code = caller->GetCodeItem(); 950848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers CHECK_LT(dex_pc, code->insns_size_in_code_units_); 951848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const Instruction* instr = Instruction::At(&code->insns_[dex_pc]); 952848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers Instruction::Code instr_code = instr->Opcode(); 953848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers bool is_range; 954848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers switch (instr_code) { 955848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_DIRECT: 956848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kDirect; 957848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = false; 958848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 959848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_DIRECT_RANGE: 960848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kDirect; 961848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = true; 962848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 963848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_STATIC: 964848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kStatic; 965848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = false; 966848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 967848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_STATIC_RANGE: 968848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kStatic; 969848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = true; 970848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 971848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_SUPER: 972848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kSuper; 973848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = false; 974848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 975848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_SUPER_RANGE: 976848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kSuper; 977848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = true; 978848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 979848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_VIRTUAL: 980848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kVirtual; 981848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = false; 982848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 983848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_VIRTUAL_RANGE: 984848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kVirtual; 985848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = true; 986848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 987848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_INTERFACE: 988848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kInterface; 989848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = false; 990848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 991848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers case Instruction::INVOKE_INTERFACE_RANGE: 992848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kInterface; 993848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers is_range = true; 994848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers break; 995848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers default: 996e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(nullptr); 997e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers UNREACHABLE(); 998848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 999e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers called_method.dex_method_index = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c(); 1000848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } else { 1001848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers invoke_type = kStatic; 1002e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers called_method.dex_file = called->GetDexFile(); 1003e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers called_method.dex_method_index = called->GetDexMethodIndex(); 1004848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 1005848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint32_t shorty_len; 1006848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const char* shorty = 1007e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers called_method.dex_file->GetMethodShorty( 1008e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers called_method.dex_file->GetMethodId(called_method.dex_method_index), &shorty_len); 1009590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier RememberForGcArgumentVisitor visitor(sp, invoke_type == kStatic, shorty, shorty_len, &soa); 1010848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers visitor.VisitArguments(); 1011bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe self->EndAssertNoThreadSuspension(old_cause); 1012e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers const bool virtual_or_interface = invoke_type == kVirtual || invoke_type == kInterface; 1013848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Resolve method filling in dex cache. 1014e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers if (!called_method_known_on_entry) { 1015eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<1> hs(self); 10160cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier mirror::Object* dummy = nullptr; 10170cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier HandleWrapper<mirror::Object> h_receiver( 10180cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier hs.NewHandleWrapper(virtual_or_interface ? &receiver : &dummy)); 1019e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers DCHECK_EQ(caller->GetDexFile(), called_method.dex_file); 102042ef8ab151a3d0cbb42cb43f6841c3708d65fca3Andreas Gampe called = linker->ResolveMethod<ClassLinker::kForceICCECheck>( 102142ef8ab151a3d0cbb42cb43f6841c3708d65fca3Andreas Gampe self, called_method.dex_method_index, caller, invoke_type); 1022848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 1023e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers const void* code = nullptr; 1024bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (LIKELY(!self->IsExceptionPending())) { 1025848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Incompatible class change should have been handled in resolve method. 10262ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom CHECK(!called->CheckIncompatibleClassChange(invoke_type)) 10272ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom << PrettyMethod(called) << " " << invoke_type; 1028e523423a053af5cb55837f07ceae9ff2fd581712Nicolas Geoffray if (virtual_or_interface || invoke_type == kSuper) { 1029e523423a053af5cb55837f07ceae9ff2fd581712Nicolas Geoffray // Refine called method based on receiver for kVirtual/kInterface, and 1030e523423a053af5cb55837f07ceae9ff2fd581712Nicolas Geoffray // caller for kSuper. 1031e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* orig_called = called; 103255871bf5277f8e8041f1303a416be2cd9215aa07Mathieu Chartier if (invoke_type == kVirtual) { 1033e523423a053af5cb55837f07ceae9ff2fd581712Nicolas Geoffray CHECK(receiver != nullptr) << invoke_type; 1034e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier called = receiver->GetClass()->FindVirtualMethodForVirtual(called, sizeof(void*)); 1035e523423a053af5cb55837f07ceae9ff2fd581712Nicolas Geoffray } else if (invoke_type == kInterface) { 1036e523423a053af5cb55837f07ceae9ff2fd581712Nicolas Geoffray CHECK(receiver != nullptr) << invoke_type; 1037e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier called = receiver->GetClass()->FindVirtualMethodForInterface(called, sizeof(void*)); 1038e523423a053af5cb55837f07ceae9ff2fd581712Nicolas Geoffray } else { 1039e523423a053af5cb55837f07ceae9ff2fd581712Nicolas Geoffray DCHECK_EQ(invoke_type, kSuper); 1040e523423a053af5cb55837f07ceae9ff2fd581712Nicolas Geoffray CHECK(caller != nullptr) << invoke_type; 104121aa4d405cbe3d4612e3f50ebb7610cc0b3503a2Nicolas Geoffray StackHandleScope<2> hs(self); 104221aa4d405cbe3d4612e3f50ebb7610cc0b3503a2Nicolas Geoffray Handle<mirror::DexCache> dex_cache( 104321aa4d405cbe3d4612e3f50ebb7610cc0b3503a2Nicolas Geoffray hs.NewHandle(caller->GetDeclaringClass()->GetDexCache())); 104421aa4d405cbe3d4612e3f50ebb7610cc0b3503a2Nicolas Geoffray Handle<mirror::ClassLoader> class_loader( 104521aa4d405cbe3d4612e3f50ebb7610cc0b3503a2Nicolas Geoffray hs.NewHandle(caller->GetDeclaringClass()->GetClassLoader())); 1046fedd91d50930e160c021d65b3740264f6ffec260Alex Light // TODO Maybe put this into a mirror::Class function. 1047fedd91d50930e160c021d65b3740264f6ffec260Alex Light mirror::Class* ref_class = linker->ResolveReferencedClassOfMethod( 104821aa4d405cbe3d4612e3f50ebb7610cc0b3503a2Nicolas Geoffray called_method.dex_method_index, dex_cache, class_loader); 1049fedd91d50930e160c021d65b3740264f6ffec260Alex Light if (ref_class->IsInterface()) { 1050fedd91d50930e160c021d65b3740264f6ffec260Alex Light called = ref_class->FindVirtualMethodForInterfaceSuper(called, sizeof(void*)); 1051fedd91d50930e160c021d65b3740264f6ffec260Alex Light } else { 1052fedd91d50930e160c021d65b3740264f6ffec260Alex Light called = caller->GetDeclaringClass()->GetSuperClass()->GetVTableEntry( 1053fedd91d50930e160c021d65b3740264f6ffec260Alex Light called->GetMethodIndex(), sizeof(void*)); 1054fedd91d50930e160c021d65b3740264f6ffec260Alex Light } 105555871bf5277f8e8041f1303a416be2cd9215aa07Mathieu Chartier } 1056f486778d50fc8afa61330df495e94f4f3ec0e238Mingyao Yang 1057f486778d50fc8afa61330df495e94f4f3ec0e238Mingyao Yang CHECK(called != nullptr) << PrettyMethod(orig_called) << " " 1058f486778d50fc8afa61330df495e94f4f3ec0e238Mingyao Yang << PrettyTypeOf(receiver) << " " 1059f486778d50fc8afa61330df495e94f4f3ec0e238Mingyao Yang << invoke_type << " " << orig_called->GetVtableIndex(); 1060f486778d50fc8afa61330df495e94f4f3ec0e238Mingyao Yang 106183883d7fddf30fdb8b6903560fa1337ab991e74cIan Rogers // We came here because of sharpening. Ensure the dex cache is up-to-date on the method index 1062e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers // of the sharpened method avoiding dirtying the dex cache if possible. 106300f1527007381a0cbf1a2b36b956cb3ddac906cbIan Rogers // Note, called_method.dex_method_index references the dex method before the 106400f1527007381a0cbf1a2b36b956cb3ddac906cbIan Rogers // FindVirtualMethodFor... This is ok for FindDexMethodIndexInOtherDexFile that only cares 106500f1527007381a0cbf1a2b36b956cb3ddac906cbIan Rogers // about the name and signature. 106600f1527007381a0cbf1a2b36b956cb3ddac906cbIan Rogers uint32_t update_dex_cache_method_index = called->GetDexMethodIndex(); 106705792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko if (!called->HasSameDexCacheResolvedMethods(caller, sizeof(void*))) { 106883883d7fddf30fdb8b6903560fa1337ab991e74cIan Rogers // Calling from one dex file to another, need to compute the method index appropriate to 1069bbcc0c0a17262f3d2a70fc0a82e1783862f708ccVladimir Marko // the caller's dex file. Since we get here only if the original called was a runtime 1070bbcc0c0a17262f3d2a70fc0a82e1783862f708ccVladimir Marko // method, we've got the correct dex_file and a dex_method_idx from above. 1071e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers DCHECK(!called_method_known_on_entry); 1072e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers DCHECK_EQ(caller->GetDexFile(), called_method.dex_file); 1073e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers const DexFile* caller_dex_file = called_method.dex_file; 1074e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers uint32_t caller_method_name_and_sig_index = called_method.dex_method_index; 1075e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers update_dex_cache_method_index = 1076e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers called->FindDexMethodIndexInOtherDexFile(*caller_dex_file, 1077e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers caller_method_name_and_sig_index); 1078e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers } 1079e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers if ((update_dex_cache_method_index != DexFile::kDexNoIndex) && 1080e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier (caller->GetDexCacheResolvedMethod( 1081e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier update_dex_cache_method_index, sizeof(void*)) != called)) { 1082e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier caller->SetDexCacheResolvedMethod(update_dex_cache_method_index, called, sizeof(void*)); 108383883d7fddf30fdb8b6903560fa1337ab991e74cIan Rogers } 1084e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6Mathieu Chartier } else if (invoke_type == kStatic) { 1085e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6Mathieu Chartier const auto called_dex_method_idx = called->GetDexMethodIndex(); 1086e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6Mathieu Chartier // For static invokes, we may dispatch to the static method in the superclass but resolve 1087e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6Mathieu Chartier // using the subclass. To prevent getting slow paths on each invoke, we force set the 1088e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6Mathieu Chartier // resolved method for the super class dex method index if we are in the same dex file. 1089e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6Mathieu Chartier // b/19175856 1090e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6Mathieu Chartier if (called->GetDexFile() == called_method.dex_file && 1091e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6Mathieu Chartier called_method.dex_method_index != called_dex_method_idx) { 1092e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier called->GetDexCache()->SetResolvedMethod(called_dex_method_idx, called, sizeof(void*)); 1093e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6Mathieu Chartier } 109483883d7fddf30fdb8b6903560fa1337ab991e74cIan Rogers } 1095eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi 1096848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Ensure that the called method's class is initialized. 1097eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<1> hs(soa.Self()); 1098eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::Class> called_class(hs.NewHandle(called->GetDeclaringClass())); 10997b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers linker->EnsureInitialized(soa.Self(), called_class, true, true); 1100848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers if (LIKELY(called_class->IsInitialized())) { 1101eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (UNLIKELY(Dbg::IsForcedInterpreterNeededForResolution(self, called))) { 1102eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are single-stepping or the called method is deoptimized (by a 1103eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // breakpoint, for example), then we have to execute the called method 1104eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // with the interpreter. 1105eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi code = GetQuickToInterpreterBridge(); 1106eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } else if (UNLIKELY(Dbg::IsForcedInstrumentationNeededForResolution(self, caller))) { 1107eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If the caller is deoptimized (by a breakpoint, for example), we have to 1108eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // continue its execution with interpreter when returning from the called 1109eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // method. Because we do not want to execute the called method with the 1110eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // interpreter, we wrap its execution into the instrumentation stubs. 1111eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // When the called method returns, it will execute the instrumentation 1112eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // exit hook that will determine the need of the interpreter with a call 1113eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // to Dbg::IsForcedInterpreterNeededForUpcall and deoptimize the stack if 1114eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // it is needed. 1115eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi code = GetQuickInstrumentationEntryPoint(); 1116eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } else { 1117eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi code = called->GetEntryPointFromQuickCompiledCode(); 1118eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } 1119848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } else if (called_class->IsInitializing()) { 1120eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi if (UNLIKELY(Dbg::IsForcedInterpreterNeededForResolution(self, called))) { 1121eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // If we are single-stepping or the called method is deoptimized (by a 1122eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // breakpoint, for example), then we have to execute the called method 1123eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi // with the interpreter. 1124eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi code = GetQuickToInterpreterBridge(); 1125eb07669e9784ccb41d75df180727e57fc4520e28Daniel Mihalyi } else if (invoke_type == kStatic) { 1126848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Class is still initializing, go to oat and grab code (trampoline must be left in place 1127848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // until class is initialized to stop races between threads). 1128ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers code = linker->GetQuickOatCodeFor(called); 1129848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } else { 1130848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // No trampoline for non-static methods. 1131ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers code = called->GetEntryPointFromQuickCompiledCode(); 1132848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 1133848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } else { 1134848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers DCHECK(called_class->IsErroneous()); 1135848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 1136848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 1137e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers CHECK_EQ(code == nullptr, self->IsExceptionPending()); 113807d447bebe6cc358e05ef041db84a5095a69e4f1Mathieu Chartier // Fixup any locally saved objects may have moved during a GC. 113907d447bebe6cc358e05ef041db84a5095a69e4f1Mathieu Chartier visitor.FixupReferences(); 1140848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Place called method in callee-save frame to be placed as first argument to quick method. 1141e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier *sp = called; 1142e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier 1143848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers return code; 1144848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers} 1145848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 1146c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe/* 1147c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * This class uses a couple of observations to unite the different calling conventions through 1148c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * a few constants. 1149c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1150c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1) Number of registers used for passing is normally even, so counting down has no penalty for 1151c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * possible alignment. 1152c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 2) Known 64b architectures store 8B units on the stack, both for integral and floating point 1153c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * types, so using uintptr_t is OK. Also means that we can use kRegistersNeededX to denote 1154c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * when we have to split things 1155c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 3) The only soft-float, Arm, is 32b, so no widening needs to be taken into account for floats 1156c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * and we can use Int handling directly. 1157c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 4) Only 64b architectures widen, and their stack is aligned 8B anyways, so no padding code 1158c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * necessary when widening. Also, widening of Ints will take place implicitly, and the 1159c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * extension should be compatible with Aarch64, which mandates copying the available bits 1160c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * into LSB and leaving the rest unspecified. 1161c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 5) Aligning longs and doubles is necessary on arm only, and it's the same in registers and on 1162c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * the stack. 1163c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 6) There is only little endian. 1164c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1165c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1166c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * Actual work is supposed to be done in a delegate of the template type. The interface is as 1167c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * follows: 1168c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1169c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * void PushGpr(uintptr_t): Add a value for the next GPR 1170c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1171c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * void PushFpr4(float): Add a value for the next FPR of size 32b. Is only called if we need 1172c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * padding, that is, think the architecture is 32b and aligns 64b. 1173c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1174c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * void PushFpr8(uint64_t): Push a double. We _will_ call this on 32b, it's the callee's job to 1175c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * split this if necessary. The current state will have aligned, if 1176c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * necessary. 1177c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1178c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * void PushStack(uintptr_t): Push a value to the stack. 1179c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1180eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier * uintptr_t PushHandleScope(mirror::Object* ref): Add a reference to the HandleScope. This _will_ have nullptr, 118136fea8dd490ab6439f391b8cd7f366c59f026fd2Andreas Gampe * as this might be important for null initialization. 1182c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * Must return the jobject, that is, the reference to the 1183eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier * entry in the HandleScope (nullptr if necessary). 1184c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1185c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe */ 1186c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampetemplate<class T> class BuildNativeCallFrameStateMachine { 1187c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe public: 1188bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe#if defined(__arm__) 1189bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe // TODO: These are all dummy values! 1190c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kNativeSoftFloatAbi = true; 1191c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr size_t kNumNativeGprArgs = 4; // 4 arguments passed in GPRs, r0-r3 1192bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kNumNativeFprArgs = 0; // 0 arguments passed in FPRs. 1193bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1194bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kRegistersNeededForLong = 2; 1195bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kRegistersNeededForDouble = 2; 1196c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kMultiRegistersAligned = true; 11971a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiFPRegistersWidened = false; 11981a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiGPRegistersWidened = false; 1199c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kAlignLongOnStack = true; 1200c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kAlignDoubleOnStack = true; 1201b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#elif defined(__aarch64__) 1202b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr bool kNativeSoftFloatAbi = false; // This is a hard float ABI. 1203b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr size_t kNumNativeGprArgs = 8; // 6 arguments passed in GPRs. 1204b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr size_t kNumNativeFprArgs = 8; // 8 arguments passed in FPRs. 1205b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith 1206b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr size_t kRegistersNeededForLong = 1; 1207b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr size_t kRegistersNeededForDouble = 1; 1208b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr bool kMultiRegistersAligned = false; 12091a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiFPRegistersWidened = false; 12101a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiGPRegistersWidened = false; 1211b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr bool kAlignLongOnStack = false; 1212b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith static constexpr bool kAlignDoubleOnStack = false; 12131a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe#elif defined(__mips__) && !defined(__LP64__) 1214bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr bool kNativeSoftFloatAbi = true; // This is a hard float ABI. 1215735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung static constexpr size_t kNumNativeGprArgs = 4; // 4 arguments passed in GPRs. 1216735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung static constexpr size_t kNumNativeFprArgs = 0; // 0 arguments passed in FPRs. 1217bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1218bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kRegistersNeededForLong = 2; 1219bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kRegistersNeededForDouble = 2; 1220c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kMultiRegistersAligned = true; 12211a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiFPRegistersWidened = true; 12221a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiGPRegistersWidened = false; 1223735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung static constexpr bool kAlignLongOnStack = true; 1224735b8559d6dd26c610d4b97d72f25a092d9c8947Douglas Leung static constexpr bool kAlignDoubleOnStack = true; 12251a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe#elif defined(__mips__) && defined(__LP64__) 12261a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe // Let the code prepare GPRs only and we will load the FPRs with same data. 12271a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kNativeSoftFloatAbi = true; 12281a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr size_t kNumNativeGprArgs = 8; 12291a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr size_t kNumNativeFprArgs = 0; 12301a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe 12311a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr size_t kRegistersNeededForLong = 1; 12321a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr size_t kRegistersNeededForDouble = 1; 12331a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiRegistersAligned = false; 12341a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiFPRegistersWidened = false; 12351a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiGPRegistersWidened = true; 12361a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kAlignLongOnStack = false; 12371a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kAlignDoubleOnStack = false; 1238bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe#elif defined(__i386__) 1239bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe // TODO: Check these! 1240c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kNativeSoftFloatAbi = false; // Not using int registers for fp 1241bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kNumNativeGprArgs = 0; // 6 arguments passed in GPRs. 1242bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kNumNativeFprArgs = 0; // 8 arguments passed in FPRs. 1243bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1244bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kRegistersNeededForLong = 2; 1245bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kRegistersNeededForDouble = 2; 1246c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe static constexpr bool kMultiRegistersAligned = false; // x86 not using regs, anyways 12471a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiFPRegistersWidened = false; 12481a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiGPRegistersWidened = false; 1249c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kAlignLongOnStack = false; 1250c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kAlignDoubleOnStack = false; 1251bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe#elif defined(__x86_64__) 1252bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr bool kNativeSoftFloatAbi = false; // This is a hard float ABI. 1253bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kNumNativeGprArgs = 6; // 6 arguments passed in GPRs. 1254bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kNumNativeFprArgs = 8; // 8 arguments passed in FPRs. 1255bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1256bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kRegistersNeededForLong = 1; 1257bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe static constexpr size_t kRegistersNeededForDouble = 1; 1258c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kMultiRegistersAligned = false; 12591a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiFPRegistersWidened = false; 12601a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe static constexpr bool kMultiGPRegistersWidened = false; 1261c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kAlignLongOnStack = false; 1262c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe static constexpr bool kAlignDoubleOnStack = false; 1263bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe#else 1264bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe#error "Unsupported architecture" 1265bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe#endif 1266bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1267c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe public: 1268c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe explicit BuildNativeCallFrameStateMachine(T* delegate) 1269c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe : gpr_index_(kNumNativeGprArgs), 1270c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe fpr_index_(kNumNativeFprArgs), 1271c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe stack_entries_(0), 1272c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe delegate_(delegate) { 1273c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // For register alignment, we want to assume that counters (gpr_index_, fpr_index_) are even iff 1274c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // the next register is even; counting down is just to make the compiler happy... 1275575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe static_assert(kNumNativeGprArgs % 2 == 0U, "Number of native GPR arguments not even"); 1276575e78c41ece0dec969d31f46be563d4eb7ae43bAndreas Gampe static_assert(kNumNativeFprArgs % 2 == 0U, "Number of native FPR arguments not even"); 1277c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1278c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1279c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe virtual ~BuildNativeCallFrameStateMachine() {} 1280c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 12811428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool HavePointerGpr() const { 1282c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return gpr_index_ > 0; 1283c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1284c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1285c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe void AdvancePointer(const void* val) { 1286c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (HavePointerGpr()) { 1287c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe gpr_index_--; 1288c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushGpr(reinterpret_cast<uintptr_t>(val)); 1289c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1290c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe stack_entries_++; // TODO: have a field for pointer length as multiple of 32b 1291c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushStack(reinterpret_cast<uintptr_t>(val)); 1292c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe gpr_index_ = 0; 1293c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1294c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1295c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 12961428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool HaveHandleScopeGpr() const { 1297c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return gpr_index_ > 0; 1298c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1299c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 130090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void AdvanceHandleScope(mirror::Object* ptr) SHARED_REQUIRES(Locks::mutator_lock_) { 1301eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier uintptr_t handle = PushHandle(ptr); 1302eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier if (HaveHandleScopeGpr()) { 1303c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe gpr_index_--; 1304eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier PushGpr(handle); 1305c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1306c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe stack_entries_++; 1307eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier PushStack(handle); 1308c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe gpr_index_ = 0; 1309c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1310c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1311c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 13121428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool HaveIntGpr() const { 1313c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return gpr_index_ > 0; 1314c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1315c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1316c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void AdvanceInt(uint32_t val) { 1317c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (HaveIntGpr()) { 1318c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe gpr_index_--; 13191a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe if (kMultiGPRegistersWidened) { 13201a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe DCHECK_EQ(sizeof(uintptr_t), sizeof(int64_t)); 1321da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain PushGpr(static_cast<int64_t>(bit_cast<int32_t, uint32_t>(val))); 13221a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe } else { 13231a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe PushGpr(val); 13241a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe } 1325c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1326c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe stack_entries_++; 13271a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe if (kMultiGPRegistersWidened) { 13281a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe DCHECK_EQ(sizeof(uintptr_t), sizeof(int64_t)); 1329da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain PushStack(static_cast<int64_t>(bit_cast<int32_t, uint32_t>(val))); 13301a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe } else { 13311a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe PushStack(val); 13321a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe } 1333c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe gpr_index_ = 0; 1334c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1335c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1336c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 13371428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool HaveLongGpr() const { 1338c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return gpr_index_ >= kRegistersNeededForLong + (LongGprNeedsPadding() ? 1 : 0); 1339c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1340c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 13411428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool LongGprNeedsPadding() const { 1342c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return kRegistersNeededForLong > 1 && // only pad when using multiple registers 1343c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe kAlignLongOnStack && // and when it needs alignment 1344c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe (gpr_index_ & 1) == 1; // counter is odd, see constructor 1345c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1346c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 13471428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool LongStackNeedsPadding() const { 1348c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return kRegistersNeededForLong > 1 && // only pad when using multiple registers 1349c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe kAlignLongOnStack && // and when it needs 8B alignment 1350c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe (stack_entries_ & 1) == 1; // counter is odd 1351c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1352c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1353c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void AdvanceLong(uint64_t val) { 1354c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (HaveLongGpr()) { 1355c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (LongGprNeedsPadding()) { 1356c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushGpr(0); 1357c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe gpr_index_--; 1358c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1359c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (kRegistersNeededForLong == 1) { 1360c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushGpr(static_cast<uintptr_t>(val)); 1361c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1362c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushGpr(static_cast<uintptr_t>(val & 0xFFFFFFFF)); 1363c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushGpr(static_cast<uintptr_t>((val >> 32) & 0xFFFFFFFF)); 1364c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1365c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe gpr_index_ -= kRegistersNeededForLong; 1366c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1367c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (LongStackNeedsPadding()) { 1368c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushStack(0); 1369c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe stack_entries_++; 1370c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1371c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (kRegistersNeededForLong == 1) { 1372c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushStack(static_cast<uintptr_t>(val)); 1373c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe stack_entries_++; 1374c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1375c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushStack(static_cast<uintptr_t>(val & 0xFFFFFFFF)); 1376c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushStack(static_cast<uintptr_t>((val >> 32) & 0xFFFFFFFF)); 1377c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe stack_entries_ += 2; 1378c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1379c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe gpr_index_ = 0; 1380c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1381c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1382c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 13831428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool HaveFloatFpr() const { 1384c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return fpr_index_ > 0; 1385c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1386c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1387c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void AdvanceFloat(float val) { 1388c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (kNativeSoftFloatAbi) { 1389da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain AdvanceInt(bit_cast<uint32_t, float>(val)); 1390c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1391c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (HaveFloatFpr()) { 1392c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe fpr_index_--; 1393c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (kRegistersNeededForDouble == 1) { 13941a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe if (kMultiFPRegistersWidened) { 1395da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain PushFpr8(bit_cast<uint64_t, double>(val)); 1396c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1397c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // No widening, just use the bits. 1398da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain PushFpr8(static_cast<uint64_t>(bit_cast<uint32_t, float>(val))); 1399c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1400c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1401c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushFpr4(val); 1402c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1403c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1404c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe stack_entries_++; 14051a5c40672783fac98aca5a04ac798a0a0014de65Andreas Gampe if (kRegistersNeededForDouble == 1 && kMultiFPRegistersWidened) { 1406c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // Need to widen before storing: Note the "double" in the template instantiation. 1407c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Note: We need to jump through those hoops to make the compiler happy. 1408c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe DCHECK_EQ(sizeof(uintptr_t), sizeof(uint64_t)); 1409da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain PushStack(static_cast<uintptr_t>(bit_cast<uint64_t, double>(val))); 1410c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1411da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain PushStack(static_cast<uintptr_t>(bit_cast<uint32_t, float>(val))); 1412c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1413c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe fpr_index_ = 0; 1414c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1415c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1416c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1417c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 14181428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool HaveDoubleFpr() const { 1419c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return fpr_index_ >= kRegistersNeededForDouble + (DoubleFprNeedsPadding() ? 1 : 0); 1420c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1421c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 14221428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool DoubleFprNeedsPadding() const { 1423c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return kRegistersNeededForDouble > 1 && // only pad when using multiple registers 1424c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe kAlignDoubleOnStack && // and when it needs alignment 1425c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe (fpr_index_ & 1) == 1; // counter is odd, see constructor 1426c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1427c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 14281428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers bool DoubleStackNeedsPadding() const { 1429c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return kRegistersNeededForDouble > 1 && // only pad when using multiple registers 1430c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe kAlignDoubleOnStack && // and when it needs 8B alignment 1431c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe (stack_entries_ & 1) == 1; // counter is odd 1432c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1433c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1434c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void AdvanceDouble(uint64_t val) { 1435c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (kNativeSoftFloatAbi) { 1436c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe AdvanceLong(val); 1437c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1438c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (HaveDoubleFpr()) { 1439c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (DoubleFprNeedsPadding()) { 1440c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushFpr4(0); 1441c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe fpr_index_--; 1442c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1443c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushFpr8(val); 1444c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe fpr_index_ -= kRegistersNeededForDouble; 1445c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1446c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (DoubleStackNeedsPadding()) { 1447c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushStack(0); 1448c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe stack_entries_++; 1449c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1450c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe if (kRegistersNeededForDouble == 1) { 1451c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushStack(static_cast<uintptr_t>(val)); 1452c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe stack_entries_++; 1453c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } else { 1454c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushStack(static_cast<uintptr_t>(val & 0xFFFFFFFF)); 1455c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe PushStack(static_cast<uintptr_t>((val >> 32) & 0xFFFFFFFF)); 1456c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe stack_entries_ += 2; 1457c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1458c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe fpr_index_ = 0; 1459c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1460c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1461c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1462c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 14631428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers uint32_t GetStackEntries() const { 1464c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return stack_entries_; 1465c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1466c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 14671428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers uint32_t GetNumberOfUsedGprs() const { 1468c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return kNumNativeGprArgs - gpr_index_; 1469c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1470c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 14711428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers uint32_t GetNumberOfUsedFprs() const { 1472c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return kNumNativeFprArgs - fpr_index_; 1473c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1474c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1475c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe private: 1476c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushGpr(uintptr_t val) { 1477c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe delegate_->PushGpr(val); 1478c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1479c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushFpr4(float val) { 1480c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe delegate_->PushFpr4(val); 1481c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1482c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushFpr8(uint64_t val) { 1483c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe delegate_->PushFpr8(val); 1484c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1485c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushStack(uintptr_t val) { 1486c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe delegate_->PushStack(val); 1487c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 148890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier uintptr_t PushHandle(mirror::Object* ref) SHARED_REQUIRES(Locks::mutator_lock_) { 1489eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return delegate_->PushHandle(ref); 1490c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1491c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1492c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe uint32_t gpr_index_; // Number of free GPRs 1493c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe uint32_t fpr_index_; // Number of free FPRs 1494c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe uint32_t stack_entries_; // Stack entries are in multiples of 32b, as floats are usually not 1495c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // extended 14961428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers T* const delegate_; // What Push implementation gets called 1497c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe}; 1498bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1499c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe// Computes the sizes of register stacks and call stack area. Handling of references can be extended 1500c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe// in subclasses. 1501c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe// 1502c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe// To handle native pointers, use "L" in the shorty for an object reference, which simulates 1503c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe// them with handles. 1504c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeclass ComputeNativeCallFrameSize { 1505c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe public: 1506c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe ComputeNativeCallFrameSize() : num_stack_entries_(0) {} 1507c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1508c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe virtual ~ComputeNativeCallFrameSize() {} 1509c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 15101428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers uint32_t GetStackSize() const { 1511c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return num_stack_entries_ * sizeof(uintptr_t); 1512c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1513c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 15141428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers uint8_t* LayoutCallStack(uint8_t* sp8) const { 1515c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe sp8 -= GetStackSize(); 1516779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe // Align by kStackAlignment. 1517779f8c951c0fbe36d4b213113a99541132947bb7Andreas Gampe sp8 = reinterpret_cast<uint8_t*>(RoundDown(reinterpret_cast<uintptr_t>(sp8), kStackAlignment)); 1518c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return sp8; 1519c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1520c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 15211428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers uint8_t* LayoutCallRegisterStacks(uint8_t* sp8, uintptr_t** start_gpr, uint32_t** start_fpr) 15221428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers const { 1523c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // Assumption is OK right now, as we have soft-float arm 1524c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe size_t fregs = BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>::kNumNativeFprArgs; 1525c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe sp8 -= fregs * sizeof(uintptr_t); 1526c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe *start_fpr = reinterpret_cast<uint32_t*>(sp8); 1527c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe size_t iregs = BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>::kNumNativeGprArgs; 1528c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe sp8 -= iregs * sizeof(uintptr_t); 1529c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe *start_gpr = reinterpret_cast<uintptr_t*>(sp8); 1530c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return sp8; 1531c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1532c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1533c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uint8_t* LayoutNativeCall(uint8_t* sp8, uintptr_t** start_stack, uintptr_t** start_gpr, 15341428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers uint32_t** start_fpr) const { 1535c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Native call stack. 1536c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe sp8 = LayoutCallStack(sp8); 1537c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe *start_stack = reinterpret_cast<uintptr_t*>(sp8); 1538c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1539c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Put fprs and gprs below. 1540c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe sp8 = LayoutCallRegisterStacks(sp8, start_gpr, start_fpr); 154136fea8dd490ab6439f391b8cd7f366c59f026fd2Andreas Gampe 1542c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Return the new bottom. 1543c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return sp8; 1544c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1545c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 15464b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain virtual void WalkHeader( 15474b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm ATTRIBUTE_UNUSED) 154890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 15496a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers } 1550c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 155190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void Walk(const char* shorty, uint32_t shorty_len) SHARED_REQUIRES(Locks::mutator_lock_) { 1552c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize> sm(this); 1553c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1554c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe WalkHeader(&sm); 1555c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1556c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe for (uint32_t i = 1; i < shorty_len; ++i) { 1557c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe Primitive::Type cur_type_ = Primitive::GetType(shorty[i]); 1558c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe switch (cur_type_) { 1559c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe case Primitive::kPrimNot: 15601d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers // TODO: fix abuse of mirror types. 1561c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe sm.AdvanceHandleScope( 1562c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe reinterpret_cast<mirror::Object*>(0x12345678)); 1563c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe break; 1564c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1565c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe case Primitive::kPrimBoolean: 1566c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe case Primitive::kPrimByte: 1567c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe case Primitive::kPrimChar: 1568c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe case Primitive::kPrimShort: 1569c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe case Primitive::kPrimInt: 1570c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe sm.AdvanceInt(0); 1571c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe break; 1572c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe case Primitive::kPrimFloat: 1573c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe sm.AdvanceFloat(0); 1574c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe break; 1575c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe case Primitive::kPrimDouble: 1576c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe sm.AdvanceDouble(0); 1577c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe break; 1578c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe case Primitive::kPrimLong: 1579c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe sm.AdvanceLong(0); 1580c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe break; 1581c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe default: 1582c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe LOG(FATAL) << "Unexpected type: " << cur_type_ << " in " << shorty; 1583e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers UNREACHABLE(); 1584c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1585c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1586c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 15871428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers num_stack_entries_ = sm.GetStackEntries(); 1588c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1589c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1590c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushGpr(uintptr_t /* val */) { 1591c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // not optimizing registers, yet 1592c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1593c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1594c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushFpr4(float /* val */) { 1595c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // not optimizing registers, yet 1596c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1597c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1598c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushFpr8(uint64_t /* val */) { 1599c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // not optimizing registers, yet 1600c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1601c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1602c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushStack(uintptr_t /* val */) { 1603c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // counting is already done in the superclass 1604c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1605c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1606c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe virtual uintptr_t PushHandle(mirror::Object* /* ptr */) { 1607c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe return reinterpret_cast<uintptr_t>(nullptr); 1608c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1609c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1610c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe protected: 1611c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe uint32_t num_stack_entries_; 1612c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe}; 1613c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1614c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeclass ComputeGenericJniFrameSize FINAL : public ComputeNativeCallFrameSize { 1615bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe public: 1616c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe ComputeGenericJniFrameSize() : num_handle_scope_references_(0) {} 1617c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1618c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Lays out the callee-save frame. Assumes that the incorrect frame corresponding to RefsAndArgs 1619c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // is at *m = sp. Will update to point to the bottom of the save frame. 1620c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // 1621c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Note: assumes ComputeAll() has been run before. 1622e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier void LayoutCalleeSaveFrame(Thread* self, ArtMethod*** m, void* sp, HandleScope** handle_scope) 162390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 1624e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method = **m; 1625e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier 1626e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*)); 1627bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1628c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uint8_t* sp8 = reinterpret_cast<uint8_t*>(sp); 1629bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1630c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // First, fix up the layout of the callee-save frame. 1631c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // We have to squeeze in the HandleScope, and relocate the method pointer. 1632bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1633c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // "Free" the slot for the method. 163413735955f39b3b304c37d2b2840663c131262c18Ian Rogers sp8 += sizeof(void*); // In the callee-save frame we use a full pointer. 1635bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1636c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Under the callee saves put handle scope and new method stack reference. 1637c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe size_t handle_scope_size = HandleScope::SizeOf(num_handle_scope_references_); 1638e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier size_t scope_and_method = handle_scope_size + sizeof(ArtMethod*); 1639c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1640c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe sp8 -= scope_and_method; 1641c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Align by kStackAlignment. 1642e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier sp8 = reinterpret_cast<uint8_t*>(RoundDown(reinterpret_cast<uintptr_t>(sp8), kStackAlignment)); 1643c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1644e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint8_t* sp8_table = sp8 + sizeof(ArtMethod*); 164559c07060a6fbb93e455b44f00098cafb8e7e26ccIan Rogers *handle_scope = HandleScope::Create(sp8_table, self->GetTopHandleScope(), 164659c07060a6fbb93e455b44f00098cafb8e7e26ccIan Rogers num_handle_scope_references_); 1647c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1648c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Add a slot for the method pointer, and fill it. Fix the pointer-pointer given to us. 1649c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uint8_t* method_pointer = sp8; 1650e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto** new_method_ref = reinterpret_cast<ArtMethod**>(method_pointer); 1651e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier *new_method_ref = method; 1652c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe *m = new_method_ref; 1653c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1654c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1655c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Adds space for the cookie. Note: may leave stack unaligned. 16561428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers void LayoutCookie(uint8_t** sp) const { 1657c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Reference cookie and padding 1658c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe *sp -= 8; 1659c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1660c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1661c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Re-layout the callee-save frame (insert a handle-scope). Then add space for the cookie. 1662c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Returns the new bottom. Note: this may be unaligned. 1663e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint8_t* LayoutJNISaveFrame(Thread* self, ArtMethod*** m, void* sp, HandleScope** handle_scope) 166490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 1665c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // First, fix up the layout of the callee-save frame. 1666c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // We have to squeeze in the HandleScope, and relocate the method pointer. 166759c07060a6fbb93e455b44f00098cafb8e7e26ccIan Rogers LayoutCalleeSaveFrame(self, m, sp, handle_scope); 1668c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1669c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // The bottom of the callee-save frame is now where the method is, *m. 1670c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uint8_t* sp8 = reinterpret_cast<uint8_t*>(*m); 1671c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1672c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Add space for cookie. 1673c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe LayoutCookie(&sp8); 1674c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1675c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return sp8; 16760cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier } 16770cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier 1678c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // WARNING: After this, *sp won't be pointing to the method anymore! 1679e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint8_t* ComputeLayout(Thread* self, ArtMethod*** m, const char* shorty, uint32_t shorty_len, 1680e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier HandleScope** handle_scope, uintptr_t** start_stack, uintptr_t** start_gpr, 1681e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint32_t** start_fpr) 168290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 1683c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe Walk(shorty, shorty_len); 1684c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1685c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // JNI part. 168659c07060a6fbb93e455b44f00098cafb8e7e26ccIan Rogers uint8_t* sp8 = LayoutJNISaveFrame(self, m, reinterpret_cast<void*>(*m), handle_scope); 1687c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1688c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe sp8 = LayoutNativeCall(sp8, start_stack, start_gpr, start_fpr); 1689c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1690c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Return the new bottom. 1691c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return sp8; 1692c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1693c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1694c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uintptr_t PushHandle(mirror::Object* /* ptr */) OVERRIDE; 1695c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1696c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Add JNIEnv* and jobj/jclass before the shorty-derived elements. 1697c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe void WalkHeader(BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm) OVERRIDE 169890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_); 1699c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1700c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe private: 1701c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uint32_t num_handle_scope_references_; 1702c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe}; 1703c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1704c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeuintptr_t ComputeGenericJniFrameSize::PushHandle(mirror::Object* /* ptr */) { 1705c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe num_handle_scope_references_++; 1706c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return reinterpret_cast<uintptr_t>(nullptr); 1707c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe} 1708c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1709c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampevoid ComputeGenericJniFrameSize::WalkHeader( 1710c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm) { 1711c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // JNIEnv 1712c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe sm->AdvancePointer(nullptr); 1713c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1714c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Class object or this as first argument 1715c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe sm->AdvanceHandleScope(reinterpret_cast<mirror::Object*>(0x12345678)); 1716c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe} 1717c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1718c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe// Class to push values to three separate regions. Used to fill the native call part. Adheres to 1719c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe// the template requirements of BuildGenericJniFrameStateMachine. 1720c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeclass FillNativeCall { 1721c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe public: 1722c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe FillNativeCall(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args) : 1723c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe cur_gpr_reg_(gpr_regs), cur_fpr_reg_(fpr_regs), cur_stack_arg_(stack_args) {} 1724c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1725c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe virtual ~FillNativeCall() {} 1726c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1727c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe void Reset(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args) { 1728c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe cur_gpr_reg_ = gpr_regs; 1729c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe cur_fpr_reg_ = fpr_regs; 1730c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe cur_stack_arg_ = stack_args; 1731bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 1732bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1733c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushGpr(uintptr_t val) { 1734c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe *cur_gpr_reg_ = val; 1735c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe cur_gpr_reg_++; 1736bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 1737bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1738c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushFpr4(float val) { 1739c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe *cur_fpr_reg_ = val; 1740c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe cur_fpr_reg_++; 1741bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 1742bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1743c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushFpr8(uint64_t val) { 1744c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe uint64_t* tmp = reinterpret_cast<uint64_t*>(cur_fpr_reg_); 1745c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe *tmp = val; 1746c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe cur_fpr_reg_ += 2; 1747bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 1748bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1749c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe void PushStack(uintptr_t val) { 1750c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe *cur_stack_arg_ = val; 1751c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe cur_stack_arg_++; 1752bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 1753bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 175490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier virtual uintptr_t PushHandle(mirror::Object*) SHARED_REQUIRES(Locks::mutator_lock_) { 1755c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe LOG(FATAL) << "(Non-JNI) Native call does not use handles."; 17566a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 1757c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1758c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1759c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe private: 1760c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uintptr_t* cur_gpr_reg_; 1761c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uint32_t* cur_fpr_reg_; 1762c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uintptr_t* cur_stack_arg_; 1763c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe}; 1764c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1765c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe// Visits arguments on the stack placing them into a region lower down the stack for the benefit 1766c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe// of transitioning into native code. 1767c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeclass BuildGenericJniFrameVisitor FINAL : public QuickArgumentVisitor { 1768c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe public: 176959c07060a6fbb93e455b44f00098cafb8e7e26ccIan Rogers BuildGenericJniFrameVisitor(Thread* self, bool is_static, const char* shorty, uint32_t shorty_len, 1770e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod*** sp) 1771c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe : QuickArgumentVisitor(*sp, is_static, shorty, shorty_len), 1772c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe jni_call_(nullptr, nullptr, nullptr, nullptr), sm_(&jni_call_) { 1773c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe ComputeGenericJniFrameSize fsc; 1774c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uintptr_t* start_gpr_reg; 1775c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uint32_t* start_fpr_reg; 1776c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uintptr_t* start_stack_arg; 17776a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers bottom_of_used_area_ = fsc.ComputeLayout(self, sp, shorty, shorty_len, 177859c07060a6fbb93e455b44f00098cafb8e7e26ccIan Rogers &handle_scope_, 177959c07060a6fbb93e455b44f00098cafb8e7e26ccIan Rogers &start_stack_arg, 1780c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe &start_gpr_reg, &start_fpr_reg); 1781c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1782c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe jni_call_.Reset(start_gpr_reg, start_fpr_reg, start_stack_arg, handle_scope_); 1783c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1784c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // jni environment is always first argument 1785c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe sm_.AdvancePointer(self->GetJniEnv()); 1786c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1787c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe if (is_static) { 1788e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier sm_.AdvanceHandleScope((**sp)->GetDeclaringClass()); 178936fea8dd490ab6439f391b8cd7f366c59f026fd2Andreas Gampe } 1790bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 1791bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 179290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void Visit() SHARED_REQUIRES(Locks::mutator_lock_) OVERRIDE; 1793c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 179490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void FinalizeHandleScope(Thread* self) SHARED_REQUIRES(Locks::mutator_lock_); 1795c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1796f39745e663f8f2634fc8858e427b77da98f8f2b4Vladimir Marko StackReference<mirror::Object>* GetFirstHandleScopeEntry() { 1797c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return handle_scope_->GetHandle(0).GetReference(); 1798c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1799c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 180090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier jobject GetFirstHandleScopeJObject() const SHARED_REQUIRES(Locks::mutator_lock_) { 1801c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return handle_scope_->GetHandle(0).ToJObject(); 1802c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe } 1803bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 18041428dce77b8b0e8ec3e3665d816678df1253fc10Ian Rogers void* GetBottomOfUsedArea() const { 1805c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return bottom_of_used_area_; 1806bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 1807bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1808c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe private: 1809c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // A class to fill a JNI call. Adds reference/handle-scope management to FillNativeCall. 1810c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe class FillJniCall FINAL : public FillNativeCall { 1811c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe public: 1812c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe FillJniCall(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args, 1813c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe HandleScope* handle_scope) : FillNativeCall(gpr_regs, fpr_regs, stack_args), 1814c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe handle_scope_(handle_scope), cur_entry_(0) {} 1815c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 181690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier uintptr_t PushHandle(mirror::Object* ref) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_); 1817c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1818c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe void Reset(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args, HandleScope* scope) { 1819c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe FillNativeCall::Reset(gpr_regs, fpr_regs, stack_args); 1820c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe handle_scope_ = scope; 1821c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe cur_entry_ = 0U; 1822c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1823c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 182490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier void ResetRemainingScopeSlots() SHARED_REQUIRES(Locks::mutator_lock_) { 1825c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Initialize padding entries. 1826c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe size_t expected_slots = handle_scope_->NumberOfReferences(); 1827c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe while (cur_entry_ < expected_slots) { 18285a4b8a236030460651a3136397d23ca6744e7eb7Andreas Gampe handle_scope_->GetMutableHandle(cur_entry_++).Assign(nullptr); 1829c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1830c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe DCHECK_NE(cur_entry_, 0U); 1831c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe } 1832c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1833c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe private: 1834c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe HandleScope* handle_scope_; 1835c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe size_t cur_entry_; 1836c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe }; 1837c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 1838eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier HandleScope* handle_scope_; 1839c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe FillJniCall jni_call_; 1840c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe void* bottom_of_used_area_; 1841c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe 1842c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe BuildNativeCallFrameStateMachine<FillJniCall> sm_; 1843bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1844bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe DISALLOW_COPY_AND_ASSIGN(BuildGenericJniFrameVisitor); 1845bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe}; 1846bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1847c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeuintptr_t BuildGenericJniFrameVisitor::FillJniCall::PushHandle(mirror::Object* ref) { 1848c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe uintptr_t tmp; 18495a4b8a236030460651a3136397d23ca6744e7eb7Andreas Gampe MutableHandle<mirror::Object> h = handle_scope_->GetMutableHandle(cur_entry_); 1850c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe h.Assign(ref); 1851c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe tmp = reinterpret_cast<uintptr_t>(h.ToJObject()); 1852c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe cur_entry_++; 1853c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return tmp; 1854c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe} 1855c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 18569758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogersvoid BuildGenericJniFrameVisitor::Visit() { 18579758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers Primitive::Type type = GetParamPrimitiveType(); 18589758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers switch (type) { 18599758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimLong: { 18609758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers jlong long_arg; 18619758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers if (IsSplitLongOrDouble()) { 18629758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers long_arg = ReadSplitLongParam(); 18639758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } else { 18649758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers long_arg = *reinterpret_cast<jlong*>(GetParamAddress()); 18659758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 18669758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers sm_.AdvanceLong(long_arg); 18679758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 18689758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 18699758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimDouble: { 18709758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers uint64_t double_arg; 18719758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers if (IsSplitLongOrDouble()) { 18729758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers // Read into union so that we don't case to a double. 18739758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers double_arg = ReadSplitLongParam(); 18749758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } else { 18759758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers double_arg = *reinterpret_cast<uint64_t*>(GetParamAddress()); 18769758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 18779758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers sm_.AdvanceDouble(double_arg); 18789758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 18799758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 18809758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimNot: { 18819758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers StackReference<mirror::Object>* stack_ref = 18829758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress()); 1883eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier sm_.AdvanceHandleScope(stack_ref->AsMirrorPtr()); 18849758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 18859758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 18869758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimFloat: 18879758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers sm_.AdvanceFloat(*reinterpret_cast<float*>(GetParamAddress())); 18889758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 18899758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimBoolean: // Fall-through. 18909758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimByte: // Fall-through. 18919758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimChar: // Fall-through. 18929758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimShort: // Fall-through. 18939758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimInt: // Fall-through. 18949758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers sm_.AdvanceInt(*reinterpret_cast<jint*>(GetParamAddress())); 18959758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers break; 18969758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers case Primitive::kPrimVoid: 18979758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers LOG(FATAL) << "UNREACHABLE"; 18982c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers UNREACHABLE(); 18999758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers } 19009758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers} 19019758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers 1902eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartiervoid BuildGenericJniFrameVisitor::FinalizeHandleScope(Thread* self) { 1903c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Clear out rest of the scope. 1904c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe jni_call_.ResetRemainingScopeSlots(); 1905eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Install HandleScope. 1906eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier self->PushHandleScope(handle_scope_); 19079758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers} 19089758f79a6c1ef7f662caca9c1df39de1934166b8Ian Rogers 190904c31d2c984d382b4186974fa0a416aecbed2625Ian Rogers#if defined(__arm__) || defined(__aarch64__) 191090546836312adda54f28b700f25ff29ec8becdf8Andreas Gampeextern "C" void* artFindNativeMethod(); 191104c31d2c984d382b4186974fa0a416aecbed2625Ian Rogers#else 191204c31d2c984d382b4186974fa0a416aecbed2625Ian Rogersextern "C" void* artFindNativeMethod(Thread* self); 191304c31d2c984d382b4186974fa0a416aecbed2625Ian Rogers#endif 191490546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe 1915ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampeuint64_t artQuickGenericJniEndJNIRef(Thread* self, uint32_t cookie, jobject l, jobject lock) { 1916ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe if (lock != nullptr) { 1917ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe return reinterpret_cast<uint64_t>(JniMethodEndWithReferenceSynchronized(l, cookie, lock, self)); 1918ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe } else { 1919ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe return reinterpret_cast<uint64_t>(JniMethodEndWithReference(l, cookie, self)); 1920ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe } 1921ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe} 1922ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe 1923ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampevoid artQuickGenericJniEndJNINonRef(Thread* self, uint32_t cookie, jobject lock) { 1924ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe if (lock != nullptr) { 1925ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe JniMethodEndSynchronized(cookie, lock, self); 1926ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe } else { 1927ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe JniMethodEnd(cookie, self); 1928ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe } 1929ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe} 1930ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe 1931c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe/* 1932c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * Initializes an alloca region assumed to be directly below sp for a native call: 1933eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier * Create a HandleScope and call stack and fill a mini stack with values to be pushed to registers. 1934c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * The final element on the stack is a pointer to the native code. 1935c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 193636fea8dd490ab6439f391b8cd7f366c59f026fd2Andreas Gampe * On entry, the stack has a standard callee-save frame above sp, and an alloca below it. 1937eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier * We need to fix this, as the handle scope needs to go into the callee-save frame. 193836fea8dd490ab6439f391b8cd7f366c59f026fd2Andreas Gampe * 1939c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * The return of this function denotes: 1940c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 1) How many bytes of the alloca can be released, if the value is non-negative. 1941c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe * 2) An error, if the value is negative. 1942c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe */ 1943e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierextern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self, ArtMethod** sp) 194490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 1945e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* called = *sp; 194636fea8dd490ab6439f391b8cd7f366c59f026fd2Andreas Gampe DCHECK(called->IsNative()) << PrettyMethod(called, true); 1947bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier uint32_t shorty_len = 0; 1948bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier const char* shorty = called->GetShorty(&shorty_len); 1949c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe 19501d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers // Run the visitor and update sp. 195159c07060a6fbb93e455b44f00098cafb8e7e26ccIan Rogers BuildGenericJniFrameVisitor visitor(self, called->IsStatic(), shorty, shorty_len, &sp); 1952bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe visitor.VisitArguments(); 1953eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier visitor.FinalizeHandleScope(self); 1954bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1955c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Fix up managed-stack things in Thread. 19561d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers self->SetTopOfStack(sp); 1957bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 1958e0dcd46314d07eeb332edea292f5110178e4e3d2Ian Rogers self->VerifyStack(); 1959e0dcd46314d07eeb332edea292f5110178e4e3d2Ian Rogers 196090546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe // Start JNI, save the cookie. 1961bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe uint32_t cookie; 1962bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (called->IsSynchronized()) { 19630cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier cookie = JniMethodStartSynchronized(visitor.GetFirstHandleScopeJObject(), self); 1964bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe if (self->IsExceptionPending()) { 1965eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier self->PopHandleScope(); 1966c147b00f86c28f5275c99c8ce515499c90c01e31Andreas Gampe // A negative value denotes an error. 1967c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return GetTwoWordFailureValue(); 1968bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 1969bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } else { 1970bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe cookie = JniMethodStart(self); 1971bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 197236fea8dd490ab6439f391b8cd7f366c59f026fd2Andreas Gampe uint32_t* sp32 = reinterpret_cast<uint32_t*>(sp); 1973e0dcd46314d07eeb332edea292f5110178e4e3d2Ian Rogers *(sp32 - 1) = cookie; 1974bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 197590546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe // Retrieve the stored native code. 19762d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier void* nativeCode = called->GetEntryPointFromJni(); 197790546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe 19789a6a99aaac2e4c973e0bc71075f196b8b084100fAndreas Gampe // There are two cases for the content of nativeCode: 19799a6a99aaac2e4c973e0bc71075f196b8b084100fAndreas Gampe // 1) Pointer to the native function. 19809a6a99aaac2e4c973e0bc71075f196b8b084100fAndreas Gampe // 2) Pointer to the trampoline for native code binding. 19819a6a99aaac2e4c973e0bc71075f196b8b084100fAndreas Gampe // In the second case, we need to execute the binding and continue with the actual native function 19829a6a99aaac2e4c973e0bc71075f196b8b084100fAndreas Gampe // pointer. 198390546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe DCHECK(nativeCode != nullptr); 198490546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe if (nativeCode == GetJniDlsymLookupStub()) { 198504c31d2c984d382b4186974fa0a416aecbed2625Ian Rogers#if defined(__arm__) || defined(__aarch64__) 198690546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe nativeCode = artFindNativeMethod(); 198704c31d2c984d382b4186974fa0a416aecbed2625Ian Rogers#else 198804c31d2c984d382b4186974fa0a416aecbed2625Ian Rogers nativeCode = artFindNativeMethod(self); 198904c31d2c984d382b4186974fa0a416aecbed2625Ian Rogers#endif 199090546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe 199190546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe if (nativeCode == nullptr) { 199290546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe DCHECK(self->IsExceptionPending()); // There should be an exception pending now. 1993ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe 1994ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe // End JNI, as the assembly will move to deliver the exception. 19950cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier jobject lock = called->IsSynchronized() ? visitor.GetFirstHandleScopeJObject() : nullptr; 1996bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier if (shorty[0] == 'L') { 1997ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe artQuickGenericJniEndJNIRef(self, cookie, nullptr, lock); 1998ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe } else { 1999ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe artQuickGenericJniEndJNINonRef(self, cookie, lock); 2000ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe } 2001ad61517890168ff6ed19063cc8032a9c033d135bAndreas Gampe 2002c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return GetTwoWordFailureValue(); 200390546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe } 200490546836312adda54f28b700f25ff29ec8becdf8Andreas Gampe // Note that the native code pointer will be automatically set by artFindNativeMethod(). 2005bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe } 2006bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 2007c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe // Return native code addr(lo) and bottom of alloca address(hi). 2008c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(visitor.GetBottomOfUsedArea()), 2009c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe reinterpret_cast<uintptr_t>(nativeCode)); 2010bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe} 2011bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe 2012a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi// Defined in quick_jni_entrypoints.cc. 2013a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchiextern uint64_t GenericJniMethodEnd(Thread* self, uint32_t saved_local_ref_cookie, 2014a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi jvalue result, uint64_t result_f, ArtMethod* called, 2015a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi HandleScope* handle_scope); 2016bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe/* 2017eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier * Is called after the native JNI code. Responsible for cleanup (handle scope, saved state) and 2018bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe * unlocking. 2019bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe */ 2020a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchiextern "C" uint64_t artQuickGenericJniEndTrampoline(Thread* self, 2021a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi jvalue result, 2022a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi uint64_t result_f) { 2023a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi // We're here just back from a native call. We don't have the shared mutator lock at this point 2024a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi // yet until we call GoToRunnable() later in GenericJniMethodEnd(). Accessing objects or doing 2025a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi // anything that requires a mutator lock before that would cause problems as GC may have the 2026a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi // exclusive mutator lock and may be moving objects, etc. 2027e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod** sp = self->GetManagedStack()->GetTopQuickFrame(); 2028bf6b92a158053c98b15f4393abb3b86344ec9a20Andreas Gampe uint32_t* sp32 = reinterpret_cast<uint32_t*>(sp); 2029e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* called = *sp; 2030e0dcd46314d07eeb332edea292f5110178e4e3d2Ian Rogers uint32_t cookie = *(sp32 - 1); 2031a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi HandleScope* table = reinterpret_cast<HandleScope*>(reinterpret_cast<uint8_t*>(sp) + sizeof(*sp)); 2032a23b4680a8565f28e8aa958febf8949db74a3064Hiroshi Yamauchi return GenericJniMethodEnd(self, cookie, result, result_f, called, table); 20332da882315a61072664f7ce3c212307342e907207Andreas Gampe} 20342da882315a61072664f7ce3c212307342e907207Andreas Gampe 2035d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe// We use TwoWordReturn to optimize scalar returns. We use the hi value for code, and the lo value 2036d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe// for the method pointer. 203751f763506c7bb34420242e88e1631550f94d6417Andreas Gampe// 2038d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe// It is valid to use this, as at the usage points here (returns from C functions) we are assuming 203990443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier// to hold the mutator lock (see SHARED_REQUIRES(Locks::mutator_lock_) annotations). 204051f763506c7bb34420242e88e1631550f94d6417Andreas Gampe 20415f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartiertemplate<InvokeType type, bool access_check> 2042e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic TwoWordReturn artInvokeCommon(uint32_t method_idx, mirror::Object* this_object, Thread* self, 2043e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod** sp) { 20441d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers ScopedQuickEntrypointChecks sqec(self); 2045e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)); 2046e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp); 2047e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type); 20485f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier if (UNLIKELY(method == nullptr)) { 20495f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache()->GetDexFile(); 20505f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier uint32_t shorty_len; 2051c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx), &shorty_len); 20525f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier { 20535f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier // Remember the args in case a GC happens in FindMethodFromCode. 20545f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier ScopedObjectAccessUnchecked soa(self->GetJniEnv()); 20555f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier RememberForGcArgumentVisitor visitor(sp, type == kStatic, shorty, shorty_len, &soa); 20565f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier visitor.VisitArguments(); 20573a35714ebca10c989aa383c0861e2e84fe8dadf8Andreas Gampe method = FindMethodFromCode<type, access_check>(method_idx, &this_object, caller_method, 20580cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier self); 20595f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier visitor.FixupReferences(); 20605f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier } 20615f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 2062e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers if (UNLIKELY(method == nullptr)) { 20635f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier CHECK(self->IsExceptionPending()); 2064d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe return GetTwoWordFailureValue(); // Failure. 20655f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier } 20665f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier } 20675f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier DCHECK(!self->IsExceptionPending()); 20685f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier const void* code = method->GetEntryPointFromQuickCompiledCode(); 20695f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 20705f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier // When we return, the caller will branch to this address, so it had better not be 0! 2071e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers DCHECK(code != nullptr) << "Code was null in method: " << PrettyMethod(method) 2072c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe << " location: " 2073c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe << method->GetDexFile()->GetLocation(); 207451f763506c7bb34420242e88e1631550f94d6417Andreas Gampe 2075d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(code), 2076d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe reinterpret_cast<uintptr_t>(method)); 20775f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier} 20785f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 20798689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas Geoffray// Explicit artInvokeCommon template function declarations to please analysis tool. 20808689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas Geoffray#define EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(type, access_check) \ 208190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier template SHARED_REQUIRES(Locks::mutator_lock_) \ 2082e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier TwoWordReturn artInvokeCommon<type, access_check>( \ 2083e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp) 20848689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas Geoffray 20858689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kVirtual, false); 20868689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kVirtual, true); 20878689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kInterface, false); 20888689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kInterface, true); 20898689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kDirect, false); 20908689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kDirect, true); 20918689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kStatic, false); 20928689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kStatic, true); 20938689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kSuper, false); 20948689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas GeoffrayEXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kSuper, true); 20958689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas Geoffray#undef EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL 20968689a0a0f266dde073fe7b328c3ceeaa1b23276aNicolas Geoffray 20975f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier// See comments in runtime_support_asm.S 2098c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeextern "C" TwoWordReturn artInvokeInterfaceTrampolineWithAccessCheck( 2099e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp) 210090443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 21017ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray return artInvokeCommon<kInterface, true>(method_idx, this_object, self, sp); 21025f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier} 21035f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 2104c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeextern "C" TwoWordReturn artInvokeDirectTrampolineWithAccessCheck( 2105e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp) 210690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 21077ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray return artInvokeCommon<kDirect, true>(method_idx, this_object, self, sp); 21085f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier} 21095f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 2110c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeextern "C" TwoWordReturn artInvokeStaticTrampolineWithAccessCheck( 2111e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp) 211290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 21137ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray return artInvokeCommon<kStatic, true>(method_idx, this_object, self, sp); 21145f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier} 21155f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 2116c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeextern "C" TwoWordReturn artInvokeSuperTrampolineWithAccessCheck( 2117e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp) 211890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 21197ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray return artInvokeCommon<kSuper, true>(method_idx, this_object, self, sp); 21205f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier} 21215f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 2122c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampeextern "C" TwoWordReturn artInvokeVirtualTrampolineWithAccessCheck( 2123e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp) 212490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 21257ea6a170486d81b127e69673cd1020c4db628c93Nicolas Geoffray return artInvokeCommon<kVirtual, true>(method_idx, this_object, self, sp); 21265f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier} 21275f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 2128796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray// Determine target of interface dispatch. This object is known non-null. First argument 2129796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray// is there for consistency but should not be used, as some architectures overwrite it 2130796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray// in the assembly trampoline. 2131796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffrayextern "C" TwoWordReturn artInvokeInterfaceTrampoline(uint32_t deadbeef ATTRIBUTE_UNUSED, 213251f763506c7bb34420242e88e1631550f94d6417Andreas Gampe mirror::Object* this_object, 2133796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray Thread* self, 2134796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray ArtMethod** sp) 213590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 21361d8cdbc5202378a5f1a4b3a1fba610675ed4dcd5Ian Rogers ScopedQuickEntrypointChecks sqec(self); 2137796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray StackHandleScope<1> hs(self); 2138796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray Handle<mirror::Class> cls(hs.NewHandle(this_object->GetClass())); 2139796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray 2140d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray // The optimizing compiler currently does not inline methods that have an interface 2141d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray // invocation. We use the outer method directly to avoid fetching a stack map, which is 2142d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray // more expensive. 2143e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* caller_method = QuickArgumentVisitor::GetOuterMethod(sp); 2144d23eeef3492b53102eb8093524cf37e2b4c296dbNicolas Geoffray DCHECK_EQ(caller_method, QuickArgumentVisitor::GetCallingMethod(sp)); 2145796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray 2146796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray // Fetch the dex_method_idx of the target interface method from the caller. 2147796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp); 2148796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray 2149796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray const DexFile::CodeItem* code_item = caller_method->GetCodeItem(); 2150796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray CHECK_LT(dex_pc, code_item->insns_size_in_code_units_); 2151796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]); 2152796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray Instruction::Code instr_code = instr->Opcode(); 2153796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray CHECK(instr_code == Instruction::INVOKE_INTERFACE || 2154796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray instr_code == Instruction::INVOKE_INTERFACE_RANGE) 2155796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray << "Unexpected call into interface trampoline: " << instr->DumpString(nullptr); 2156796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray uint32_t dex_method_idx; 2157796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray if (instr_code == Instruction::INVOKE_INTERFACE) { 2158796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray dex_method_idx = instr->VRegB_35c(); 2159796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray } else { 2160796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray CHECK_EQ(instr_code, Instruction::INVOKE_INTERFACE_RANGE); 2161796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray dex_method_idx = instr->VRegB_3rc(); 2162796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray } 2163796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray 2164e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* interface_method = caller_method->GetDexCacheResolvedMethod( 2165e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier dex_method_idx, sizeof(void*)); 2166e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK(interface_method != nullptr) << dex_method_idx << " " << PrettyMethod(caller_method); 2167796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray ArtMethod* method = nullptr; 2168796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray 21695f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier if (LIKELY(interface_method->GetDexMethodIndex() != DexFile::kDexNoIndex)) { 2170796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray // If the dex cache already resolved the interface method, look whether we have 2171796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray // a match in the ImtConflictTable. 2172796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray uint32_t imt_index = interface_method->GetDexMethodIndex(); 2173796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray ArtMethod* conflict_method = cls->GetEmbeddedImTableEntry( 2174796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray imt_index % mirror::Class::kImtSize, sizeof(void*)); 21759fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light if (LIKELY(conflict_method->IsRuntimeMethod())) { 21769fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light ImtConflictTable* current_table = conflict_method->GetImtConflictTable(sizeof(void*)); 2177cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier DCHECK(current_table != nullptr); 2178cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier method = current_table->Lookup(interface_method, sizeof(void*)); 21799fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light } else { 21809fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light // It seems we aren't really a conflict method! 21819fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light method = cls->FindVirtualMethodForInterface(interface_method, sizeof(void*)); 21829fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light } 2183796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray if (method != nullptr) { 2184796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray return GetTwoWordSuccessValue( 2185796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode()), 2186796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray reinterpret_cast<uintptr_t>(method)); 2187796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray } 2188796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray 2189796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray // No match, use the IfTable. 2190796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray method = cls->FindVirtualMethodForInterface(interface_method, sizeof(void*)); 2191e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers if (UNLIKELY(method == nullptr)) { 2192e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch( 2193e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier interface_method, this_object, caller_method); 2194d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe return GetTwoWordFailureValue(); // Failure. 21955f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier } 21965f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier } else { 2197796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray // The dex cache did not resolve the method, look it up in the dex file 2198796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray // of the caller, 21994edd8476339fd93ba8ff384ad107f1fc662e64a3Mathieu Chartier DCHECK_EQ(interface_method, Runtime::Current()->GetResolutionMethod()); 2200c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache() 2201c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe ->GetDexFile(); 22025f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier uint32_t shorty_len; 2203c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(dex_method_idx), 2204c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe &shorty_len); 22055f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier { 22065f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier // Remember the args in case a GC happens in FindMethodFromCode. 22075f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier ScopedObjectAccessUnchecked soa(self->GetJniEnv()); 22085f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier RememberForGcArgumentVisitor visitor(sp, false, shorty, shorty_len, &soa); 22095f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier visitor.VisitArguments(); 22103a35714ebca10c989aa383c0861e2e84fe8dadf8Andreas Gampe method = FindMethodFromCode<kInterface, false>(dex_method_idx, &this_object, caller_method, 22115f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier self); 22125f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier visitor.FixupReferences(); 22135f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier } 22145f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 22155f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier if (UNLIKELY(method == nullptr)) { 22165f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier CHECK(self->IsExceptionPending()); 2217d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe return GetTwoWordFailureValue(); // Failure. 22185f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier } 2219796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray interface_method = caller_method->GetDexCacheResolvedMethod(dex_method_idx, sizeof(void*)); 2220796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray DCHECK(!interface_method->IsRuntimeMethod()); 2221796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray } 2222796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray 2223796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray // We arrive here if we have found an implementation, and it is not in the ImtConflictTable. 2224796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray // We create a new table with the new pair { interface_method, method }. 2225796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray uint32_t imt_index = interface_method->GetDexMethodIndex(); 2226796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray ArtMethod* conflict_method = cls->GetEmbeddedImTableEntry( 2227796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray imt_index % mirror::Class::kImtSize, sizeof(void*)); 22289fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light if (conflict_method->IsRuntimeMethod()) { 222949b5cede15d69930a8c156a3aea240164ca7af80Mathieu Chartier ArtMethod* new_conflict_method = Runtime::Current()->GetClassLinker()->AddMethodToConflictTable( 223049b5cede15d69930a8c156a3aea240164ca7af80Mathieu Chartier cls.Get(), 223149b5cede15d69930a8c156a3aea240164ca7af80Mathieu Chartier conflict_method, 223249b5cede15d69930a8c156a3aea240164ca7af80Mathieu Chartier interface_method, 223349b5cede15d69930a8c156a3aea240164ca7af80Mathieu Chartier method, 223449b5cede15d69930a8c156a3aea240164ca7af80Mathieu Chartier /*force_new_conflict_method*/false); 223549b5cede15d69930a8c156a3aea240164ca7af80Mathieu Chartier if (new_conflict_method != conflict_method) { 22369fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light // Update the IMT if we create a new conflict method. No fence needed here, as the 22379fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light // data is consistent. 22389fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light cls->SetEmbeddedImTableEntry(imt_index % mirror::Class::kImtSize, 22399fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light new_conflict_method, 22409fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light sizeof(void*)); 22419fc547ac3936fe88e9592f4a47afd7b134cb607cAlex Light } 22425f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier } 2243796d63050a18f263b93ea34951a61deaecab3422Nicolas Geoffray 22445f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier const void* code = method->GetEntryPointFromQuickCompiledCode(); 22455f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 22465f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier // When we return, the caller will branch to this address, so it had better not be 0! 2247e0a02dabedd7db2c511a513fb48d7e39ed3dd9c0Ian Rogers DCHECK(code != nullptr) << "Code was null in method: " << PrettyMethod(method) 2248c200a4abeca91e19969f5b35543f17f812ba32b9Andreas Gampe << " location: " << method->GetDexFile()->GetLocation(); 224951f763506c7bb34420242e88e1631550f94d6417Andreas Gampe 2250d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(code), 2251d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe reinterpret_cast<uintptr_t>(method)); 22525f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier} 22535f3ded46a1da26f6a51cad16d421ca2fdc0f23adMathieu Chartier 2254848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers} // namespace art 2255