xref: /aosp_15_r20/art/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
18*795d594fSAndroid Build Coastguard Worker #include "arch/context.h"
19*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
20*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
21*795d594fSAndroid Build Coastguard Worker #include "art_method.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/callee_save_type.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/globals.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
25*795d594fSAndroid Build Coastguard Worker #include "callee_save_frame.h"
26*795d594fSAndroid Build Coastguard Worker #include "common_throws.h"
27*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "debug_print.h"
29*795d594fSAndroid Build Coastguard Worker #include "debugger.h"
30*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
32*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction-inl.h"
33*795d594fSAndroid Build Coastguard Worker #include "dex/method_reference.h"
34*795d594fSAndroid Build Coastguard Worker #include "entrypoints/entrypoint_utils-inl.h"
35*795d594fSAndroid Build Coastguard Worker #include "entrypoints/quick/callee_save_frame.h"
36*795d594fSAndroid Build Coastguard Worker #include "entrypoints/runtime_asm_entrypoints.h"
37*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/card_table-inl.h"
38*795d594fSAndroid Build Coastguard Worker #include "imt_conflict_table.h"
39*795d594fSAndroid Build Coastguard Worker #include "imtable-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "instrumentation.h"
41*795d594fSAndroid Build Coastguard Worker #include "interpreter/interpreter.h"
42*795d594fSAndroid Build Coastguard Worker #include "interpreter/interpreter_common.h"
43*795d594fSAndroid Build Coastguard Worker #include "interpreter/shadow_frame-inl.h"
44*795d594fSAndroid Build Coastguard Worker #include "jit/jit.h"
45*795d594fSAndroid Build Coastguard Worker #include "jit/jit_code_cache.h"
46*795d594fSAndroid Build Coastguard Worker #include "linear_alloc.h"
47*795d594fSAndroid Build Coastguard Worker #include "method_handles.h"
48*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
49*795d594fSAndroid Build Coastguard Worker #include "mirror/dex_cache-inl.h"
50*795d594fSAndroid Build Coastguard Worker #include "mirror/method.h"
51*795d594fSAndroid Build Coastguard Worker #include "mirror/method_handle_impl.h"
52*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
53*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
54*795d594fSAndroid Build Coastguard Worker #include "mirror/var_handle.h"
55*795d594fSAndroid Build Coastguard Worker #include "oat/oat.h"
56*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file.h"
57*795d594fSAndroid Build Coastguard Worker #include "oat/oat_quick_method_header.h"
58*795d594fSAndroid Build Coastguard Worker #include "quick_exception_handler.h"
59*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
60*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
61*795d594fSAndroid Build Coastguard Worker #include "stack.h"
62*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
63*795d594fSAndroid Build Coastguard Worker #include "var_handles.h"
64*795d594fSAndroid Build Coastguard Worker #include "well_known_classes.h"
65*795d594fSAndroid Build Coastguard Worker #include "runtime_entrypoints_list.h"
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
68*795d594fSAndroid Build Coastguard Worker 
69*795d594fSAndroid Build Coastguard Worker // Visits the arguments as saved to the stack by a CalleeSaveType::kRefAndArgs callee save frame.
70*795d594fSAndroid Build Coastguard Worker template <typename FrameInfo>
71*795d594fSAndroid Build Coastguard Worker class QuickArgumentVisitorImpl {
72*795d594fSAndroid Build Coastguard Worker   // Number of bytes for each out register in the caller method's frame.
73*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kBytesStackArgLocation = 4;
74*795d594fSAndroid Build Coastguard Worker   // Frame size in bytes of a callee-save frame for RefsAndArgs.
75*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_FrameSize =
76*795d594fSAndroid Build Coastguard Worker       RuntimeCalleeSaveFrame::GetFrameSize(CalleeSaveType::kSaveRefsAndArgs);
77*795d594fSAndroid Build Coastguard Worker   // Offset of first GPR arg.
78*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset =
79*795d594fSAndroid Build Coastguard Worker       RuntimeCalleeSaveFrame::GetGpr1Offset(CalleeSaveType::kSaveRefsAndArgs);
80*795d594fSAndroid Build Coastguard Worker   // Offset of first FPR arg.
81*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset =
82*795d594fSAndroid Build Coastguard Worker       RuntimeCalleeSaveFrame::GetFpr1Offset(CalleeSaveType::kSaveRefsAndArgs);
83*795d594fSAndroid Build Coastguard Worker   // Offset of return address.
84*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_ReturnPcOffset =
85*795d594fSAndroid Build Coastguard Worker       RuntimeCalleeSaveFrame::GetReturnPcOffset(CalleeSaveType::kSaveRefsAndArgs);
86*795d594fSAndroid Build Coastguard Worker 
GprIndexToGprOffset(uint32_t gpr_index)87*795d594fSAndroid Build Coastguard Worker   static size_t GprIndexToGprOffset(uint32_t gpr_index) {
88*795d594fSAndroid Build Coastguard Worker     return FrameInfo::GprIndexToGprOffsetImpl(gpr_index);
89*795d594fSAndroid Build Coastguard Worker   }
90*795d594fSAndroid Build Coastguard Worker 
91*795d594fSAndroid Build Coastguard Worker   static constexpr bool kSplitPairAcrossRegisterAndStack =
92*795d594fSAndroid Build Coastguard Worker       FrameInfo::kSplitPairAcrossRegisterAndStack;
93*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignPairRegister = FrameInfo::kAlignPairRegister;
94*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSoftFloatAbi = FrameInfo::kQuickSoftFloatAbi;
95*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickDoubleRegAlignedFloatBackFilled =
96*795d594fSAndroid Build Coastguard Worker       FrameInfo::kQuickDoubleRegAlignedFloatBackFilled;
97*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSkipOddFpRegisters = FrameInfo::kQuickSkipOddFpRegisters;
98*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickGprArgs = FrameInfo::kNumQuickGprArgs;
99*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickFprArgs = FrameInfo::kNumQuickFprArgs;
100*795d594fSAndroid Build Coastguard Worker   static constexpr bool kGprFprLockstep = FrameInfo::kGprFprLockstep;
101*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNaNBoxing = FrameInfo::kNanBoxing;
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker  public:
NaNBoxing()104*795d594fSAndroid Build Coastguard Worker   static constexpr bool NaNBoxing() { return FrameInfo::kNaNBoxing; }
105*795d594fSAndroid Build Coastguard Worker 
GetThisObjectReference(ArtMethod ** sp)106*795d594fSAndroid Build Coastguard Worker   static StackReference<mirror::Object>* GetThisObjectReference(ArtMethod** sp)
107*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
108*795d594fSAndroid Build Coastguard Worker     CHECK_GT(kNumQuickGprArgs, 0u);
109*795d594fSAndroid Build Coastguard Worker     constexpr uint32_t kThisGprIndex = 0u;  // 'this' is in the 1st GPR.
110*795d594fSAndroid Build Coastguard Worker     size_t this_arg_offset = kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset +
111*795d594fSAndroid Build Coastguard Worker         GprIndexToGprOffset(kThisGprIndex);
112*795d594fSAndroid Build Coastguard Worker     uint8_t* this_arg_address = reinterpret_cast<uint8_t*>(sp) + this_arg_offset;
113*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<StackReference<mirror::Object>*>(this_arg_address);
114*795d594fSAndroid Build Coastguard Worker   }
115*795d594fSAndroid Build Coastguard Worker 
GetCallingMethodAndDexPc(ArtMethod ** sp,uint32_t * dex_pc)116*795d594fSAndroid Build Coastguard Worker   static ArtMethod* GetCallingMethodAndDexPc(ArtMethod** sp, uint32_t* dex_pc)
117*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
118*795d594fSAndroid Build Coastguard Worker     DCHECK((*sp)->IsCalleeSaveMethod());
119*795d594fSAndroid Build Coastguard Worker     return GetCalleeSaveMethodCallerAndDexPc(sp, CalleeSaveType::kSaveRefsAndArgs, dex_pc);
120*795d594fSAndroid Build Coastguard Worker   }
121*795d594fSAndroid Build Coastguard Worker 
GetCallingMethod(ArtMethod ** sp)122*795d594fSAndroid Build Coastguard Worker   static ArtMethod* GetCallingMethod(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) {
123*795d594fSAndroid Build Coastguard Worker     uint32_t dex_pc;
124*795d594fSAndroid Build Coastguard Worker     return GetCallingMethodAndDexPc(sp, &dex_pc);
125*795d594fSAndroid Build Coastguard Worker   }
126*795d594fSAndroid Build Coastguard Worker 
GetOuterMethod(ArtMethod ** sp)127*795d594fSAndroid Build Coastguard Worker   static ArtMethod* GetOuterMethod(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) {
128*795d594fSAndroid Build Coastguard Worker     DCHECK((*sp)->IsCalleeSaveMethod());
129*795d594fSAndroid Build Coastguard Worker     uint8_t* previous_sp =
130*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize;
131*795d594fSAndroid Build Coastguard Worker     return *reinterpret_cast<ArtMethod**>(previous_sp);
132*795d594fSAndroid Build Coastguard Worker   }
133*795d594fSAndroid Build Coastguard Worker 
GetCallingPcAddr(ArtMethod ** sp)134*795d594fSAndroid Build Coastguard Worker   static uint8_t* GetCallingPcAddr(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) {
135*795d594fSAndroid Build Coastguard Worker     DCHECK((*sp)->IsCalleeSaveMethod());
136*795d594fSAndroid Build Coastguard Worker     uint8_t* return_adress_spill =
137*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_ReturnPcOffset;
138*795d594fSAndroid Build Coastguard Worker     return return_adress_spill;
139*795d594fSAndroid Build Coastguard Worker   }
140*795d594fSAndroid Build Coastguard Worker 
141*795d594fSAndroid Build Coastguard Worker   // For the given quick ref and args quick frame, return the caller's PC.
GetCallingPc(ArtMethod ** sp)142*795d594fSAndroid Build Coastguard Worker   static uintptr_t GetCallingPc(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) {
143*795d594fSAndroid Build Coastguard Worker     return *reinterpret_cast<uintptr_t*>(GetCallingPcAddr(sp));
144*795d594fSAndroid Build Coastguard Worker   }
145*795d594fSAndroid Build Coastguard Worker 
QuickArgumentVisitorImpl(ArtMethod ** sp,bool is_static,std::string_view shorty)146*795d594fSAndroid Build Coastguard Worker   QuickArgumentVisitorImpl(ArtMethod** sp, bool is_static, std::string_view shorty)
147*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_)
148*795d594fSAndroid Build Coastguard Worker       : is_static_(is_static),
149*795d594fSAndroid Build Coastguard Worker         shorty_(shorty),
150*795d594fSAndroid Build Coastguard Worker         gpr_args_(reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset),
151*795d594fSAndroid Build Coastguard Worker         fpr_args_(reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset),
152*795d594fSAndroid Build Coastguard Worker         stack_args_(reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize +
153*795d594fSAndroid Build Coastguard Worker             sizeof(ArtMethod*)),  // Skip ArtMethod*.
154*795d594fSAndroid Build Coastguard Worker         gpr_index_(0),
155*795d594fSAndroid Build Coastguard Worker         fpr_index_(0),
156*795d594fSAndroid Build Coastguard Worker         fpr_double_index_(0),
157*795d594fSAndroid Build Coastguard Worker         stack_index_(0),
158*795d594fSAndroid Build Coastguard Worker         cur_type_(Primitive::kPrimVoid),
159*795d594fSAndroid Build Coastguard Worker         is_split_long_or_double_(false) {
160*795d594fSAndroid Build Coastguard Worker     static_assert(kQuickSoftFloatAbi == (kNumQuickFprArgs == 0),
161*795d594fSAndroid Build Coastguard Worker                   "Number of Quick FPR arguments unexpected");
162*795d594fSAndroid Build Coastguard Worker     static_assert(!(kQuickSoftFloatAbi && kQuickDoubleRegAlignedFloatBackFilled),
163*795d594fSAndroid Build Coastguard Worker                   "Double alignment unexpected");
164*795d594fSAndroid Build Coastguard Worker     // For register alignment, we want to assume that counters(fpr_double_index_) are even if the
165*795d594fSAndroid Build Coastguard Worker     // next register is even.
166*795d594fSAndroid Build Coastguard Worker     static_assert(!kQuickDoubleRegAlignedFloatBackFilled || kNumQuickFprArgs % 2 == 0,
167*795d594fSAndroid Build Coastguard Worker                   "Number of Quick FPR arguments not even");
168*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
169*795d594fSAndroid Build Coastguard Worker   }
170*795d594fSAndroid Build Coastguard Worker 
~QuickArgumentVisitorImpl()171*795d594fSAndroid Build Coastguard Worker   virtual ~QuickArgumentVisitorImpl() {}
172*795d594fSAndroid Build Coastguard Worker 
173*795d594fSAndroid Build Coastguard Worker   virtual void Visit() = 0;
174*795d594fSAndroid Build Coastguard Worker 
GetParamPrimitiveType() const175*795d594fSAndroid Build Coastguard Worker   Primitive::Type GetParamPrimitiveType() const {
176*795d594fSAndroid Build Coastguard Worker     return cur_type_;
177*795d594fSAndroid Build Coastguard Worker   }
178*795d594fSAndroid Build Coastguard Worker 
GetParamAddress() const179*795d594fSAndroid Build Coastguard Worker   uint8_t* GetParamAddress() const {
180*795d594fSAndroid Build Coastguard Worker     if (!kQuickSoftFloatAbi) {
181*795d594fSAndroid Build Coastguard Worker       Primitive::Type type = GetParamPrimitiveType();
182*795d594fSAndroid Build Coastguard Worker       if (UNLIKELY((type == Primitive::kPrimDouble) || (type == Primitive::kPrimFloat))) {
183*795d594fSAndroid Build Coastguard Worker         if (type == Primitive::kPrimDouble && kQuickDoubleRegAlignedFloatBackFilled) {
184*795d594fSAndroid Build Coastguard Worker           if (fpr_double_index_ + 2 < kNumQuickFprArgs + 1) {
185*795d594fSAndroid Build Coastguard Worker             return fpr_args_ +
186*795d594fSAndroid Build Coastguard Worker                    (fpr_double_index_ * GetBytesPerFprSpillLocation(kRuntimeQuickCodeISA));
187*795d594fSAndroid Build Coastguard Worker           }
188*795d594fSAndroid Build Coastguard Worker         } else if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
189*795d594fSAndroid Build Coastguard Worker           return fpr_args_ + (fpr_index_ * GetBytesPerFprSpillLocation(kRuntimeQuickCodeISA));
190*795d594fSAndroid Build Coastguard Worker         }
191*795d594fSAndroid Build Coastguard Worker         return stack_args_ + (stack_index_ * kBytesStackArgLocation);
192*795d594fSAndroid Build Coastguard Worker       }
193*795d594fSAndroid Build Coastguard Worker     }
194*795d594fSAndroid Build Coastguard Worker     if (gpr_index_ < kNumQuickGprArgs) {
195*795d594fSAndroid Build Coastguard Worker       return gpr_args_ + GprIndexToGprOffset(gpr_index_);
196*795d594fSAndroid Build Coastguard Worker     }
197*795d594fSAndroid Build Coastguard Worker     return stack_args_ + (stack_index_ * kBytesStackArgLocation);
198*795d594fSAndroid Build Coastguard Worker   }
199*795d594fSAndroid Build Coastguard Worker 
IsSplitLongOrDouble() const200*795d594fSAndroid Build Coastguard Worker   bool IsSplitLongOrDouble() const {
201*795d594fSAndroid Build Coastguard Worker     if ((GetBytesPerGprSpillLocation(kRuntimeQuickCodeISA) == 4) ||
202*795d594fSAndroid Build Coastguard Worker         (GetBytesPerFprSpillLocation(kRuntimeQuickCodeISA) == 4)) {
203*795d594fSAndroid Build Coastguard Worker       return is_split_long_or_double_;
204*795d594fSAndroid Build Coastguard Worker     } else {
205*795d594fSAndroid Build Coastguard Worker       return false;  // An optimization for when GPR and FPRs are 64bit.
206*795d594fSAndroid Build Coastguard Worker     }
207*795d594fSAndroid Build Coastguard Worker   }
208*795d594fSAndroid Build Coastguard Worker 
IsParamAReference() const209*795d594fSAndroid Build Coastguard Worker   bool IsParamAReference() const {
210*795d594fSAndroid Build Coastguard Worker     return GetParamPrimitiveType() == Primitive::kPrimNot;
211*795d594fSAndroid Build Coastguard Worker   }
212*795d594fSAndroid Build Coastguard Worker 
IsParamALongOrDouble() const213*795d594fSAndroid Build Coastguard Worker   bool IsParamALongOrDouble() const {
214*795d594fSAndroid Build Coastguard Worker     Primitive::Type type = GetParamPrimitiveType();
215*795d594fSAndroid Build Coastguard Worker     return type == Primitive::kPrimLong || type == Primitive::kPrimDouble;
216*795d594fSAndroid Build Coastguard Worker   }
217*795d594fSAndroid Build Coastguard Worker 
ReadSplitLongParam() const218*795d594fSAndroid Build Coastguard Worker   uint64_t ReadSplitLongParam() const {
219*795d594fSAndroid Build Coastguard Worker     // The splitted long is always available through the stack.
220*795d594fSAndroid Build Coastguard Worker     return *reinterpret_cast<uint64_t*>(stack_args_
221*795d594fSAndroid Build Coastguard Worker         + stack_index_ * kBytesStackArgLocation);
222*795d594fSAndroid Build Coastguard Worker   }
223*795d594fSAndroid Build Coastguard Worker 
IncGprIndex()224*795d594fSAndroid Build Coastguard Worker   void IncGprIndex() {
225*795d594fSAndroid Build Coastguard Worker     gpr_index_++;
226*795d594fSAndroid Build Coastguard Worker     if (kGprFprLockstep) {
227*795d594fSAndroid Build Coastguard Worker       fpr_index_++;
228*795d594fSAndroid Build Coastguard Worker     }
229*795d594fSAndroid Build Coastguard Worker   }
230*795d594fSAndroid Build Coastguard Worker 
IncFprIndex()231*795d594fSAndroid Build Coastguard Worker   void IncFprIndex() {
232*795d594fSAndroid Build Coastguard Worker     fpr_index_++;
233*795d594fSAndroid Build Coastguard Worker     if (kGprFprLockstep) {
234*795d594fSAndroid Build Coastguard Worker       gpr_index_++;
235*795d594fSAndroid Build Coastguard Worker     }
236*795d594fSAndroid Build Coastguard Worker   }
237*795d594fSAndroid Build Coastguard Worker 
VisitArguments()238*795d594fSAndroid Build Coastguard Worker   void VisitArguments() REQUIRES_SHARED(Locks::mutator_lock_) {
239*795d594fSAndroid Build Coastguard Worker     // (a) 'stack_args_' should point to the first method's argument
240*795d594fSAndroid Build Coastguard Worker     // (b) whatever the argument type it is, the 'stack_index_' should
241*795d594fSAndroid Build Coastguard Worker     //     be moved forward along with every visiting.
242*795d594fSAndroid Build Coastguard Worker     gpr_index_ = 0;
243*795d594fSAndroid Build Coastguard Worker     fpr_index_ = 0;
244*795d594fSAndroid Build Coastguard Worker     if (kQuickDoubleRegAlignedFloatBackFilled) {
245*795d594fSAndroid Build Coastguard Worker       fpr_double_index_ = 0;
246*795d594fSAndroid Build Coastguard Worker     }
247*795d594fSAndroid Build Coastguard Worker     stack_index_ = 0;
248*795d594fSAndroid Build Coastguard Worker     if (!is_static_) {  // Handle this.
249*795d594fSAndroid Build Coastguard Worker       cur_type_ = Primitive::kPrimNot;
250*795d594fSAndroid Build Coastguard Worker       is_split_long_or_double_ = false;
251*795d594fSAndroid Build Coastguard Worker       Visit();
252*795d594fSAndroid Build Coastguard Worker       stack_index_++;
253*795d594fSAndroid Build Coastguard Worker       if (kNumQuickGprArgs > 0) {
254*795d594fSAndroid Build Coastguard Worker         IncGprIndex();
255*795d594fSAndroid Build Coastguard Worker       }
256*795d594fSAndroid Build Coastguard Worker     }
257*795d594fSAndroid Build Coastguard Worker     for (char c : shorty_.substr(1u)) {
258*795d594fSAndroid Build Coastguard Worker       cur_type_ = Primitive::GetType(c);
259*795d594fSAndroid Build Coastguard Worker       switch (cur_type_) {
260*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimNot:
261*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
262*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
263*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
264*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
265*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
266*795d594fSAndroid Build Coastguard Worker           is_split_long_or_double_ = false;
267*795d594fSAndroid Build Coastguard Worker           Visit();
268*795d594fSAndroid Build Coastguard Worker           stack_index_++;
269*795d594fSAndroid Build Coastguard Worker           if (gpr_index_ < kNumQuickGprArgs) {
270*795d594fSAndroid Build Coastguard Worker             IncGprIndex();
271*795d594fSAndroid Build Coastguard Worker           }
272*795d594fSAndroid Build Coastguard Worker           break;
273*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
274*795d594fSAndroid Build Coastguard Worker           is_split_long_or_double_ = false;
275*795d594fSAndroid Build Coastguard Worker           Visit();
276*795d594fSAndroid Build Coastguard Worker           stack_index_++;
277*795d594fSAndroid Build Coastguard Worker           if (kQuickSoftFloatAbi) {
278*795d594fSAndroid Build Coastguard Worker             if (gpr_index_ < kNumQuickGprArgs) {
279*795d594fSAndroid Build Coastguard Worker               IncGprIndex();
280*795d594fSAndroid Build Coastguard Worker             }
281*795d594fSAndroid Build Coastguard Worker           } else {
282*795d594fSAndroid Build Coastguard Worker             if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
283*795d594fSAndroid Build Coastguard Worker               IncFprIndex();
284*795d594fSAndroid Build Coastguard Worker               if (kQuickDoubleRegAlignedFloatBackFilled) {
285*795d594fSAndroid Build Coastguard Worker                 // Double should not overlap with float.
286*795d594fSAndroid Build Coastguard Worker                 // For example, if fpr_index_ = 3, fpr_double_index_ should be at least 4.
287*795d594fSAndroid Build Coastguard Worker                 fpr_double_index_ = std::max(fpr_double_index_, RoundUp(fpr_index_, 2));
288*795d594fSAndroid Build Coastguard Worker                 // Float should not overlap with double.
289*795d594fSAndroid Build Coastguard Worker                 if (fpr_index_ % 2 == 0) {
290*795d594fSAndroid Build Coastguard Worker                   fpr_index_ = std::max(fpr_double_index_, fpr_index_);
291*795d594fSAndroid Build Coastguard Worker                 }
292*795d594fSAndroid Build Coastguard Worker               } else if (kQuickSkipOddFpRegisters) {
293*795d594fSAndroid Build Coastguard Worker                 IncFprIndex();
294*795d594fSAndroid Build Coastguard Worker               }
295*795d594fSAndroid Build Coastguard Worker             }
296*795d594fSAndroid Build Coastguard Worker           }
297*795d594fSAndroid Build Coastguard Worker           break;
298*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
299*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
300*795d594fSAndroid Build Coastguard Worker           if (kQuickSoftFloatAbi || (cur_type_ == Primitive::kPrimLong)) {
301*795d594fSAndroid Build Coastguard Worker             if (cur_type_ == Primitive::kPrimLong &&
302*795d594fSAndroid Build Coastguard Worker                 gpr_index_ == 0 &&
303*795d594fSAndroid Build Coastguard Worker                 kAlignPairRegister) {
304*795d594fSAndroid Build Coastguard Worker               // Currently, this is only for ARM, where we align long parameters with
305*795d594fSAndroid Build Coastguard Worker               // even-numbered registers by skipping R1 and using R2 instead.
306*795d594fSAndroid Build Coastguard Worker               IncGprIndex();
307*795d594fSAndroid Build Coastguard Worker             }
308*795d594fSAndroid Build Coastguard Worker             is_split_long_or_double_ = (GetBytesPerGprSpillLocation(kRuntimeQuickCodeISA) == 4) &&
309*795d594fSAndroid Build Coastguard Worker                 ((gpr_index_ + 1) == kNumQuickGprArgs);
310*795d594fSAndroid Build Coastguard Worker             if (!kSplitPairAcrossRegisterAndStack && is_split_long_or_double_) {
311*795d594fSAndroid Build Coastguard Worker               // We don't want to split this. Pass over this register.
312*795d594fSAndroid Build Coastguard Worker               gpr_index_++;
313*795d594fSAndroid Build Coastguard Worker               is_split_long_or_double_ = false;
314*795d594fSAndroid Build Coastguard Worker             }
315*795d594fSAndroid Build Coastguard Worker             Visit();
316*795d594fSAndroid Build Coastguard Worker             if (kBytesStackArgLocation == 4) {
317*795d594fSAndroid Build Coastguard Worker               stack_index_+= 2;
318*795d594fSAndroid Build Coastguard Worker             } else {
319*795d594fSAndroid Build Coastguard Worker               CHECK_EQ(kBytesStackArgLocation, 8U);
320*795d594fSAndroid Build Coastguard Worker               stack_index_++;
321*795d594fSAndroid Build Coastguard Worker             }
322*795d594fSAndroid Build Coastguard Worker             if (gpr_index_ < kNumQuickGprArgs) {
323*795d594fSAndroid Build Coastguard Worker               IncGprIndex();
324*795d594fSAndroid Build Coastguard Worker               if (GetBytesPerGprSpillLocation(kRuntimeQuickCodeISA) == 4) {
325*795d594fSAndroid Build Coastguard Worker                 if (gpr_index_ < kNumQuickGprArgs) {
326*795d594fSAndroid Build Coastguard Worker                   IncGprIndex();
327*795d594fSAndroid Build Coastguard Worker                 }
328*795d594fSAndroid Build Coastguard Worker               }
329*795d594fSAndroid Build Coastguard Worker             }
330*795d594fSAndroid Build Coastguard Worker           } else {
331*795d594fSAndroid Build Coastguard Worker             is_split_long_or_double_ = (GetBytesPerFprSpillLocation(kRuntimeQuickCodeISA) == 4) &&
332*795d594fSAndroid Build Coastguard Worker                 ((fpr_index_ + 1) == kNumQuickFprArgs) && !kQuickDoubleRegAlignedFloatBackFilled;
333*795d594fSAndroid Build Coastguard Worker             Visit();
334*795d594fSAndroid Build Coastguard Worker             if (kBytesStackArgLocation == 4) {
335*795d594fSAndroid Build Coastguard Worker               stack_index_+= 2;
336*795d594fSAndroid Build Coastguard Worker             } else {
337*795d594fSAndroid Build Coastguard Worker               CHECK_EQ(kBytesStackArgLocation, 8U);
338*795d594fSAndroid Build Coastguard Worker               stack_index_++;
339*795d594fSAndroid Build Coastguard Worker             }
340*795d594fSAndroid Build Coastguard Worker             if (kQuickDoubleRegAlignedFloatBackFilled) {
341*795d594fSAndroid Build Coastguard Worker               if (fpr_double_index_ + 2 < kNumQuickFprArgs + 1) {
342*795d594fSAndroid Build Coastguard Worker                 fpr_double_index_ += 2;
343*795d594fSAndroid Build Coastguard Worker                 // Float should not overlap with double.
344*795d594fSAndroid Build Coastguard Worker                 if (fpr_index_ % 2 == 0) {
345*795d594fSAndroid Build Coastguard Worker                   fpr_index_ = std::max(fpr_double_index_, fpr_index_);
346*795d594fSAndroid Build Coastguard Worker                 }
347*795d594fSAndroid Build Coastguard Worker               }
348*795d594fSAndroid Build Coastguard Worker             } else if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
349*795d594fSAndroid Build Coastguard Worker               IncFprIndex();
350*795d594fSAndroid Build Coastguard Worker               if (GetBytesPerFprSpillLocation(kRuntimeQuickCodeISA) == 4) {
351*795d594fSAndroid Build Coastguard Worker                 if (fpr_index_ + 1 < kNumQuickFprArgs + 1) {
352*795d594fSAndroid Build Coastguard Worker                   IncFprIndex();
353*795d594fSAndroid Build Coastguard Worker                 }
354*795d594fSAndroid Build Coastguard Worker               }
355*795d594fSAndroid Build Coastguard Worker             }
356*795d594fSAndroid Build Coastguard Worker           }
357*795d594fSAndroid Build Coastguard Worker           break;
358*795d594fSAndroid Build Coastguard Worker         default:
359*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected type: " << cur_type_ << " in " << shorty_;
360*795d594fSAndroid Build Coastguard Worker       }
361*795d594fSAndroid Build Coastguard Worker     }
362*795d594fSAndroid Build Coastguard Worker   }
363*795d594fSAndroid Build Coastguard Worker 
364*795d594fSAndroid Build Coastguard Worker  protected:
365*795d594fSAndroid Build Coastguard Worker   const bool is_static_;
366*795d594fSAndroid Build Coastguard Worker   const std::string_view shorty_;
367*795d594fSAndroid Build Coastguard Worker 
368*795d594fSAndroid Build Coastguard Worker  private:
369*795d594fSAndroid Build Coastguard Worker   uint8_t* const gpr_args_;  // Address of GPR arguments in callee save frame.
370*795d594fSAndroid Build Coastguard Worker   uint8_t* const fpr_args_;  // Address of FPR arguments in callee save frame.
371*795d594fSAndroid Build Coastguard Worker   uint8_t* const stack_args_;  // Address of stack arguments in caller's frame.
372*795d594fSAndroid Build Coastguard Worker   uint32_t gpr_index_;  // Index into spilled GPRs.
373*795d594fSAndroid Build Coastguard Worker   // Index into spilled FPRs.
374*795d594fSAndroid Build Coastguard Worker   // In case kQuickDoubleRegAlignedFloatBackFilled, it may index a hole while fpr_double_index_
375*795d594fSAndroid Build Coastguard Worker   // holds a higher register number.
376*795d594fSAndroid Build Coastguard Worker   uint32_t fpr_index_;
377*795d594fSAndroid Build Coastguard Worker   // Index into spilled FPRs for aligned double.
378*795d594fSAndroid Build Coastguard Worker   // Only used when kQuickDoubleRegAlignedFloatBackFilled. Next available double register indexed in
379*795d594fSAndroid Build Coastguard Worker   // terms of singles, may be behind fpr_index.
380*795d594fSAndroid Build Coastguard Worker   uint32_t fpr_double_index_;
381*795d594fSAndroid Build Coastguard Worker   uint32_t stack_index_;  // Index into arguments on the stack.
382*795d594fSAndroid Build Coastguard Worker   // The current type of argument during VisitArguments.
383*795d594fSAndroid Build Coastguard Worker   Primitive::Type cur_type_;
384*795d594fSAndroid Build Coastguard Worker   // Does a 64bit parameter straddle the register and stack arguments?
385*795d594fSAndroid Build Coastguard Worker   bool is_split_long_or_double_;
386*795d594fSAndroid Build Coastguard Worker };
387*795d594fSAndroid Build Coastguard Worker 
388*795d594fSAndroid Build Coastguard Worker class QuickArgumentFrameInfoARM {
389*795d594fSAndroid Build Coastguard Worker  public:
390*795d594fSAndroid Build Coastguard Worker   // The callee save frame is pointed to by SP.
391*795d594fSAndroid Build Coastguard Worker   // | argN       |  |
392*795d594fSAndroid Build Coastguard Worker   // | ...        |  |
393*795d594fSAndroid Build Coastguard Worker   // | arg4       |  |
394*795d594fSAndroid Build Coastguard Worker   // | arg3 spill |  |  Caller's frame
395*795d594fSAndroid Build Coastguard Worker   // | arg2 spill |  |
396*795d594fSAndroid Build Coastguard Worker   // | arg1 spill |  |
397*795d594fSAndroid Build Coastguard Worker   // | Method*    | ---
398*795d594fSAndroid Build Coastguard Worker   // | LR         |
399*795d594fSAndroid Build Coastguard Worker   // | ...        |    4x6 bytes callee saves
400*795d594fSAndroid Build Coastguard Worker   // | R3         |
401*795d594fSAndroid Build Coastguard Worker   // | R2         |
402*795d594fSAndroid Build Coastguard Worker   // | R1         |
403*795d594fSAndroid Build Coastguard Worker   // | S15        |
404*795d594fSAndroid Build Coastguard Worker   // | :          |
405*795d594fSAndroid Build Coastguard Worker   // | S0         |
406*795d594fSAndroid Build Coastguard Worker   // |            |    4x2 bytes padding
407*795d594fSAndroid Build Coastguard Worker   // | Method*    |  <- sp
408*795d594fSAndroid Build Coastguard Worker   static constexpr bool kSplitPairAcrossRegisterAndStack = false;
409*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignPairRegister = true;
410*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSoftFloatAbi = false;
411*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = true;
412*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSkipOddFpRegisters = false;
413*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickGprArgs = 3;
414*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickFprArgs = 16;
415*795d594fSAndroid Build Coastguard Worker   static constexpr bool kGprFprLockstep = false;
416*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNaNBoxing = false;
GprIndexToGprOffsetImpl(uint32_t gpr_index)417*795d594fSAndroid Build Coastguard Worker   static size_t GprIndexToGprOffsetImpl(uint32_t gpr_index) {
418*795d594fSAndroid Build Coastguard Worker     return gpr_index * GetBytesPerGprSpillLocation(InstructionSet::kArm);
419*795d594fSAndroid Build Coastguard Worker   }
420*795d594fSAndroid Build Coastguard Worker };
421*795d594fSAndroid Build Coastguard Worker 
422*795d594fSAndroid Build Coastguard Worker class QuickArgumentFrameInfoARM64 {
423*795d594fSAndroid Build Coastguard Worker  public:
424*795d594fSAndroid Build Coastguard Worker   // The callee save frame is pointed to by SP.
425*795d594fSAndroid Build Coastguard Worker   // | argN       |  |
426*795d594fSAndroid Build Coastguard Worker   // | ...        |  |
427*795d594fSAndroid Build Coastguard Worker   // | arg4       |  |
428*795d594fSAndroid Build Coastguard Worker   // | arg3 spill |  |  Caller's frame
429*795d594fSAndroid Build Coastguard Worker   // | arg2 spill |  |
430*795d594fSAndroid Build Coastguard Worker   // | arg1 spill |  |
431*795d594fSAndroid Build Coastguard Worker   // | Method*    | ---
432*795d594fSAndroid Build Coastguard Worker   // | LR         |
433*795d594fSAndroid Build Coastguard Worker   // | X29        |
434*795d594fSAndroid Build Coastguard Worker   // |  :         |
435*795d594fSAndroid Build Coastguard Worker   // | X20        |
436*795d594fSAndroid Build Coastguard Worker   // | X7         |
437*795d594fSAndroid Build Coastguard Worker   // | :          |
438*795d594fSAndroid Build Coastguard Worker   // | X1         |
439*795d594fSAndroid Build Coastguard Worker   // | D7         |
440*795d594fSAndroid Build Coastguard Worker   // |  :         |
441*795d594fSAndroid Build Coastguard Worker   // | D0         |
442*795d594fSAndroid Build Coastguard Worker   // |            |    padding
443*795d594fSAndroid Build Coastguard Worker   // | Method*    |  <- sp
444*795d594fSAndroid Build Coastguard Worker   static constexpr bool kSplitPairAcrossRegisterAndStack = false;
445*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignPairRegister = false;
446*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSoftFloatAbi = false;  // This is a hard float ABI.
447*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
448*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSkipOddFpRegisters = false;
449*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickGprArgs = 7;  // 7 arguments passed in GPRs.
450*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickFprArgs = 8;  // 8 arguments passed in FPRs.
451*795d594fSAndroid Build Coastguard Worker   static constexpr bool kGprFprLockstep = false;
452*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNaNBoxing = false;
GprIndexToGprOffsetImpl(uint32_t gpr_index)453*795d594fSAndroid Build Coastguard Worker   static size_t GprIndexToGprOffsetImpl(uint32_t gpr_index) {
454*795d594fSAndroid Build Coastguard Worker     return gpr_index * GetBytesPerGprSpillLocation(InstructionSet::kArm64);
455*795d594fSAndroid Build Coastguard Worker   }
456*795d594fSAndroid Build Coastguard Worker };
457*795d594fSAndroid Build Coastguard Worker 
458*795d594fSAndroid Build Coastguard Worker class QuickArgumentFrameInfoRISCV64 {
459*795d594fSAndroid Build Coastguard Worker  public:
460*795d594fSAndroid Build Coastguard Worker   // The callee save frame is pointed to by SP.
461*795d594fSAndroid Build Coastguard Worker   // | argN            |  |
462*795d594fSAndroid Build Coastguard Worker   // | ...             |  |
463*795d594fSAndroid Build Coastguard Worker   // | reg. arg spills |  |  Caller's frame
464*795d594fSAndroid Build Coastguard Worker   // | Method*         | ---
465*795d594fSAndroid Build Coastguard Worker   // | RA              |
466*795d594fSAndroid Build Coastguard Worker   // | S11/X27         |  callee-saved 11
467*795d594fSAndroid Build Coastguard Worker   // | S10/X26         |  callee-saved 10
468*795d594fSAndroid Build Coastguard Worker   // | S9/X25          |  callee-saved 9
469*795d594fSAndroid Build Coastguard Worker   // | S9/X24          |  callee-saved 8
470*795d594fSAndroid Build Coastguard Worker   // | S7/X23          |  callee-saved 7
471*795d594fSAndroid Build Coastguard Worker   // | S6/X22          |  callee-saved 6
472*795d594fSAndroid Build Coastguard Worker   // | S5/X21          |  callee-saved 5
473*795d594fSAndroid Build Coastguard Worker   // | S4/X20          |  callee-saved 4
474*795d594fSAndroid Build Coastguard Worker   // | S3/X19          |  callee-saved 3
475*795d594fSAndroid Build Coastguard Worker   // | S2/X18          |  callee-saved 2
476*795d594fSAndroid Build Coastguard Worker   // | A7/X17          |  arg 7
477*795d594fSAndroid Build Coastguard Worker   // | A6/X16          |  arg 6
478*795d594fSAndroid Build Coastguard Worker   // | A5/X15          |  arg 5
479*795d594fSAndroid Build Coastguard Worker   // | A4/X14          |  arg 4
480*795d594fSAndroid Build Coastguard Worker   // | A3/X13          |  arg 3
481*795d594fSAndroid Build Coastguard Worker   // | A2/X12          |  arg 2
482*795d594fSAndroid Build Coastguard Worker   // | A1/X11          |  arg 1 (A0 is the method => skipped)
483*795d594fSAndroid Build Coastguard Worker   // | S0/X8/FP        |  callee-saved 0 (S1 is TR => skipped)
484*795d594fSAndroid Build Coastguard Worker   // | FA7             |  float arg 8
485*795d594fSAndroid Build Coastguard Worker   // | FA6             |  float arg 7
486*795d594fSAndroid Build Coastguard Worker   // | FA5             |  float arg 6
487*795d594fSAndroid Build Coastguard Worker   // | FA4             |  float arg 5
488*795d594fSAndroid Build Coastguard Worker   // | FA3             |  float arg 4
489*795d594fSAndroid Build Coastguard Worker   // | FA2             |  float arg 3
490*795d594fSAndroid Build Coastguard Worker   // | FA1             |  float arg 2
491*795d594fSAndroid Build Coastguard Worker   // | FA0             |  float arg 1
492*795d594fSAndroid Build Coastguard Worker   // | A0/Method*      | <- sp
493*795d594fSAndroid Build Coastguard Worker   static constexpr bool kSplitPairAcrossRegisterAndStack = false;
494*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignPairRegister = false;
495*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSoftFloatAbi = false;
496*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
497*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSkipOddFpRegisters = false;
498*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickGprArgs = 7;
499*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickFprArgs = 8;
500*795d594fSAndroid Build Coastguard Worker   static constexpr bool kGprFprLockstep = false;
501*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNaNBoxing = true;
GprIndexToGprOffsetImpl(uint32_t gpr_index)502*795d594fSAndroid Build Coastguard Worker   static size_t GprIndexToGprOffsetImpl(uint32_t gpr_index) {
503*795d594fSAndroid Build Coastguard Worker     // skip S0/X8/FP
504*795d594fSAndroid Build Coastguard Worker     return (gpr_index + 1) * GetBytesPerGprSpillLocation(InstructionSet::kRiscv64);
505*795d594fSAndroid Build Coastguard Worker   }
506*795d594fSAndroid Build Coastguard Worker };
507*795d594fSAndroid Build Coastguard Worker 
508*795d594fSAndroid Build Coastguard Worker class QuickArgumentFrameInfoX86 {
509*795d594fSAndroid Build Coastguard Worker  public:
510*795d594fSAndroid Build Coastguard Worker   // The callee save frame is pointed to by SP.
511*795d594fSAndroid Build Coastguard Worker   // | argN        |  |
512*795d594fSAndroid Build Coastguard Worker   // | ...         |  |
513*795d594fSAndroid Build Coastguard Worker   // | arg4        |  |
514*795d594fSAndroid Build Coastguard Worker   // | arg3 spill  |  |  Caller's frame
515*795d594fSAndroid Build Coastguard Worker   // | arg2 spill  |  |
516*795d594fSAndroid Build Coastguard Worker   // | arg1 spill  |  |
517*795d594fSAndroid Build Coastguard Worker   // | Method*     | ---
518*795d594fSAndroid Build Coastguard Worker   // | Return      |
519*795d594fSAndroid Build Coastguard Worker   // | EBP,ESI,EDI |    callee saves
520*795d594fSAndroid Build Coastguard Worker   // | EBX         |    arg3
521*795d594fSAndroid Build Coastguard Worker   // | EDX         |    arg2
522*795d594fSAndroid Build Coastguard Worker   // | ECX         |    arg1
523*795d594fSAndroid Build Coastguard Worker   // | XMM3        |    float arg 4
524*795d594fSAndroid Build Coastguard Worker   // | XMM2        |    float arg 3
525*795d594fSAndroid Build Coastguard Worker   // | XMM1        |    float arg 2
526*795d594fSAndroid Build Coastguard Worker   // | XMM0        |    float arg 1
527*795d594fSAndroid Build Coastguard Worker   // | EAX/Method* |  <- sp
528*795d594fSAndroid Build Coastguard Worker   static constexpr bool kSplitPairAcrossRegisterAndStack = false;
529*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignPairRegister = false;
530*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSoftFloatAbi = false;  // This is a hard float ABI.
531*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
532*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSkipOddFpRegisters = false;
533*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickGprArgs = 3;  // 3 arguments passed in GPRs.
534*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickFprArgs = 4;  // 4 arguments passed in FPRs.
535*795d594fSAndroid Build Coastguard Worker   static constexpr bool kGprFprLockstep = false;
536*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNaNBoxing = false;
GprIndexToGprOffsetImpl(uint32_t gpr_index)537*795d594fSAndroid Build Coastguard Worker   static size_t GprIndexToGprOffsetImpl(uint32_t gpr_index) {
538*795d594fSAndroid Build Coastguard Worker     return gpr_index * GetBytesPerGprSpillLocation(InstructionSet::kX86);
539*795d594fSAndroid Build Coastguard Worker   }
540*795d594fSAndroid Build Coastguard Worker };
541*795d594fSAndroid Build Coastguard Worker 
542*795d594fSAndroid Build Coastguard Worker class QuickArgumentFrameInfoX86_64 {
543*795d594fSAndroid Build Coastguard Worker  public:
544*795d594fSAndroid Build Coastguard Worker   // The callee save frame is pointed to by SP.
545*795d594fSAndroid Build Coastguard Worker   // | argN            |  |
546*795d594fSAndroid Build Coastguard Worker   // | ...             |  |
547*795d594fSAndroid Build Coastguard Worker   // | reg. arg spills |  |  Caller's frame
548*795d594fSAndroid Build Coastguard Worker   // | Method*         | ---
549*795d594fSAndroid Build Coastguard Worker   // | Return          |
550*795d594fSAndroid Build Coastguard Worker   // | R15             |    callee save
551*795d594fSAndroid Build Coastguard Worker   // | R14             |    callee save
552*795d594fSAndroid Build Coastguard Worker   // | R13             |    callee save
553*795d594fSAndroid Build Coastguard Worker   // | R12             |    callee save
554*795d594fSAndroid Build Coastguard Worker   // | R9              |    arg5
555*795d594fSAndroid Build Coastguard Worker   // | R8              |    arg4
556*795d594fSAndroid Build Coastguard Worker   // | RSI/R6          |    arg1
557*795d594fSAndroid Build Coastguard Worker   // | RBP/R5          |    callee save
558*795d594fSAndroid Build Coastguard Worker   // | RBX/R3          |    callee save
559*795d594fSAndroid Build Coastguard Worker   // | RDX/R2          |    arg2
560*795d594fSAndroid Build Coastguard Worker   // | RCX/R1          |    arg3
561*795d594fSAndroid Build Coastguard Worker   // | XMM15           |    callee save
562*795d594fSAndroid Build Coastguard Worker   // | XMM14           |    callee save
563*795d594fSAndroid Build Coastguard Worker   // | XMM13           |    callee save
564*795d594fSAndroid Build Coastguard Worker   // | XMM12           |    callee save
565*795d594fSAndroid Build Coastguard Worker   // | XMM7            |    float arg 8
566*795d594fSAndroid Build Coastguard Worker   // | XMM6            |    float arg 7
567*795d594fSAndroid Build Coastguard Worker   // | XMM5            |    float arg 6
568*795d594fSAndroid Build Coastguard Worker   // | XMM4            |    float arg 5
569*795d594fSAndroid Build Coastguard Worker   // | XMM3            |    float arg 4
570*795d594fSAndroid Build Coastguard Worker   // | XMM2            |    float arg 3
571*795d594fSAndroid Build Coastguard Worker   // | XMM1            |    float arg 2
572*795d594fSAndroid Build Coastguard Worker   // | XMM0            |    float arg 1
573*795d594fSAndroid Build Coastguard Worker   // | Padding         |
574*795d594fSAndroid Build Coastguard Worker   // | RDI/Method*     |  <- sp
575*795d594fSAndroid Build Coastguard Worker   static constexpr bool kSplitPairAcrossRegisterAndStack = false;
576*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignPairRegister = false;
577*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSoftFloatAbi = false;  // This is a hard float ABI.
578*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false;
579*795d594fSAndroid Build Coastguard Worker   static constexpr bool kQuickSkipOddFpRegisters = false;
580*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickGprArgs = 5;  // 5 arguments passed in GPRs.
581*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumQuickFprArgs = 8;  // 8 arguments passed in FPRs.
582*795d594fSAndroid Build Coastguard Worker   static constexpr bool kGprFprLockstep = false;
583*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNaNBoxing = false;
GprIndexToGprOffsetImpl(uint32_t gpr_index)584*795d594fSAndroid Build Coastguard Worker   static size_t GprIndexToGprOffsetImpl(uint32_t gpr_index) {
585*795d594fSAndroid Build Coastguard Worker     static constexpr size_t kBytesPerSpill = GetBytesPerGprSpillLocation(InstructionSet::kX86_64);
586*795d594fSAndroid Build Coastguard Worker     switch (gpr_index) {
587*795d594fSAndroid Build Coastguard Worker       case 0: return (4 * kBytesPerSpill);
588*795d594fSAndroid Build Coastguard Worker       case 1: return (1 * kBytesPerSpill);
589*795d594fSAndroid Build Coastguard Worker       case 2: return (0 * kBytesPerSpill);
590*795d594fSAndroid Build Coastguard Worker       case 3: return (5 * kBytesPerSpill);
591*795d594fSAndroid Build Coastguard Worker       case 4: return (6 * kBytesPerSpill);
592*795d594fSAndroid Build Coastguard Worker       default:
593*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unexpected GPR index: " << gpr_index;
594*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
595*795d594fSAndroid Build Coastguard Worker     }
596*795d594fSAndroid Build Coastguard Worker   }
597*795d594fSAndroid Build Coastguard Worker };
598*795d594fSAndroid Build Coastguard Worker 
599*795d594fSAndroid Build Coastguard Worker namespace detail {
600*795d594fSAndroid Build Coastguard Worker 
601*795d594fSAndroid Build Coastguard Worker template <InstructionSet>
602*795d594fSAndroid Build Coastguard Worker struct QAFISelector;
603*795d594fSAndroid Build Coastguard Worker 
604*795d594fSAndroid Build Coastguard Worker template <>
605*795d594fSAndroid Build Coastguard Worker struct QAFISelector<InstructionSet::kArm> { using type = QuickArgumentFrameInfoARM; };
606*795d594fSAndroid Build Coastguard Worker template <>
607*795d594fSAndroid Build Coastguard Worker struct QAFISelector<InstructionSet::kArm64> { using type = QuickArgumentFrameInfoARM64; };
608*795d594fSAndroid Build Coastguard Worker template <>
609*795d594fSAndroid Build Coastguard Worker struct QAFISelector<InstructionSet::kRiscv64> { using type = QuickArgumentFrameInfoRISCV64; };
610*795d594fSAndroid Build Coastguard Worker template <>
611*795d594fSAndroid Build Coastguard Worker struct QAFISelector<InstructionSet::kX86> { using type = QuickArgumentFrameInfoX86; };
612*795d594fSAndroid Build Coastguard Worker template <>
613*795d594fSAndroid Build Coastguard Worker struct QAFISelector<InstructionSet::kX86_64> { using type = QuickArgumentFrameInfoX86_64; };
614*795d594fSAndroid Build Coastguard Worker 
615*795d594fSAndroid Build Coastguard Worker }  // namespace detail
616*795d594fSAndroid Build Coastguard Worker 
617*795d594fSAndroid Build Coastguard Worker using QuickArgumentVisitor =
618*795d594fSAndroid Build Coastguard Worker     QuickArgumentVisitorImpl<detail::QAFISelector<kRuntimeQuickCodeISA>::type>;
619*795d594fSAndroid Build Coastguard Worker 
620*795d594fSAndroid Build Coastguard Worker // Returns the 'this' object of a proxy method. This function is only used by StackVisitor. It
621*795d594fSAndroid Build Coastguard Worker // allows to use the QuickArgumentVisitor constants without moving all the code in its own module.
artQuickGetProxyThisObject(ArtMethod ** sp)622*795d594fSAndroid Build Coastguard Worker extern "C" mirror::Object* artQuickGetProxyThisObject(ArtMethod** sp)
623*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
624*795d594fSAndroid Build Coastguard Worker   DCHECK((*sp)->IsProxyMethod());
625*795d594fSAndroid Build Coastguard Worker   return QuickArgumentVisitor::GetThisObjectReference(sp)->AsMirrorPtr();
626*795d594fSAndroid Build Coastguard Worker }
627*795d594fSAndroid Build Coastguard Worker 
628*795d594fSAndroid Build Coastguard Worker // Visits arguments on the stack placing them into the shadow frame.
629*795d594fSAndroid Build Coastguard Worker class BuildQuickShadowFrameVisitor final : public QuickArgumentVisitor {
630*795d594fSAndroid Build Coastguard Worker  public:
BuildQuickShadowFrameVisitor(ArtMethod ** sp,bool is_static,std::string_view shorty,ShadowFrame * sf,size_t first_arg_reg)631*795d594fSAndroid Build Coastguard Worker   BuildQuickShadowFrameVisitor(ArtMethod** sp,
632*795d594fSAndroid Build Coastguard Worker                                bool is_static,
633*795d594fSAndroid Build Coastguard Worker                                std::string_view shorty,
634*795d594fSAndroid Build Coastguard Worker                                ShadowFrame* sf,
635*795d594fSAndroid Build Coastguard Worker                                size_t first_arg_reg)
636*795d594fSAndroid Build Coastguard Worker       : QuickArgumentVisitor(sp, is_static, shorty), sf_(sf), cur_reg_(first_arg_reg) {}
637*795d594fSAndroid Build Coastguard Worker 
638*795d594fSAndroid Build Coastguard Worker   void Visit() REQUIRES_SHARED(Locks::mutator_lock_) override;
639*795d594fSAndroid Build Coastguard Worker   void SetReceiver(ObjPtr<mirror::Object> receiver) REQUIRES_SHARED(Locks::mutator_lock_);
640*795d594fSAndroid Build Coastguard Worker 
641*795d594fSAndroid Build Coastguard Worker  private:
642*795d594fSAndroid Build Coastguard Worker   ShadowFrame* const sf_;
643*795d594fSAndroid Build Coastguard Worker   uint32_t cur_reg_;
644*795d594fSAndroid Build Coastguard Worker 
645*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(BuildQuickShadowFrameVisitor);
646*795d594fSAndroid Build Coastguard Worker };
647*795d594fSAndroid Build Coastguard Worker 
SetReceiver(ObjPtr<mirror::Object> receiver)648*795d594fSAndroid Build Coastguard Worker void BuildQuickShadowFrameVisitor::SetReceiver(ObjPtr<mirror::Object> receiver) {
649*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(cur_reg_, 0u);
650*795d594fSAndroid Build Coastguard Worker   sf_->SetVRegReference(cur_reg_, receiver);
651*795d594fSAndroid Build Coastguard Worker   ++cur_reg_;
652*795d594fSAndroid Build Coastguard Worker }
653*795d594fSAndroid Build Coastguard Worker 
Visit()654*795d594fSAndroid Build Coastguard Worker void BuildQuickShadowFrameVisitor::Visit() {
655*795d594fSAndroid Build Coastguard Worker   Primitive::Type type = GetParamPrimitiveType();
656*795d594fSAndroid Build Coastguard Worker   switch (type) {
657*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimLong:  // Fall-through.
658*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimDouble:
659*795d594fSAndroid Build Coastguard Worker       if (IsSplitLongOrDouble()) {
660*795d594fSAndroid Build Coastguard Worker         sf_->SetVRegLong(cur_reg_, ReadSplitLongParam());
661*795d594fSAndroid Build Coastguard Worker       } else {
662*795d594fSAndroid Build Coastguard Worker         sf_->SetVRegLong(cur_reg_, *reinterpret_cast<jlong*>(GetParamAddress()));
663*795d594fSAndroid Build Coastguard Worker       }
664*795d594fSAndroid Build Coastguard Worker       ++cur_reg_;
665*795d594fSAndroid Build Coastguard Worker       break;
666*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimNot: {
667*795d594fSAndroid Build Coastguard Worker         StackReference<mirror::Object>* stack_ref =
668*795d594fSAndroid Build Coastguard Worker             reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress());
669*795d594fSAndroid Build Coastguard Worker         sf_->SetVRegReference(cur_reg_, stack_ref->AsMirrorPtr());
670*795d594fSAndroid Build Coastguard Worker       }
671*795d594fSAndroid Build Coastguard Worker       break;
672*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimBoolean:  // Fall-through.
673*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimByte:     // Fall-through.
674*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimChar:     // Fall-through.
675*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimShort:    // Fall-through.
676*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimInt:      // Fall-through.
677*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimFloat:
678*795d594fSAndroid Build Coastguard Worker       sf_->SetVReg(cur_reg_, *reinterpret_cast<jint*>(GetParamAddress()));
679*795d594fSAndroid Build Coastguard Worker       break;
680*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimVoid:
681*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "UNREACHABLE";
682*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
683*795d594fSAndroid Build Coastguard Worker   }
684*795d594fSAndroid Build Coastguard Worker   ++cur_reg_;
685*795d594fSAndroid Build Coastguard Worker }
686*795d594fSAndroid Build Coastguard Worker 
687*795d594fSAndroid Build Coastguard Worker // Don't inline. See b/65159206.
688*795d594fSAndroid Build Coastguard Worker NO_INLINE
HandleDeoptimization(JValue * result,ArtMethod * method,ShadowFrame * deopt_frame,ManagedStack * fragment)689*795d594fSAndroid Build Coastguard Worker static void HandleDeoptimization(JValue* result,
690*795d594fSAndroid Build Coastguard Worker                                  ArtMethod* method,
691*795d594fSAndroid Build Coastguard Worker                                  ShadowFrame* deopt_frame,
692*795d594fSAndroid Build Coastguard Worker                                  ManagedStack* fragment)
693*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
694*795d594fSAndroid Build Coastguard Worker   // Coming from partial-fragment deopt.
695*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
696*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
697*795d594fSAndroid Build Coastguard Worker     // Consistency-check: are the methods as expected? We check that the last shadow frame
698*795d594fSAndroid Build Coastguard Worker     // (the bottom of the call-stack) corresponds to the called method.
699*795d594fSAndroid Build Coastguard Worker     ShadowFrame* linked = deopt_frame;
700*795d594fSAndroid Build Coastguard Worker     while (linked->GetLink() != nullptr) {
701*795d594fSAndroid Build Coastguard Worker       linked = linked->GetLink();
702*795d594fSAndroid Build Coastguard Worker     }
703*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(method, linked->GetMethod()) << method->PrettyMethod() << " "
704*795d594fSAndroid Build Coastguard Worker         << ArtMethod::PrettyMethod(linked->GetMethod());
705*795d594fSAndroid Build Coastguard Worker   }
706*795d594fSAndroid Build Coastguard Worker 
707*795d594fSAndroid Build Coastguard Worker   if (VLOG_IS_ON(deopt)) {
708*795d594fSAndroid Build Coastguard Worker     // Print out the stack to verify that it was a partial-fragment deopt.
709*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "Continue-ing from deopt. Stack is:";
710*795d594fSAndroid Build Coastguard Worker     QuickExceptionHandler::DumpFramesWithType(self, true);
711*795d594fSAndroid Build Coastguard Worker   }
712*795d594fSAndroid Build Coastguard Worker 
713*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Throwable> pending_exception;
714*795d594fSAndroid Build Coastguard Worker   bool from_code = false;
715*795d594fSAndroid Build Coastguard Worker   DeoptimizationMethodType method_type;
716*795d594fSAndroid Build Coastguard Worker   self->PopDeoptimizationContext(/* out */ result,
717*795d594fSAndroid Build Coastguard Worker                                  /* out */ &pending_exception,
718*795d594fSAndroid Build Coastguard Worker                                  /* out */ &from_code,
719*795d594fSAndroid Build Coastguard Worker                                  /* out */ &method_type);
720*795d594fSAndroid Build Coastguard Worker 
721*795d594fSAndroid Build Coastguard Worker   // Push a transition back into managed code onto the linked list in thread.
722*795d594fSAndroid Build Coastguard Worker   self->PushManagedStackFragment(fragment);
723*795d594fSAndroid Build Coastguard Worker 
724*795d594fSAndroid Build Coastguard Worker   // Ensure that the stack is still in order.
725*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
726*795d594fSAndroid Build Coastguard Worker     class EntireStackVisitor : public StackVisitor {
727*795d594fSAndroid Build Coastguard Worker      public:
728*795d594fSAndroid Build Coastguard Worker       explicit EntireStackVisitor(Thread* self_in) REQUIRES_SHARED(Locks::mutator_lock_)
729*795d594fSAndroid Build Coastguard Worker           : StackVisitor(self_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
730*795d594fSAndroid Build Coastguard Worker 
731*795d594fSAndroid Build Coastguard Worker       bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
732*795d594fSAndroid Build Coastguard Worker         // Nothing to do here. In a debug build, ValidateFrame will do the work in the walking
733*795d594fSAndroid Build Coastguard Worker         // logic. Just always say we want to continue.
734*795d594fSAndroid Build Coastguard Worker         return true;
735*795d594fSAndroid Build Coastguard Worker       }
736*795d594fSAndroid Build Coastguard Worker     };
737*795d594fSAndroid Build Coastguard Worker     EntireStackVisitor esv(self);
738*795d594fSAndroid Build Coastguard Worker     esv.WalkStack();
739*795d594fSAndroid Build Coastguard Worker   }
740*795d594fSAndroid Build Coastguard Worker 
741*795d594fSAndroid Build Coastguard Worker   // Restore the exception that was pending before deoptimization then interpret the
742*795d594fSAndroid Build Coastguard Worker   // deoptimized frames.
743*795d594fSAndroid Build Coastguard Worker   if (pending_exception != nullptr) {
744*795d594fSAndroid Build Coastguard Worker     self->SetException(pending_exception);
745*795d594fSAndroid Build Coastguard Worker   }
746*795d594fSAndroid Build Coastguard Worker   interpreter::EnterInterpreterFromDeoptimize(self,
747*795d594fSAndroid Build Coastguard Worker                                               deopt_frame,
748*795d594fSAndroid Build Coastguard Worker                                               result,
749*795d594fSAndroid Build Coastguard Worker                                               from_code,
750*795d594fSAndroid Build Coastguard Worker                                               method_type);
751*795d594fSAndroid Build Coastguard Worker }
752*795d594fSAndroid Build Coastguard Worker 
NanBoxResultIfNeeded(int64_t result,char result_shorty)753*795d594fSAndroid Build Coastguard Worker static int64_t NanBoxResultIfNeeded(int64_t result, char result_shorty) {
754*795d594fSAndroid Build Coastguard Worker   return (QuickArgumentVisitor::NaNBoxing() && result_shorty == 'F')
755*795d594fSAndroid Build Coastguard Worker       ? result | UINT64_C(0xffffffff00000000)
756*795d594fSAndroid Build Coastguard Worker       : result;
757*795d594fSAndroid Build Coastguard Worker }
758*795d594fSAndroid Build Coastguard Worker 
759*795d594fSAndroid Build Coastguard Worker NO_STACK_PROTECTOR
artQuickToInterpreterBridge(ArtMethod * method,Thread * self,ArtMethod ** sp)760*795d594fSAndroid Build Coastguard Worker extern "C" uint64_t artQuickToInterpreterBridge(ArtMethod* method, Thread* self, ArtMethod** sp)
761*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
762*795d594fSAndroid Build Coastguard Worker   // Ensure we don't get thread suspension until the object arguments are safely in the shadow
763*795d594fSAndroid Build Coastguard Worker   // frame.
764*795d594fSAndroid Build Coastguard Worker   ScopedQuickEntrypointChecks sqec(self);
765*795d594fSAndroid Build Coastguard Worker 
766*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!method->IsInvokable())) {
767*795d594fSAndroid Build Coastguard Worker     method->ThrowInvocationTimeError(
768*795d594fSAndroid Build Coastguard Worker         method->IsStatic()
769*795d594fSAndroid Build Coastguard Worker             ? nullptr
770*795d594fSAndroid Build Coastguard Worker             : QuickArgumentVisitor::GetThisObjectReference(sp)->AsMirrorPtr());
771*795d594fSAndroid Build Coastguard Worker     return 0;
772*795d594fSAndroid Build Coastguard Worker   }
773*795d594fSAndroid Build Coastguard Worker 
774*795d594fSAndroid Build Coastguard Worker   DCHECK(!method->IsNative()) << method->PrettyMethod();
775*795d594fSAndroid Build Coastguard Worker 
776*795d594fSAndroid Build Coastguard Worker   JValue result;
777*795d594fSAndroid Build Coastguard Worker 
778*795d594fSAndroid Build Coastguard Worker   ArtMethod* non_proxy_method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
779*795d594fSAndroid Build Coastguard Worker   DCHECK(non_proxy_method->GetCodeItem() != nullptr) << method->PrettyMethod();
780*795d594fSAndroid Build Coastguard Worker   std::string_view shorty = non_proxy_method->GetShortyView();
781*795d594fSAndroid Build Coastguard Worker 
782*795d594fSAndroid Build Coastguard Worker   ManagedStack fragment;
783*795d594fSAndroid Build Coastguard Worker   ShadowFrame* deopt_frame = self->MaybePopDeoptimizedStackedShadowFrame();
784*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(deopt_frame != nullptr)) {
785*795d594fSAndroid Build Coastguard Worker     HandleDeoptimization(&result, method, deopt_frame, &fragment);
786*795d594fSAndroid Build Coastguard Worker   } else {
787*795d594fSAndroid Build Coastguard Worker     CodeItemDataAccessor accessor(non_proxy_method->DexInstructionData());
788*795d594fSAndroid Build Coastguard Worker     const char* old_cause = self->StartAssertNoThreadSuspension(
789*795d594fSAndroid Build Coastguard Worker         "Building interpreter shadow frame");
790*795d594fSAndroid Build Coastguard Worker     uint16_t num_regs = accessor.RegistersSize();
791*795d594fSAndroid Build Coastguard Worker     // No last shadow coming from quick.
792*795d594fSAndroid Build Coastguard Worker     ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
793*795d594fSAndroid Build Coastguard Worker         CREATE_SHADOW_FRAME(num_regs, method, /* dex_pc= */ 0);
794*795d594fSAndroid Build Coastguard Worker     ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get();
795*795d594fSAndroid Build Coastguard Worker     size_t first_arg_reg = accessor.RegistersSize() - accessor.InsSize();
796*795d594fSAndroid Build Coastguard Worker     BuildQuickShadowFrameVisitor shadow_frame_builder(
797*795d594fSAndroid Build Coastguard Worker         sp, method->IsStatic(), shorty, shadow_frame, first_arg_reg);
798*795d594fSAndroid Build Coastguard Worker     shadow_frame_builder.VisitArguments();
799*795d594fSAndroid Build Coastguard Worker     self->EndAssertNoThreadSuspension(old_cause);
800*795d594fSAndroid Build Coastguard Worker 
801*795d594fSAndroid Build Coastguard Worker     // Potentially run <clinit> before pushing the shadow frame. We do not want
802*795d594fSAndroid Build Coastguard Worker     // to have the called method on the stack if there is an exception.
803*795d594fSAndroid Build Coastguard Worker     if (!EnsureInitialized(self, shadow_frame)) {
804*795d594fSAndroid Build Coastguard Worker       DCHECK(self->IsExceptionPending());
805*795d594fSAndroid Build Coastguard Worker       return 0;
806*795d594fSAndroid Build Coastguard Worker     }
807*795d594fSAndroid Build Coastguard Worker 
808*795d594fSAndroid Build Coastguard Worker     // Push a transition back into managed code onto the linked list in thread.
809*795d594fSAndroid Build Coastguard Worker     self->PushManagedStackFragment(&fragment);
810*795d594fSAndroid Build Coastguard Worker     self->PushShadowFrame(shadow_frame);
811*795d594fSAndroid Build Coastguard Worker     result = interpreter::EnterInterpreterFromEntryPoint(self, accessor, shadow_frame);
812*795d594fSAndroid Build Coastguard Worker   }
813*795d594fSAndroid Build Coastguard Worker 
814*795d594fSAndroid Build Coastguard Worker   // Pop transition.
815*795d594fSAndroid Build Coastguard Worker   self->PopManagedStackFragment(fragment);
816*795d594fSAndroid Build Coastguard Worker 
817*795d594fSAndroid Build Coastguard Worker   // Check if caller needs to be deoptimized for instrumentation reasons.
818*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
819*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(instr->ShouldDeoptimizeCaller(self, sp))) {
820*795d594fSAndroid Build Coastguard Worker     ArtMethod* caller = QuickArgumentVisitor::GetOuterMethod(sp);
821*795d594fSAndroid Build Coastguard Worker     uintptr_t caller_pc = QuickArgumentVisitor::GetCallingPc(sp);
822*795d594fSAndroid Build Coastguard Worker     DCHECK(Runtime::Current()->IsAsyncDeoptimizeable(caller, caller_pc));
823*795d594fSAndroid Build Coastguard Worker     DCHECK(caller != nullptr);
824*795d594fSAndroid Build Coastguard Worker     DCHECK(self->GetException() != Thread::GetDeoptimizationException());
825*795d594fSAndroid Build Coastguard Worker     // Push the context of the deoptimization stack so we can restore the return value and the
826*795d594fSAndroid Build Coastguard Worker     // exception before executing the deoptimized frames.
827*795d594fSAndroid Build Coastguard Worker     self->PushDeoptimizationContext(result,
828*795d594fSAndroid Build Coastguard Worker                                     shorty[0] == 'L' || shorty[0] == '[',  // class or array
829*795d594fSAndroid Build Coastguard Worker                                     self->GetException(),
830*795d594fSAndroid Build Coastguard Worker                                     /* from_code= */ false,
831*795d594fSAndroid Build Coastguard Worker                                     DeoptimizationMethodType::kDefault);
832*795d594fSAndroid Build Coastguard Worker 
833*795d594fSAndroid Build Coastguard Worker     // Set special exception to cause deoptimization.
834*795d594fSAndroid Build Coastguard Worker     self->SetException(Thread::GetDeoptimizationException());
835*795d594fSAndroid Build Coastguard Worker   }
836*795d594fSAndroid Build Coastguard Worker 
837*795d594fSAndroid Build Coastguard Worker   // No need to restore the args since the method has already been run by the interpreter.
838*795d594fSAndroid Build Coastguard Worker   return NanBoxResultIfNeeded(result.GetJ(), shorty[0]);
839*795d594fSAndroid Build Coastguard Worker }
840*795d594fSAndroid Build Coastguard Worker 
841*795d594fSAndroid Build Coastguard Worker // Visits arguments on the stack placing them into the args vector, Object* arguments are converted
842*795d594fSAndroid Build Coastguard Worker // to jobjects.
843*795d594fSAndroid Build Coastguard Worker class BuildQuickArgumentVisitor final : public QuickArgumentVisitor {
844*795d594fSAndroid Build Coastguard Worker  public:
BuildQuickArgumentVisitor(ArtMethod ** sp,bool is_static,std::string_view shorty,ScopedObjectAccessUnchecked * soa,std::vector<jvalue> * args)845*795d594fSAndroid Build Coastguard Worker   BuildQuickArgumentVisitor(ArtMethod** sp,
846*795d594fSAndroid Build Coastguard Worker                             bool is_static,
847*795d594fSAndroid Build Coastguard Worker                             std::string_view shorty,
848*795d594fSAndroid Build Coastguard Worker                             ScopedObjectAccessUnchecked* soa,
849*795d594fSAndroid Build Coastguard Worker                             std::vector<jvalue>* args)
850*795d594fSAndroid Build Coastguard Worker       : QuickArgumentVisitor(sp, is_static, shorty), soa_(soa), args_(args) {}
851*795d594fSAndroid Build Coastguard Worker 
852*795d594fSAndroid Build Coastguard Worker   void Visit() REQUIRES_SHARED(Locks::mutator_lock_) override;
853*795d594fSAndroid Build Coastguard Worker 
854*795d594fSAndroid Build Coastguard Worker  private:
855*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccessUnchecked* const soa_;
856*795d594fSAndroid Build Coastguard Worker   std::vector<jvalue>* const args_;
857*795d594fSAndroid Build Coastguard Worker 
858*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(BuildQuickArgumentVisitor);
859*795d594fSAndroid Build Coastguard Worker };
860*795d594fSAndroid Build Coastguard Worker 
Visit()861*795d594fSAndroid Build Coastguard Worker void BuildQuickArgumentVisitor::Visit() {
862*795d594fSAndroid Build Coastguard Worker   jvalue val;
863*795d594fSAndroid Build Coastguard Worker   Primitive::Type type = GetParamPrimitiveType();
864*795d594fSAndroid Build Coastguard Worker   switch (type) {
865*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimNot: {
866*795d594fSAndroid Build Coastguard Worker       StackReference<mirror::Object>* stack_ref =
867*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress());
868*795d594fSAndroid Build Coastguard Worker       val.l = soa_->AddLocalReference<jobject>(stack_ref->AsMirrorPtr());
869*795d594fSAndroid Build Coastguard Worker       break;
870*795d594fSAndroid Build Coastguard Worker     }
871*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimLong:  // Fall-through.
872*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimDouble:
873*795d594fSAndroid Build Coastguard Worker       if (IsSplitLongOrDouble()) {
874*795d594fSAndroid Build Coastguard Worker         val.j = ReadSplitLongParam();
875*795d594fSAndroid Build Coastguard Worker       } else {
876*795d594fSAndroid Build Coastguard Worker         val.j = *reinterpret_cast<jlong*>(GetParamAddress());
877*795d594fSAndroid Build Coastguard Worker       }
878*795d594fSAndroid Build Coastguard Worker       break;
879*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimBoolean:  // Fall-through.
880*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimByte:     // Fall-through.
881*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimChar:     // Fall-through.
882*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimShort:    // Fall-through.
883*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimInt:      // Fall-through.
884*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimFloat:
885*795d594fSAndroid Build Coastguard Worker       val.i = *reinterpret_cast<jint*>(GetParamAddress());
886*795d594fSAndroid Build Coastguard Worker       break;
887*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimVoid:
888*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "UNREACHABLE";
889*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
890*795d594fSAndroid Build Coastguard Worker   }
891*795d594fSAndroid Build Coastguard Worker   args_->push_back(val);
892*795d594fSAndroid Build Coastguard Worker }
893*795d594fSAndroid Build Coastguard Worker 
894*795d594fSAndroid Build Coastguard Worker // Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
895*795d594fSAndroid Build Coastguard Worker // which is responsible for recording callee save registers. We explicitly place into jobjects the
896*795d594fSAndroid Build Coastguard Worker // incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
897*795d594fSAndroid Build Coastguard Worker // field within the proxy object, which will box the primitive arguments and deal with error cases.
artQuickProxyInvokeHandler(ArtMethod * proxy_method,mirror::Object * receiver,Thread * self,ArtMethod ** sp)898*795d594fSAndroid Build Coastguard Worker extern "C" uint64_t artQuickProxyInvokeHandler(
899*795d594fSAndroid Build Coastguard Worker     ArtMethod* proxy_method, mirror::Object* receiver, Thread* self, ArtMethod** sp)
900*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
901*795d594fSAndroid Build Coastguard Worker   DCHECK(proxy_method->IsProxyMethod()) << proxy_method->PrettyMethod();
902*795d594fSAndroid Build Coastguard Worker   DCHECK(receiver->GetClass()->IsProxyClass()) << proxy_method->PrettyMethod();
903*795d594fSAndroid Build Coastguard Worker   // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
904*795d594fSAndroid Build Coastguard Worker   const char* old_cause =
905*795d594fSAndroid Build Coastguard Worker       self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
906*795d594fSAndroid Build Coastguard Worker   // Register the top of the managed stack, making stack crawlable.
907*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ((*sp), proxy_method) << proxy_method->PrettyMethod();
908*795d594fSAndroid Build Coastguard Worker   self->VerifyStack();
909*795d594fSAndroid Build Coastguard Worker   // Start new JNI local reference state.
910*795d594fSAndroid Build Coastguard Worker   JNIEnvExt* env = self->GetJniEnv();
911*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccessUnchecked soa(env);
912*795d594fSAndroid Build Coastguard Worker   ScopedJniEnvLocalRefState env_state(env);
913*795d594fSAndroid Build Coastguard Worker   // Create local ref. copies of proxy method and the receiver.
914*795d594fSAndroid Build Coastguard Worker   jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
915*795d594fSAndroid Build Coastguard Worker 
916*795d594fSAndroid Build Coastguard Worker   // Placing arguments into args vector and remove the receiver.
917*795d594fSAndroid Build Coastguard Worker   ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
918*795d594fSAndroid Build Coastguard Worker   CHECK(!non_proxy_method->IsStatic()) << proxy_method->PrettyMethod() << " "
919*795d594fSAndroid Build Coastguard Worker                                        << non_proxy_method->PrettyMethod();
920*795d594fSAndroid Build Coastguard Worker   std::vector<jvalue> args;
921*795d594fSAndroid Build Coastguard Worker   uint32_t shorty_len = 0;
922*795d594fSAndroid Build Coastguard Worker   const char* raw_shorty = non_proxy_method->GetShorty(&shorty_len);
923*795d594fSAndroid Build Coastguard Worker   std::string_view shorty(raw_shorty, shorty_len);
924*795d594fSAndroid Build Coastguard Worker   BuildQuickArgumentVisitor local_ref_visitor(sp, /* is_static= */ false, shorty, &soa, &args);
925*795d594fSAndroid Build Coastguard Worker 
926*795d594fSAndroid Build Coastguard Worker   local_ref_visitor.VisitArguments();
927*795d594fSAndroid Build Coastguard Worker   DCHECK_GT(args.size(), 0U) << proxy_method->PrettyMethod();
928*795d594fSAndroid Build Coastguard Worker   args.erase(args.begin());
929*795d594fSAndroid Build Coastguard Worker 
930*795d594fSAndroid Build Coastguard Worker   // Convert proxy method into expected interface method.
931*795d594fSAndroid Build Coastguard Worker   ArtMethod* interface_method = proxy_method->FindOverriddenMethod(kRuntimePointerSize);
932*795d594fSAndroid Build Coastguard Worker   DCHECK(interface_method != nullptr) << proxy_method->PrettyMethod();
933*795d594fSAndroid Build Coastguard Worker   DCHECK(!interface_method->IsProxyMethod()) << interface_method->PrettyMethod();
934*795d594fSAndroid Build Coastguard Worker   self->EndAssertNoThreadSuspension(old_cause);
935*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
936*795d594fSAndroid Build Coastguard Worker   DCHECK(!Runtime::Current()->IsActiveTransaction());
937*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Method> interface_reflect_method =
938*795d594fSAndroid Build Coastguard Worker       mirror::Method::CreateFromArtMethod<kRuntimePointerSize>(soa.Self(), interface_method);
939*795d594fSAndroid Build Coastguard Worker   if (interface_reflect_method == nullptr) {
940*795d594fSAndroid Build Coastguard Worker     soa.Self()->AssertPendingOOMException();
941*795d594fSAndroid Build Coastguard Worker     return 0;
942*795d594fSAndroid Build Coastguard Worker   }
943*795d594fSAndroid Build Coastguard Worker   jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_reflect_method);
944*795d594fSAndroid Build Coastguard Worker 
945*795d594fSAndroid Build Coastguard Worker   // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
946*795d594fSAndroid Build Coastguard Worker   // that performs allocations or instrumentation events.
947*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
948*795d594fSAndroid Build Coastguard Worker   if (instr->HasMethodEntryListeners()) {
949*795d594fSAndroid Build Coastguard Worker     instr->MethodEnterEvent(soa.Self(), proxy_method);
950*795d594fSAndroid Build Coastguard Worker     if (soa.Self()->IsExceptionPending()) {
951*795d594fSAndroid Build Coastguard Worker       instr->MethodUnwindEvent(self,
952*795d594fSAndroid Build Coastguard Worker                                proxy_method,
953*795d594fSAndroid Build Coastguard Worker                                0);
954*795d594fSAndroid Build Coastguard Worker       return 0;
955*795d594fSAndroid Build Coastguard Worker     }
956*795d594fSAndroid Build Coastguard Worker   }
957*795d594fSAndroid Build Coastguard Worker   JValue result =
958*795d594fSAndroid Build Coastguard Worker       InvokeProxyInvocationHandler(soa, raw_shorty, rcvr_jobj, interface_method_jobj, args);
959*795d594fSAndroid Build Coastguard Worker   if (soa.Self()->IsExceptionPending()) {
960*795d594fSAndroid Build Coastguard Worker     if (instr->HasMethodUnwindListeners()) {
961*795d594fSAndroid Build Coastguard Worker       instr->MethodUnwindEvent(self,
962*795d594fSAndroid Build Coastguard Worker                                proxy_method,
963*795d594fSAndroid Build Coastguard Worker                                0);
964*795d594fSAndroid Build Coastguard Worker     }
965*795d594fSAndroid Build Coastguard Worker   } else if (instr->HasMethodExitListeners()) {
966*795d594fSAndroid Build Coastguard Worker     instr->MethodExitEvent(self,
967*795d594fSAndroid Build Coastguard Worker                            proxy_method,
968*795d594fSAndroid Build Coastguard Worker                            {},
969*795d594fSAndroid Build Coastguard Worker                            result);
970*795d594fSAndroid Build Coastguard Worker   }
971*795d594fSAndroid Build Coastguard Worker 
972*795d594fSAndroid Build Coastguard Worker   return NanBoxResultIfNeeded(result.GetJ(), shorty[0]);
973*795d594fSAndroid Build Coastguard Worker }
974*795d594fSAndroid Build Coastguard Worker 
975*795d594fSAndroid Build Coastguard Worker // Visitor returning a reference argument at a given position in a Quick stack frame.
976*795d594fSAndroid Build Coastguard Worker // NOTE: Only used for testing purposes.
977*795d594fSAndroid Build Coastguard Worker class GetQuickReferenceArgumentAtVisitor final : public QuickArgumentVisitor {
978*795d594fSAndroid Build Coastguard Worker  public:
GetQuickReferenceArgumentAtVisitor(ArtMethod ** sp,std::string_view shorty,size_t arg_pos)979*795d594fSAndroid Build Coastguard Worker   GetQuickReferenceArgumentAtVisitor(ArtMethod** sp, std::string_view shorty, size_t arg_pos)
980*795d594fSAndroid Build Coastguard Worker       : QuickArgumentVisitor(sp, /* is_static= */ false, shorty),
981*795d594fSAndroid Build Coastguard Worker         cur_pos_(0u),
982*795d594fSAndroid Build Coastguard Worker         arg_pos_(arg_pos),
983*795d594fSAndroid Build Coastguard Worker         ref_arg_(nullptr) {
984*795d594fSAndroid Build Coastguard Worker     CHECK_LT(arg_pos, shorty.length()) << "Argument position greater than the number arguments";
985*795d594fSAndroid Build Coastguard Worker   }
986*795d594fSAndroid Build Coastguard Worker 
Visit()987*795d594fSAndroid Build Coastguard Worker   void Visit() REQUIRES_SHARED(Locks::mutator_lock_) override {
988*795d594fSAndroid Build Coastguard Worker     if (cur_pos_ == arg_pos_) {
989*795d594fSAndroid Build Coastguard Worker       Primitive::Type type = GetParamPrimitiveType();
990*795d594fSAndroid Build Coastguard Worker       CHECK_EQ(type, Primitive::kPrimNot) << "Argument at searched position is not a reference";
991*795d594fSAndroid Build Coastguard Worker       ref_arg_ = reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress());
992*795d594fSAndroid Build Coastguard Worker     }
993*795d594fSAndroid Build Coastguard Worker     ++cur_pos_;
994*795d594fSAndroid Build Coastguard Worker   }
995*795d594fSAndroid Build Coastguard Worker 
GetReferenceArgument()996*795d594fSAndroid Build Coastguard Worker   StackReference<mirror::Object>* GetReferenceArgument() {
997*795d594fSAndroid Build Coastguard Worker     return ref_arg_;
998*795d594fSAndroid Build Coastguard Worker   }
999*795d594fSAndroid Build Coastguard Worker 
1000*795d594fSAndroid Build Coastguard Worker  private:
1001*795d594fSAndroid Build Coastguard Worker   // The position of the currently visited argument.
1002*795d594fSAndroid Build Coastguard Worker   size_t cur_pos_;
1003*795d594fSAndroid Build Coastguard Worker   // The position of the searched argument.
1004*795d594fSAndroid Build Coastguard Worker   const size_t arg_pos_;
1005*795d594fSAndroid Build Coastguard Worker   // The reference argument, if found.
1006*795d594fSAndroid Build Coastguard Worker   StackReference<mirror::Object>* ref_arg_;
1007*795d594fSAndroid Build Coastguard Worker 
1008*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(GetQuickReferenceArgumentAtVisitor);
1009*795d594fSAndroid Build Coastguard Worker };
1010*795d594fSAndroid Build Coastguard Worker 
1011*795d594fSAndroid Build Coastguard Worker // Returning reference argument at position `arg_pos` in Quick stack frame at address `sp`.
1012*795d594fSAndroid Build Coastguard Worker // NOTE: Only used for testing purposes.
artQuickGetProxyReferenceArgumentAt(size_t arg_pos,ArtMethod ** sp)1013*795d594fSAndroid Build Coastguard Worker EXPORT extern "C" StackReference<mirror::Object>* artQuickGetProxyReferenceArgumentAt(
1014*795d594fSAndroid Build Coastguard Worker     size_t arg_pos, ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) {
1015*795d594fSAndroid Build Coastguard Worker   ArtMethod* proxy_method = *sp;
1016*795d594fSAndroid Build Coastguard Worker   ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
1017*795d594fSAndroid Build Coastguard Worker   CHECK(!non_proxy_method->IsStatic())
1018*795d594fSAndroid Build Coastguard Worker       << proxy_method->PrettyMethod() << " " << non_proxy_method->PrettyMethod();
1019*795d594fSAndroid Build Coastguard Worker   std::string_view shorty = non_proxy_method->GetShortyView();
1020*795d594fSAndroid Build Coastguard Worker   GetQuickReferenceArgumentAtVisitor ref_arg_visitor(sp, shorty, arg_pos);
1021*795d594fSAndroid Build Coastguard Worker   ref_arg_visitor.VisitArguments();
1022*795d594fSAndroid Build Coastguard Worker   StackReference<mirror::Object>* ref_arg = ref_arg_visitor.GetReferenceArgument();
1023*795d594fSAndroid Build Coastguard Worker   return ref_arg;
1024*795d594fSAndroid Build Coastguard Worker }
1025*795d594fSAndroid Build Coastguard Worker 
1026*795d594fSAndroid Build Coastguard Worker // Visitor returning all the reference arguments in a Quick stack frame.
1027*795d594fSAndroid Build Coastguard Worker class GetQuickReferenceArgumentsVisitor final : public QuickArgumentVisitor {
1028*795d594fSAndroid Build Coastguard Worker  public:
GetQuickReferenceArgumentsVisitor(ArtMethod ** sp,bool is_static,std::string_view shorty)1029*795d594fSAndroid Build Coastguard Worker   GetQuickReferenceArgumentsVisitor(ArtMethod** sp, bool is_static, std::string_view shorty)
1030*795d594fSAndroid Build Coastguard Worker       : QuickArgumentVisitor(sp, is_static, shorty) {}
1031*795d594fSAndroid Build Coastguard Worker 
Visit()1032*795d594fSAndroid Build Coastguard Worker   void Visit() REQUIRES_SHARED(Locks::mutator_lock_) override {
1033*795d594fSAndroid Build Coastguard Worker     Primitive::Type type = GetParamPrimitiveType();
1034*795d594fSAndroid Build Coastguard Worker     if (type == Primitive::kPrimNot) {
1035*795d594fSAndroid Build Coastguard Worker       StackReference<mirror::Object>* ref_arg =
1036*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress());
1037*795d594fSAndroid Build Coastguard Worker       ref_args_.push_back(ref_arg);
1038*795d594fSAndroid Build Coastguard Worker     }
1039*795d594fSAndroid Build Coastguard Worker   }
1040*795d594fSAndroid Build Coastguard Worker 
GetReferenceArguments()1041*795d594fSAndroid Build Coastguard Worker   std::vector<StackReference<mirror::Object>*> GetReferenceArguments() {
1042*795d594fSAndroid Build Coastguard Worker     return ref_args_;
1043*795d594fSAndroid Build Coastguard Worker   }
1044*795d594fSAndroid Build Coastguard Worker 
1045*795d594fSAndroid Build Coastguard Worker  private:
1046*795d594fSAndroid Build Coastguard Worker   // The reference arguments.
1047*795d594fSAndroid Build Coastguard Worker   std::vector<StackReference<mirror::Object>*> ref_args_;
1048*795d594fSAndroid Build Coastguard Worker 
1049*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(GetQuickReferenceArgumentsVisitor);
1050*795d594fSAndroid Build Coastguard Worker };
1051*795d594fSAndroid Build Coastguard Worker 
1052*795d594fSAndroid Build Coastguard Worker // Returning all reference arguments in Quick stack frame at address `sp`.
GetProxyReferenceArguments(ArtMethod ** sp)1053*795d594fSAndroid Build Coastguard Worker std::vector<StackReference<mirror::Object>*> GetProxyReferenceArguments(ArtMethod** sp)
1054*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
1055*795d594fSAndroid Build Coastguard Worker   ArtMethod* proxy_method = *sp;
1056*795d594fSAndroid Build Coastguard Worker   ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
1057*795d594fSAndroid Build Coastguard Worker   CHECK(!non_proxy_method->IsStatic())
1058*795d594fSAndroid Build Coastguard Worker       << proxy_method->PrettyMethod() << " " << non_proxy_method->PrettyMethod();
1059*795d594fSAndroid Build Coastguard Worker   std::string_view shorty = non_proxy_method->GetShortyView();
1060*795d594fSAndroid Build Coastguard Worker   GetQuickReferenceArgumentsVisitor ref_args_visitor(sp, /*is_static=*/ false, shorty);
1061*795d594fSAndroid Build Coastguard Worker   ref_args_visitor.VisitArguments();
1062*795d594fSAndroid Build Coastguard Worker   std::vector<StackReference<mirror::Object>*> ref_args = ref_args_visitor.GetReferenceArguments();
1063*795d594fSAndroid Build Coastguard Worker   return ref_args;
1064*795d594fSAndroid Build Coastguard Worker }
1065*795d594fSAndroid Build Coastguard Worker 
1066*795d594fSAndroid Build Coastguard Worker // Read object references held in arguments from quick frames and place in a JNI local references,
1067*795d594fSAndroid Build Coastguard Worker // so they don't get garbage collected.
1068*795d594fSAndroid Build Coastguard Worker class RememberForGcArgumentVisitor final : public QuickArgumentVisitor {
1069*795d594fSAndroid Build Coastguard Worker  public:
RememberForGcArgumentVisitor(ArtMethod ** sp,bool is_static,std::string_view shorty,ScopedObjectAccessUnchecked * soa)1070*795d594fSAndroid Build Coastguard Worker   RememberForGcArgumentVisitor(ArtMethod** sp,
1071*795d594fSAndroid Build Coastguard Worker                                bool is_static,
1072*795d594fSAndroid Build Coastguard Worker                                std::string_view shorty,
1073*795d594fSAndroid Build Coastguard Worker                                ScopedObjectAccessUnchecked* soa)
1074*795d594fSAndroid Build Coastguard Worker       : QuickArgumentVisitor(sp, is_static, shorty), soa_(soa) {}
1075*795d594fSAndroid Build Coastguard Worker 
1076*795d594fSAndroid Build Coastguard Worker   void Visit() REQUIRES_SHARED(Locks::mutator_lock_) override;
1077*795d594fSAndroid Build Coastguard Worker 
1078*795d594fSAndroid Build Coastguard Worker   void FixupReferences() REQUIRES_SHARED(Locks::mutator_lock_);
1079*795d594fSAndroid Build Coastguard Worker 
1080*795d594fSAndroid Build Coastguard Worker  private:
1081*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccessUnchecked* const soa_;
1082*795d594fSAndroid Build Coastguard Worker   // References which we must update when exiting in case the GC moved the objects.
1083*795d594fSAndroid Build Coastguard Worker   std::vector<std::pair<jobject, StackReference<mirror::Object>*> > references_;
1084*795d594fSAndroid Build Coastguard Worker 
1085*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(RememberForGcArgumentVisitor);
1086*795d594fSAndroid Build Coastguard Worker };
1087*795d594fSAndroid Build Coastguard Worker 
Visit()1088*795d594fSAndroid Build Coastguard Worker void RememberForGcArgumentVisitor::Visit() {
1089*795d594fSAndroid Build Coastguard Worker   if (IsParamAReference()) {
1090*795d594fSAndroid Build Coastguard Worker     StackReference<mirror::Object>* stack_ref =
1091*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress());
1092*795d594fSAndroid Build Coastguard Worker     jobject reference =
1093*795d594fSAndroid Build Coastguard Worker         soa_->AddLocalReference<jobject>(stack_ref->AsMirrorPtr());
1094*795d594fSAndroid Build Coastguard Worker     references_.push_back(std::make_pair(reference, stack_ref));
1095*795d594fSAndroid Build Coastguard Worker   }
1096*795d594fSAndroid Build Coastguard Worker }
1097*795d594fSAndroid Build Coastguard Worker 
FixupReferences()1098*795d594fSAndroid Build Coastguard Worker void RememberForGcArgumentVisitor::FixupReferences() {
1099*795d594fSAndroid Build Coastguard Worker   // Fixup any references which may have changed.
1100*795d594fSAndroid Build Coastguard Worker   for (const auto& pair : references_) {
1101*795d594fSAndroid Build Coastguard Worker     pair.second->Assign(soa_->Decode<mirror::Object>(pair.first));
1102*795d594fSAndroid Build Coastguard Worker     soa_->Env()->DeleteLocalRef(pair.first);
1103*795d594fSAndroid Build Coastguard Worker   }
1104*795d594fSAndroid Build Coastguard Worker }
1105*795d594fSAndroid Build Coastguard Worker 
DumpInstruction(ArtMethod * method,uint32_t dex_pc)1106*795d594fSAndroid Build Coastguard Worker static std::string DumpInstruction(ArtMethod* method, uint32_t dex_pc)
1107*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
1108*795d594fSAndroid Build Coastguard Worker   if (dex_pc == static_cast<uint32_t>(-1)) {
1109*795d594fSAndroid Build Coastguard Worker     CHECK(method == WellKnownClasses::java_lang_String_charAt);
1110*795d594fSAndroid Build Coastguard Worker     return "<native>";
1111*795d594fSAndroid Build Coastguard Worker   } else {
1112*795d594fSAndroid Build Coastguard Worker     CodeItemInstructionAccessor accessor = method->DexInstructions();
1113*795d594fSAndroid Build Coastguard Worker     CHECK_LT(dex_pc, accessor.InsnsSizeInCodeUnits());
1114*795d594fSAndroid Build Coastguard Worker     return accessor.InstructionAt(dex_pc).DumpString(method->GetDexFile());
1115*795d594fSAndroid Build Coastguard Worker   }
1116*795d594fSAndroid Build Coastguard Worker }
1117*795d594fSAndroid Build Coastguard Worker 
DumpB74410240ClassData(ObjPtr<mirror::Class> klass)1118*795d594fSAndroid Build Coastguard Worker static void DumpB74410240ClassData(ObjPtr<mirror::Class> klass)
1119*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
1120*795d594fSAndroid Build Coastguard Worker   std::string storage;
1121*795d594fSAndroid Build Coastguard Worker   const char* descriptor = klass->GetDescriptor(&storage);
1122*795d594fSAndroid Build Coastguard Worker   LOG(FATAL_WITHOUT_ABORT) << "  " << DescribeLoaders(klass->GetClassLoader(), descriptor);
1123*795d594fSAndroid Build Coastguard Worker   const OatDexFile* oat_dex_file = klass->GetDexFile().GetOatDexFile();
1124*795d594fSAndroid Build Coastguard Worker   if (oat_dex_file != nullptr) {
1125*795d594fSAndroid Build Coastguard Worker     const OatFile* oat_file = oat_dex_file->GetOatFile();
1126*795d594fSAndroid Build Coastguard Worker     const char* dex2oat_cmdline =
1127*795d594fSAndroid Build Coastguard Worker         oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey);
1128*795d594fSAndroid Build Coastguard Worker     LOG(FATAL_WITHOUT_ABORT) << "    OatFile: " << oat_file->GetLocation()
1129*795d594fSAndroid Build Coastguard Worker         << "; " << (dex2oat_cmdline != nullptr ? dex2oat_cmdline : "<not recorded>");
1130*795d594fSAndroid Build Coastguard Worker   }
1131*795d594fSAndroid Build Coastguard Worker }
1132*795d594fSAndroid Build Coastguard Worker 
DumpB74410240DebugData(ArtMethod ** sp)1133*795d594fSAndroid Build Coastguard Worker static void DumpB74410240DebugData(ArtMethod** sp) REQUIRES_SHARED(Locks::mutator_lock_) {
1134*795d594fSAndroid Build Coastguard Worker   // Mimick the search for the caller and dump some data while doing so.
1135*795d594fSAndroid Build Coastguard Worker   LOG(FATAL_WITHOUT_ABORT) << "Dumping debugging data, please attach a bugreport to b/74410240.";
1136*795d594fSAndroid Build Coastguard Worker 
1137*795d594fSAndroid Build Coastguard Worker   constexpr CalleeSaveType type = CalleeSaveType::kSaveRefsAndArgs;
1138*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(type));
1139*795d594fSAndroid Build Coastguard Worker 
1140*795d594fSAndroid Build Coastguard Worker   constexpr size_t callee_frame_size = RuntimeCalleeSaveFrame::GetFrameSize(type);
1141*795d594fSAndroid Build Coastguard Worker   auto** caller_sp = reinterpret_cast<ArtMethod**>(
1142*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<uintptr_t>(sp) + callee_frame_size);
1143*795d594fSAndroid Build Coastguard Worker   constexpr size_t callee_return_pc_offset = RuntimeCalleeSaveFrame::GetReturnPcOffset(type);
1144*795d594fSAndroid Build Coastguard Worker   uintptr_t caller_pc = *reinterpret_cast<uintptr_t*>(
1145*795d594fSAndroid Build Coastguard Worker       (reinterpret_cast<uint8_t*>(sp) + callee_return_pc_offset));
1146*795d594fSAndroid Build Coastguard Worker   ArtMethod* outer_method = *caller_sp;
1147*795d594fSAndroid Build Coastguard Worker 
1148*795d594fSAndroid Build Coastguard Worker   const OatQuickMethodHeader* current_code = outer_method->GetOatQuickMethodHeader(caller_pc);
1149*795d594fSAndroid Build Coastguard Worker   CHECK(current_code != nullptr);
1150*795d594fSAndroid Build Coastguard Worker   CHECK(current_code->IsOptimized());
1151*795d594fSAndroid Build Coastguard Worker   uintptr_t native_pc_offset = current_code->NativeQuickPcOffset(caller_pc);
1152*795d594fSAndroid Build Coastguard Worker   CodeInfo code_info(current_code);
1153*795d594fSAndroid Build Coastguard Worker   StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
1154*795d594fSAndroid Build Coastguard Worker   CHECK(stack_map.IsValid());
1155*795d594fSAndroid Build Coastguard Worker   uint32_t dex_pc = stack_map.GetDexPc();
1156*795d594fSAndroid Build Coastguard Worker 
1157*795d594fSAndroid Build Coastguard Worker   // Log the outer method and its associated dex file and class table pointer which can be used
1158*795d594fSAndroid Build Coastguard Worker   // to find out if the inlined methods were defined by other dex file(s) or class loader(s).
1159*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1160*795d594fSAndroid Build Coastguard Worker   LOG(FATAL_WITHOUT_ABORT) << "Outer: " << outer_method->PrettyMethod()
1161*795d594fSAndroid Build Coastguard Worker       << " native pc: " << caller_pc
1162*795d594fSAndroid Build Coastguard Worker       << " dex pc: " << dex_pc
1163*795d594fSAndroid Build Coastguard Worker       << " dex file: " << outer_method->GetDexFile()->GetLocation()
1164*795d594fSAndroid Build Coastguard Worker       << " class table: " << class_linker->ClassTableForClassLoader(outer_method->GetClassLoader());
1165*795d594fSAndroid Build Coastguard Worker   DumpB74410240ClassData(outer_method->GetDeclaringClass());
1166*795d594fSAndroid Build Coastguard Worker   LOG(FATAL_WITHOUT_ABORT) << "  instruction: " << DumpInstruction(outer_method, dex_pc);
1167*795d594fSAndroid Build Coastguard Worker 
1168*795d594fSAndroid Build Coastguard Worker   ArtMethod* caller = outer_method;
1169*795d594fSAndroid Build Coastguard Worker   BitTableRange<InlineInfo> inline_infos = code_info.GetInlineInfosOf(stack_map);
1170*795d594fSAndroid Build Coastguard Worker   for (InlineInfo inline_info : inline_infos) {
1171*795d594fSAndroid Build Coastguard Worker     const char* tag = "";
1172*795d594fSAndroid Build Coastguard Worker     dex_pc = inline_info.GetDexPc();
1173*795d594fSAndroid Build Coastguard Worker     if (inline_info.EncodesArtMethod()) {
1174*795d594fSAndroid Build Coastguard Worker       tag = "encoded ";
1175*795d594fSAndroid Build Coastguard Worker       caller = inline_info.GetArtMethod();
1176*795d594fSAndroid Build Coastguard Worker     } else {
1177*795d594fSAndroid Build Coastguard Worker       uint32_t method_index = code_info.GetMethodIndexOf(inline_info);
1178*795d594fSAndroid Build Coastguard Worker       if (dex_pc == static_cast<uint32_t>(-1)) {
1179*795d594fSAndroid Build Coastguard Worker         tag = "special ";
1180*795d594fSAndroid Build Coastguard Worker         CHECK(inline_info.Equals(inline_infos.back()));
1181*795d594fSAndroid Build Coastguard Worker         caller = WellKnownClasses::java_lang_String_charAt;
1182*795d594fSAndroid Build Coastguard Worker         CHECK_EQ(caller->GetDexMethodIndex(), method_index);
1183*795d594fSAndroid Build Coastguard Worker       } else {
1184*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::DexCache> dex_cache = caller->GetDexCache();
1185*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::ClassLoader> class_loader = caller->GetClassLoader();
1186*795d594fSAndroid Build Coastguard Worker         caller = class_linker->LookupResolvedMethod(method_index, dex_cache, class_loader);
1187*795d594fSAndroid Build Coastguard Worker         CHECK(caller != nullptr);
1188*795d594fSAndroid Build Coastguard Worker       }
1189*795d594fSAndroid Build Coastguard Worker     }
1190*795d594fSAndroid Build Coastguard Worker     LOG(FATAL_WITHOUT_ABORT) << "InlineInfo #" << inline_info.Row()
1191*795d594fSAndroid Build Coastguard Worker         << ": " << tag << caller->PrettyMethod()
1192*795d594fSAndroid Build Coastguard Worker         << " dex pc: " << dex_pc
1193*795d594fSAndroid Build Coastguard Worker         << " dex file: " << caller->GetDexFile()->GetLocation()
1194*795d594fSAndroid Build Coastguard Worker         << " class table: "
1195*795d594fSAndroid Build Coastguard Worker         << class_linker->ClassTableForClassLoader(caller->GetClassLoader());
1196*795d594fSAndroid Build Coastguard Worker     DumpB74410240ClassData(caller->GetDeclaringClass());
1197*795d594fSAndroid Build Coastguard Worker     LOG(FATAL_WITHOUT_ABORT) << "  instruction: " << DumpInstruction(caller, dex_pc);
1198*795d594fSAndroid Build Coastguard Worker   }
1199*795d594fSAndroid Build Coastguard Worker }
1200*795d594fSAndroid Build Coastguard Worker 
1201*795d594fSAndroid Build Coastguard Worker // Lazily resolve a method for quick. Called by stub code.
artQuickResolutionTrampoline(ArtMethod * called,mirror::Object * receiver,Thread * self,ArtMethod ** sp)1202*795d594fSAndroid Build Coastguard Worker extern "C" const void* artQuickResolutionTrampoline(
1203*795d594fSAndroid Build Coastguard Worker     ArtMethod* called, mirror::Object* receiver, Thread* self, ArtMethod** sp)
1204*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
1205*795d594fSAndroid Build Coastguard Worker   // The resolution trampoline stashes the resolved method into the callee-save frame to transport
1206*795d594fSAndroid Build Coastguard Worker   // it. Thus, when exiting, the stack cannot be verified (as the resolved method most likely
1207*795d594fSAndroid Build Coastguard Worker   // does not have the same stack layout as the callee-save method).
1208*795d594fSAndroid Build Coastguard Worker   ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
1209*795d594fSAndroid Build Coastguard Worker   // Start new JNI local reference state
1210*795d594fSAndroid Build Coastguard Worker   JNIEnvExt* env = self->GetJniEnv();
1211*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccessUnchecked soa(env);
1212*795d594fSAndroid Build Coastguard Worker   ScopedJniEnvLocalRefState env_state(env);
1213*795d594fSAndroid Build Coastguard Worker   const char* old_cause = self->StartAssertNoThreadSuspension("Quick method resolution set up");
1214*795d594fSAndroid Build Coastguard Worker 
1215*795d594fSAndroid Build Coastguard Worker   // Compute details about the called method (avoid GCs)
1216*795d594fSAndroid Build Coastguard Worker   ClassLinker* linker = Runtime::Current()->GetClassLinker();
1217*795d594fSAndroid Build Coastguard Worker   InvokeType invoke_type;
1218*795d594fSAndroid Build Coastguard Worker   MethodReference called_method(nullptr, 0);
1219*795d594fSAndroid Build Coastguard Worker   const bool called_method_known_on_entry = !called->IsRuntimeMethod();
1220*795d594fSAndroid Build Coastguard Worker   ArtMethod* caller = nullptr;
1221*795d594fSAndroid Build Coastguard Worker   if (!called_method_known_on_entry) {
1222*795d594fSAndroid Build Coastguard Worker     uint32_t dex_pc;
1223*795d594fSAndroid Build Coastguard Worker     caller = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc);
1224*795d594fSAndroid Build Coastguard Worker     called_method.dex_file = caller->GetDexFile();
1225*795d594fSAndroid Build Coastguard Worker 
1226*795d594fSAndroid Build Coastguard Worker     {
1227*795d594fSAndroid Build Coastguard Worker       CodeItemInstructionAccessor accessor(caller->DexInstructions());
1228*795d594fSAndroid Build Coastguard Worker       CHECK_LT(dex_pc, accessor.InsnsSizeInCodeUnits());
1229*795d594fSAndroid Build Coastguard Worker       const Instruction& instr = accessor.InstructionAt(dex_pc);
1230*795d594fSAndroid Build Coastguard Worker       Instruction::Code instr_code = instr.Opcode();
1231*795d594fSAndroid Build Coastguard Worker       bool is_range;
1232*795d594fSAndroid Build Coastguard Worker       switch (instr_code) {
1233*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_DIRECT:
1234*795d594fSAndroid Build Coastguard Worker           invoke_type = kDirect;
1235*795d594fSAndroid Build Coastguard Worker           is_range = false;
1236*795d594fSAndroid Build Coastguard Worker           break;
1237*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_DIRECT_RANGE:
1238*795d594fSAndroid Build Coastguard Worker           invoke_type = kDirect;
1239*795d594fSAndroid Build Coastguard Worker           is_range = true;
1240*795d594fSAndroid Build Coastguard Worker           break;
1241*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_STATIC:
1242*795d594fSAndroid Build Coastguard Worker           invoke_type = kStatic;
1243*795d594fSAndroid Build Coastguard Worker           is_range = false;
1244*795d594fSAndroid Build Coastguard Worker           break;
1245*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_STATIC_RANGE:
1246*795d594fSAndroid Build Coastguard Worker           invoke_type = kStatic;
1247*795d594fSAndroid Build Coastguard Worker           is_range = true;
1248*795d594fSAndroid Build Coastguard Worker           break;
1249*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_SUPER:
1250*795d594fSAndroid Build Coastguard Worker           invoke_type = kSuper;
1251*795d594fSAndroid Build Coastguard Worker           is_range = false;
1252*795d594fSAndroid Build Coastguard Worker           break;
1253*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_SUPER_RANGE:
1254*795d594fSAndroid Build Coastguard Worker           invoke_type = kSuper;
1255*795d594fSAndroid Build Coastguard Worker           is_range = true;
1256*795d594fSAndroid Build Coastguard Worker           break;
1257*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_VIRTUAL:
1258*795d594fSAndroid Build Coastguard Worker           invoke_type = kVirtual;
1259*795d594fSAndroid Build Coastguard Worker           is_range = false;
1260*795d594fSAndroid Build Coastguard Worker           break;
1261*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_VIRTUAL_RANGE:
1262*795d594fSAndroid Build Coastguard Worker           invoke_type = kVirtual;
1263*795d594fSAndroid Build Coastguard Worker           is_range = true;
1264*795d594fSAndroid Build Coastguard Worker           break;
1265*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_INTERFACE:
1266*795d594fSAndroid Build Coastguard Worker           invoke_type = kInterface;
1267*795d594fSAndroid Build Coastguard Worker           is_range = false;
1268*795d594fSAndroid Build Coastguard Worker           break;
1269*795d594fSAndroid Build Coastguard Worker         case Instruction::INVOKE_INTERFACE_RANGE:
1270*795d594fSAndroid Build Coastguard Worker           invoke_type = kInterface;
1271*795d594fSAndroid Build Coastguard Worker           is_range = true;
1272*795d594fSAndroid Build Coastguard Worker           break;
1273*795d594fSAndroid Build Coastguard Worker         default:
1274*795d594fSAndroid Build Coastguard Worker           DumpB74410240DebugData(sp);
1275*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected call into trampoline: " << instr.DumpString(nullptr);
1276*795d594fSAndroid Build Coastguard Worker           UNREACHABLE();
1277*795d594fSAndroid Build Coastguard Worker       }
1278*795d594fSAndroid Build Coastguard Worker       called_method.index = (is_range) ? instr.VRegB_3rc() : instr.VRegB_35c();
1279*795d594fSAndroid Build Coastguard Worker       VLOG(dex) << "Accessed dex file for invoke " << invoke_type << " "
1280*795d594fSAndroid Build Coastguard Worker                 << called_method.index;
1281*795d594fSAndroid Build Coastguard Worker     }
1282*795d594fSAndroid Build Coastguard Worker   } else {
1283*795d594fSAndroid Build Coastguard Worker     invoke_type = kStatic;
1284*795d594fSAndroid Build Coastguard Worker     called_method.dex_file = called->GetDexFile();
1285*795d594fSAndroid Build Coastguard Worker     called_method.index = called->GetDexMethodIndex();
1286*795d594fSAndroid Build Coastguard Worker   }
1287*795d594fSAndroid Build Coastguard Worker   std::string_view shorty =
1288*795d594fSAndroid Build Coastguard Worker       called_method.dex_file->GetMethodShortyView(called_method.GetMethodId());
1289*795d594fSAndroid Build Coastguard Worker   RememberForGcArgumentVisitor visitor(sp, invoke_type == kStatic, shorty, &soa);
1290*795d594fSAndroid Build Coastguard Worker   visitor.VisitArguments();
1291*795d594fSAndroid Build Coastguard Worker   self->EndAssertNoThreadSuspension(old_cause);
1292*795d594fSAndroid Build Coastguard Worker   const bool virtual_or_interface = invoke_type == kVirtual || invoke_type == kInterface;
1293*795d594fSAndroid Build Coastguard Worker   // Resolve method filling in dex cache.
1294*795d594fSAndroid Build Coastguard Worker   if (!called_method_known_on_entry) {
1295*795d594fSAndroid Build Coastguard Worker     StackHandleScope<1> hs(self);
1296*795d594fSAndroid Build Coastguard Worker     mirror::Object* fake_receiver = nullptr;
1297*795d594fSAndroid Build Coastguard Worker     HandleWrapper<mirror::Object> h_receiver(
1298*795d594fSAndroid Build Coastguard Worker         hs.NewHandleWrapper(virtual_or_interface ? &receiver : &fake_receiver));
1299*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(caller->GetDexFile(), called_method.dex_file);
1300*795d594fSAndroid Build Coastguard Worker     called = linker->ResolveMethodWithChecks(called_method.index, caller, invoke_type);
1301*795d594fSAndroid Build Coastguard Worker   }
1302*795d594fSAndroid Build Coastguard Worker   const void* code = nullptr;
1303*795d594fSAndroid Build Coastguard Worker   if (LIKELY(!self->IsExceptionPending())) {
1304*795d594fSAndroid Build Coastguard Worker     // Incompatible class change should have been handled in resolve method.
1305*795d594fSAndroid Build Coastguard Worker     CHECK(!called->CheckIncompatibleClassChange(invoke_type))
1306*795d594fSAndroid Build Coastguard Worker         << called->PrettyMethod() << " " << invoke_type;
1307*795d594fSAndroid Build Coastguard Worker     if (virtual_or_interface || invoke_type == kSuper) {
1308*795d594fSAndroid Build Coastguard Worker       // Refine called method based on receiver for kVirtual/kInterface, and
1309*795d594fSAndroid Build Coastguard Worker       // caller for kSuper.
1310*795d594fSAndroid Build Coastguard Worker       ArtMethod* orig_called = called;
1311*795d594fSAndroid Build Coastguard Worker       if (invoke_type == kVirtual) {
1312*795d594fSAndroid Build Coastguard Worker         CHECK(receiver != nullptr) << invoke_type;
1313*795d594fSAndroid Build Coastguard Worker         called = receiver->GetClass()->FindVirtualMethodForVirtual(called, kRuntimePointerSize);
1314*795d594fSAndroid Build Coastguard Worker       } else if (invoke_type == kInterface) {
1315*795d594fSAndroid Build Coastguard Worker         CHECK(receiver != nullptr) << invoke_type;
1316*795d594fSAndroid Build Coastguard Worker         called = receiver->GetClass()->FindVirtualMethodForInterface(called, kRuntimePointerSize);
1317*795d594fSAndroid Build Coastguard Worker       } else {
1318*795d594fSAndroid Build Coastguard Worker         DCHECK_EQ(invoke_type, kSuper);
1319*795d594fSAndroid Build Coastguard Worker         CHECK(caller != nullptr) << invoke_type;
1320*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::Class> ref_class = linker->LookupResolvedType(
1321*795d594fSAndroid Build Coastguard Worker             caller->GetDexFile()->GetMethodId(called_method.index).class_idx_, caller);
1322*795d594fSAndroid Build Coastguard Worker         if (ref_class->IsInterface()) {
1323*795d594fSAndroid Build Coastguard Worker           called = ref_class->FindVirtualMethodForInterfaceSuper(called, kRuntimePointerSize);
1324*795d594fSAndroid Build Coastguard Worker         } else {
1325*795d594fSAndroid Build Coastguard Worker           called = caller->GetDeclaringClass()->GetSuperClass()->GetVTableEntry(
1326*795d594fSAndroid Build Coastguard Worker               called->GetMethodIndex(), kRuntimePointerSize);
1327*795d594fSAndroid Build Coastguard Worker         }
1328*795d594fSAndroid Build Coastguard Worker       }
1329*795d594fSAndroid Build Coastguard Worker 
1330*795d594fSAndroid Build Coastguard Worker       CHECK(called != nullptr) << orig_called->PrettyMethod() << " "
1331*795d594fSAndroid Build Coastguard Worker                                << mirror::Object::PrettyTypeOf(receiver) << " "
1332*795d594fSAndroid Build Coastguard Worker                                << invoke_type << " " << orig_called->GetVtableIndex();
1333*795d594fSAndroid Build Coastguard Worker     }
1334*795d594fSAndroid Build Coastguard Worker     // Now that we know the actual target, update .bss entry in oat file, if
1335*795d594fSAndroid Build Coastguard Worker     // any.
1336*795d594fSAndroid Build Coastguard Worker     if (!called_method_known_on_entry) {
1337*795d594fSAndroid Build Coastguard Worker       // We only put non copied methods in the BSS. Putting a copy can lead to an
1338*795d594fSAndroid Build Coastguard Worker       // odd situation where the ArtMethod being executed is unrelated to the
1339*795d594fSAndroid Build Coastguard Worker       // receiver of the method.
1340*795d594fSAndroid Build Coastguard Worker       called = called->GetCanonicalMethod();
1341*795d594fSAndroid Build Coastguard Worker       if (invoke_type == kSuper || invoke_type == kInterface || invoke_type == kVirtual) {
1342*795d594fSAndroid Build Coastguard Worker         if (called->GetDexFile() == called_method.dex_file) {
1343*795d594fSAndroid Build Coastguard Worker           called_method.index = called->GetDexMethodIndex();
1344*795d594fSAndroid Build Coastguard Worker         } else {
1345*795d594fSAndroid Build Coastguard Worker           called_method.index = called->FindDexMethodIndexInOtherDexFile(
1346*795d594fSAndroid Build Coastguard Worker               *called_method.dex_file, called_method.index);
1347*795d594fSAndroid Build Coastguard Worker           DCHECK_NE(called_method.index, dex::kDexNoIndex);
1348*795d594fSAndroid Build Coastguard Worker         }
1349*795d594fSAndroid Build Coastguard Worker       }
1350*795d594fSAndroid Build Coastguard Worker       ArtMethod* outer_method = QuickArgumentVisitor::GetOuterMethod(sp);
1351*795d594fSAndroid Build Coastguard Worker       MaybeUpdateBssMethodEntry(called, called_method, outer_method);
1352*795d594fSAndroid Build Coastguard Worker     }
1353*795d594fSAndroid Build Coastguard Worker 
1354*795d594fSAndroid Build Coastguard Worker     // Static invokes need class initialization check but instance invokes can proceed even if
1355*795d594fSAndroid Build Coastguard Worker     // the class is erroneous, i.e. in the edge case of escaping instances of erroneous classes.
1356*795d594fSAndroid Build Coastguard Worker     bool success = true;
1357*795d594fSAndroid Build Coastguard Worker     if (called->StillNeedsClinitCheck()) {
1358*795d594fSAndroid Build Coastguard Worker       // Ensure that the called method's class is initialized.
1359*795d594fSAndroid Build Coastguard Worker       StackHandleScope<1> hs(soa.Self());
1360*795d594fSAndroid Build Coastguard Worker       Handle<mirror::Class> h_called_class = hs.NewHandle(called->GetDeclaringClass());
1361*795d594fSAndroid Build Coastguard Worker       success = linker->EnsureInitialized(soa.Self(), h_called_class, true, true);
1362*795d594fSAndroid Build Coastguard Worker     }
1363*795d594fSAndroid Build Coastguard Worker     if (success) {
1364*795d594fSAndroid Build Coastguard Worker       // When the clinit check is at entry of the AOT/nterp code, we do the clinit check
1365*795d594fSAndroid Build Coastguard Worker       // before doing the suspend check. To ensure the code sees the latest
1366*795d594fSAndroid Build Coastguard Worker       // version of the class (the code doesn't do a read barrier to reduce
1367*795d594fSAndroid Build Coastguard Worker       // size), do a suspend check now.
1368*795d594fSAndroid Build Coastguard Worker       self->CheckSuspend();
1369*795d594fSAndroid Build Coastguard Worker       instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
1370*795d594fSAndroid Build Coastguard Worker       // Check if we need instrumented code here. Since resolution stubs could suspend, it is
1371*795d594fSAndroid Build Coastguard Worker       // possible that we instrumented the entry points after we started executing the resolution
1372*795d594fSAndroid Build Coastguard Worker       // stub.
1373*795d594fSAndroid Build Coastguard Worker       code = instrumentation->GetMaybeInstrumentedCodeForInvoke(called);
1374*795d594fSAndroid Build Coastguard Worker     } else {
1375*795d594fSAndroid Build Coastguard Worker       DCHECK(called->GetDeclaringClass()->IsErroneous());
1376*795d594fSAndroid Build Coastguard Worker       DCHECK(self->IsExceptionPending());
1377*795d594fSAndroid Build Coastguard Worker     }
1378*795d594fSAndroid Build Coastguard Worker   }
1379*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(code == nullptr, self->IsExceptionPending());
1380*795d594fSAndroid Build Coastguard Worker   // Fixup any locally saved objects may have moved during a GC.
1381*795d594fSAndroid Build Coastguard Worker   visitor.FixupReferences();
1382*795d594fSAndroid Build Coastguard Worker   // Place called method in callee-save frame to be placed as first argument to quick method.
1383*795d594fSAndroid Build Coastguard Worker   *sp = called;
1384*795d594fSAndroid Build Coastguard Worker 
1385*795d594fSAndroid Build Coastguard Worker   return code;
1386*795d594fSAndroid Build Coastguard Worker }
1387*795d594fSAndroid Build Coastguard Worker 
1388*795d594fSAndroid Build Coastguard Worker /*
1389*795d594fSAndroid Build Coastguard Worker  * This class uses a couple of observations to unite the different calling conventions through
1390*795d594fSAndroid Build Coastguard Worker  * a few constants.
1391*795d594fSAndroid Build Coastguard Worker  *
1392*795d594fSAndroid Build Coastguard Worker  * 1) Number of registers used for passing is normally even, so counting down has no penalty for
1393*795d594fSAndroid Build Coastguard Worker  *    possible alignment.
1394*795d594fSAndroid Build Coastguard Worker  * 2) Known 64b architectures store 8B units on the stack, both for integral and floating point
1395*795d594fSAndroid Build Coastguard Worker  *    types, so using uintptr_t is OK. Also means that we can use kRegistersNeededX to denote
1396*795d594fSAndroid Build Coastguard Worker  *    when we have to split things
1397*795d594fSAndroid Build Coastguard Worker  * 3) The only soft-float, Arm, is 32b, so no widening needs to be taken into account for floats
1398*795d594fSAndroid Build Coastguard Worker  *    and we can use Int handling directly.
1399*795d594fSAndroid Build Coastguard Worker  * 4) Only 64b architectures widen, and their stack is aligned 8B anyways, so no padding code
1400*795d594fSAndroid Build Coastguard Worker  *    necessary when widening. Also, widening of Ints will take place implicitly, and the
1401*795d594fSAndroid Build Coastguard Worker  *    extension should be compatible with Aarch64, which mandates copying the available bits
1402*795d594fSAndroid Build Coastguard Worker  *    into LSB and leaving the rest unspecified.
1403*795d594fSAndroid Build Coastguard Worker  * 5) Aligning longs and doubles is necessary on arm only, and it's the same in registers and on
1404*795d594fSAndroid Build Coastguard Worker  *    the stack.
1405*795d594fSAndroid Build Coastguard Worker  * 6) There is only little endian.
1406*795d594fSAndroid Build Coastguard Worker  *
1407*795d594fSAndroid Build Coastguard Worker  *
1408*795d594fSAndroid Build Coastguard Worker  * Actual work is supposed to be done in a delegate of the template type. The interface is as
1409*795d594fSAndroid Build Coastguard Worker  * follows:
1410*795d594fSAndroid Build Coastguard Worker  *
1411*795d594fSAndroid Build Coastguard Worker  * void PushGpr(uintptr_t):   Add a value for the next GPR
1412*795d594fSAndroid Build Coastguard Worker  *
1413*795d594fSAndroid Build Coastguard Worker  * void PushFpr4(float):      Add a value for the next FPR of size 32b. Is only called if we need
1414*795d594fSAndroid Build Coastguard Worker  *                            padding, that is, think the architecture is 32b and aligns 64b.
1415*795d594fSAndroid Build Coastguard Worker  *
1416*795d594fSAndroid Build Coastguard Worker  * void PushFpr8(uint64_t):   Push a double. We _will_ call this on 32b, it's the callee's job to
1417*795d594fSAndroid Build Coastguard Worker  *                            split this if necessary. The current state will have aligned, if
1418*795d594fSAndroid Build Coastguard Worker  *                            necessary.
1419*795d594fSAndroid Build Coastguard Worker  *
1420*795d594fSAndroid Build Coastguard Worker  * void PushStack(uintptr_t): Push a value to the stack.
1421*795d594fSAndroid Build Coastguard Worker  */
1422*795d594fSAndroid Build Coastguard Worker template<class T> class BuildNativeCallFrameStateMachine {
1423*795d594fSAndroid Build Coastguard Worker  public:
1424*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNaNBoxing = QuickArgumentVisitor::NaNBoxing();
1425*795d594fSAndroid Build Coastguard Worker #if defined(__arm__)
1426*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAbi = true;
1427*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAfterHardFloat = false;
1428*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeGprArgs = 4;  // 4 arguments passed in GPRs, r0-r3
1429*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeFprArgs = 0;  // 0 arguments passed in FPRs.
1430*795d594fSAndroid Build Coastguard Worker 
1431*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForLong = 2;
1432*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForDouble = 2;
1433*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiRegistersAligned = true;
1434*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiGPRegistersWidened = false;
1435*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignLongOnStack = true;
1436*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignDoubleOnStack = true;
1437*795d594fSAndroid Build Coastguard Worker #elif defined(__aarch64__)
1438*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAbi = false;  // This is a hard float ABI.
1439*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAfterHardFloat = false;
1440*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeGprArgs = 8;  // 8 arguments passed in GPRs.
1441*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeFprArgs = 8;  // 8 arguments passed in FPRs.
1442*795d594fSAndroid Build Coastguard Worker 
1443*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForLong = 1;
1444*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForDouble = 1;
1445*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiRegistersAligned = false;
1446*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiGPRegistersWidened = false;
1447*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignLongOnStack = false;
1448*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignDoubleOnStack = false;
1449*795d594fSAndroid Build Coastguard Worker #elif defined(__riscv)
1450*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAbi = false;
1451*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAfterHardFloat = true;
1452*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeGprArgs = 8;
1453*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeFprArgs = 8;
1454*795d594fSAndroid Build Coastguard Worker 
1455*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForLong = 1;
1456*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForDouble = 1;
1457*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiRegistersAligned = false;
1458*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiGPRegistersWidened = true;
1459*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignLongOnStack = false;
1460*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignDoubleOnStack = false;
1461*795d594fSAndroid Build Coastguard Worker #elif defined(__i386__)
1462*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAbi = false;  // Not using int registers for fp
1463*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAfterHardFloat = false;
1464*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeGprArgs = 0;  // 0 arguments passed in GPRs.
1465*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeFprArgs = 0;  // 0 arguments passed in FPRs.
1466*795d594fSAndroid Build Coastguard Worker 
1467*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForLong = 2;
1468*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForDouble = 2;
1469*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiRegistersAligned = false;  // x86 not using regs, anyways
1470*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiGPRegistersWidened = false;
1471*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignLongOnStack = false;
1472*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignDoubleOnStack = false;
1473*795d594fSAndroid Build Coastguard Worker #elif defined(__x86_64__)
1474*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAbi = false;  // This is a hard float ABI.
1475*795d594fSAndroid Build Coastguard Worker   static constexpr bool kNativeSoftFloatAfterHardFloat = false;
1476*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeGprArgs = 6;  // 6 arguments passed in GPRs.
1477*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumNativeFprArgs = 8;  // 8 arguments passed in FPRs.
1478*795d594fSAndroid Build Coastguard Worker 
1479*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForLong = 1;
1480*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kRegistersNeededForDouble = 1;
1481*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiRegistersAligned = false;
1482*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMultiGPRegistersWidened = false;
1483*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignLongOnStack = false;
1484*795d594fSAndroid Build Coastguard Worker   static constexpr bool kAlignDoubleOnStack = false;
1485*795d594fSAndroid Build Coastguard Worker #else
1486*795d594fSAndroid Build Coastguard Worker #error "Unsupported architecture"
1487*795d594fSAndroid Build Coastguard Worker #endif
1488*795d594fSAndroid Build Coastguard Worker 
1489*795d594fSAndroid Build Coastguard Worker  public:
BuildNativeCallFrameStateMachine(T * delegate)1490*795d594fSAndroid Build Coastguard Worker   explicit BuildNativeCallFrameStateMachine(T* delegate)
1491*795d594fSAndroid Build Coastguard Worker       : gpr_index_(kNumNativeGprArgs),
1492*795d594fSAndroid Build Coastguard Worker         fpr_index_(kNumNativeFprArgs),
1493*795d594fSAndroid Build Coastguard Worker         stack_entries_(0),
1494*795d594fSAndroid Build Coastguard Worker         delegate_(delegate) {
1495*795d594fSAndroid Build Coastguard Worker     // For register alignment, we want to assume that counters (gpr_index_, fpr_index_) are even iff
1496*795d594fSAndroid Build Coastguard Worker     // the next register is even; counting down is just to make the compiler happy...
1497*795d594fSAndroid Build Coastguard Worker     static_assert(kNumNativeGprArgs % 2 == 0U, "Number of native GPR arguments not even");
1498*795d594fSAndroid Build Coastguard Worker     static_assert(kNumNativeFprArgs % 2 == 0U, "Number of native FPR arguments not even");
1499*795d594fSAndroid Build Coastguard Worker   }
1500*795d594fSAndroid Build Coastguard Worker 
~BuildNativeCallFrameStateMachine()1501*795d594fSAndroid Build Coastguard Worker   virtual ~BuildNativeCallFrameStateMachine() {}
1502*795d594fSAndroid Build Coastguard Worker 
HavePointerGpr() const1503*795d594fSAndroid Build Coastguard Worker   bool HavePointerGpr() const {
1504*795d594fSAndroid Build Coastguard Worker     return gpr_index_ > 0;
1505*795d594fSAndroid Build Coastguard Worker   }
1506*795d594fSAndroid Build Coastguard Worker 
AdvancePointer(const void * val)1507*795d594fSAndroid Build Coastguard Worker   void AdvancePointer(const void* val) {
1508*795d594fSAndroid Build Coastguard Worker     if (HavePointerGpr()) {
1509*795d594fSAndroid Build Coastguard Worker       gpr_index_--;
1510*795d594fSAndroid Build Coastguard Worker       PushGpr(reinterpret_cast<uintptr_t>(val));
1511*795d594fSAndroid Build Coastguard Worker     } else {
1512*795d594fSAndroid Build Coastguard Worker       stack_entries_++;  // TODO: have a field for pointer length as multiple of 32b
1513*795d594fSAndroid Build Coastguard Worker       PushStack(reinterpret_cast<uintptr_t>(val));
1514*795d594fSAndroid Build Coastguard Worker       gpr_index_ = 0;
1515*795d594fSAndroid Build Coastguard Worker     }
1516*795d594fSAndroid Build Coastguard Worker   }
1517*795d594fSAndroid Build Coastguard Worker 
HaveIntGpr() const1518*795d594fSAndroid Build Coastguard Worker   bool HaveIntGpr() const {
1519*795d594fSAndroid Build Coastguard Worker     return gpr_index_ > 0;
1520*795d594fSAndroid Build Coastguard Worker   }
1521*795d594fSAndroid Build Coastguard Worker 
AdvanceInt(uint32_t val)1522*795d594fSAndroid Build Coastguard Worker   void AdvanceInt(uint32_t val) {
1523*795d594fSAndroid Build Coastguard Worker     if (HaveIntGpr()) {
1524*795d594fSAndroid Build Coastguard Worker       gpr_index_--;
1525*795d594fSAndroid Build Coastguard Worker       if (kMultiGPRegistersWidened) {
1526*795d594fSAndroid Build Coastguard Worker         DCHECK_EQ(sizeof(uintptr_t), sizeof(int64_t));
1527*795d594fSAndroid Build Coastguard Worker         PushGpr(static_cast<int64_t>(bit_cast<int32_t, uint32_t>(val)));
1528*795d594fSAndroid Build Coastguard Worker       } else {
1529*795d594fSAndroid Build Coastguard Worker         PushGpr(val);
1530*795d594fSAndroid Build Coastguard Worker       }
1531*795d594fSAndroid Build Coastguard Worker     } else {
1532*795d594fSAndroid Build Coastguard Worker       stack_entries_++;
1533*795d594fSAndroid Build Coastguard Worker       if (kMultiGPRegistersWidened) {
1534*795d594fSAndroid Build Coastguard Worker         DCHECK_EQ(sizeof(uintptr_t), sizeof(int64_t));
1535*795d594fSAndroid Build Coastguard Worker         PushStack(static_cast<int64_t>(bit_cast<int32_t, uint32_t>(val)));
1536*795d594fSAndroid Build Coastguard Worker       } else {
1537*795d594fSAndroid Build Coastguard Worker         PushStack(val);
1538*795d594fSAndroid Build Coastguard Worker       }
1539*795d594fSAndroid Build Coastguard Worker       gpr_index_ = 0;
1540*795d594fSAndroid Build Coastguard Worker     }
1541*795d594fSAndroid Build Coastguard Worker   }
1542*795d594fSAndroid Build Coastguard Worker 
HaveLongGpr() const1543*795d594fSAndroid Build Coastguard Worker   bool HaveLongGpr() const {
1544*795d594fSAndroid Build Coastguard Worker     return gpr_index_ >= kRegistersNeededForLong + (LongGprNeedsPadding() ? 1 : 0);
1545*795d594fSAndroid Build Coastguard Worker   }
1546*795d594fSAndroid Build Coastguard Worker 
LongGprNeedsPadding() const1547*795d594fSAndroid Build Coastguard Worker   bool LongGprNeedsPadding() const {
1548*795d594fSAndroid Build Coastguard Worker     return kRegistersNeededForLong > 1 &&     // only pad when using multiple registers
1549*795d594fSAndroid Build Coastguard Worker         kAlignLongOnStack &&                  // and when it needs alignment
1550*795d594fSAndroid Build Coastguard Worker         (gpr_index_ & 1) == 1;                // counter is odd, see constructor
1551*795d594fSAndroid Build Coastguard Worker   }
1552*795d594fSAndroid Build Coastguard Worker 
LongStackNeedsPadding() const1553*795d594fSAndroid Build Coastguard Worker   bool LongStackNeedsPadding() const {
1554*795d594fSAndroid Build Coastguard Worker     return kRegistersNeededForLong > 1 &&     // only pad when using multiple registers
1555*795d594fSAndroid Build Coastguard Worker         kAlignLongOnStack &&                  // and when it needs 8B alignment
1556*795d594fSAndroid Build Coastguard Worker         (stack_entries_ & 1) == 1;            // counter is odd
1557*795d594fSAndroid Build Coastguard Worker   }
1558*795d594fSAndroid Build Coastguard Worker 
AdvanceLong(uint64_t val)1559*795d594fSAndroid Build Coastguard Worker   void AdvanceLong(uint64_t val) {
1560*795d594fSAndroid Build Coastguard Worker     if (HaveLongGpr()) {
1561*795d594fSAndroid Build Coastguard Worker       if (LongGprNeedsPadding()) {
1562*795d594fSAndroid Build Coastguard Worker         PushGpr(0);
1563*795d594fSAndroid Build Coastguard Worker         gpr_index_--;
1564*795d594fSAndroid Build Coastguard Worker       }
1565*795d594fSAndroid Build Coastguard Worker       if (kRegistersNeededForLong == 1) {
1566*795d594fSAndroid Build Coastguard Worker         PushGpr(static_cast<uintptr_t>(val));
1567*795d594fSAndroid Build Coastguard Worker       } else {
1568*795d594fSAndroid Build Coastguard Worker         PushGpr(static_cast<uintptr_t>(val & 0xFFFFFFFF));
1569*795d594fSAndroid Build Coastguard Worker         PushGpr(static_cast<uintptr_t>((val >> 32) & 0xFFFFFFFF));
1570*795d594fSAndroid Build Coastguard Worker       }
1571*795d594fSAndroid Build Coastguard Worker       gpr_index_ -= kRegistersNeededForLong;
1572*795d594fSAndroid Build Coastguard Worker     } else {
1573*795d594fSAndroid Build Coastguard Worker       if (LongStackNeedsPadding()) {
1574*795d594fSAndroid Build Coastguard Worker         PushStack(0);
1575*795d594fSAndroid Build Coastguard Worker         stack_entries_++;
1576*795d594fSAndroid Build Coastguard Worker       }
1577*795d594fSAndroid Build Coastguard Worker       if (kRegistersNeededForLong == 1) {
1578*795d594fSAndroid Build Coastguard Worker         PushStack(static_cast<uintptr_t>(val));
1579*795d594fSAndroid Build Coastguard Worker         stack_entries_++;
1580*795d594fSAndroid Build Coastguard Worker       } else {
1581*795d594fSAndroid Build Coastguard Worker         PushStack(static_cast<uintptr_t>(val & 0xFFFFFFFF));
1582*795d594fSAndroid Build Coastguard Worker         PushStack(static_cast<uintptr_t>((val >> 32) & 0xFFFFFFFF));
1583*795d594fSAndroid Build Coastguard Worker         stack_entries_ += 2;
1584*795d594fSAndroid Build Coastguard Worker       }
1585*795d594fSAndroid Build Coastguard Worker       gpr_index_ = 0;
1586*795d594fSAndroid Build Coastguard Worker     }
1587*795d594fSAndroid Build Coastguard Worker   }
1588*795d594fSAndroid Build Coastguard Worker 
HaveFloatFpr() const1589*795d594fSAndroid Build Coastguard Worker   bool HaveFloatFpr() const {
1590*795d594fSAndroid Build Coastguard Worker     return fpr_index_ > 0;
1591*795d594fSAndroid Build Coastguard Worker   }
1592*795d594fSAndroid Build Coastguard Worker 
AdvanceFloat(uint32_t val)1593*795d594fSAndroid Build Coastguard Worker   void AdvanceFloat(uint32_t val) {
1594*795d594fSAndroid Build Coastguard Worker     if (kNativeSoftFloatAbi) {
1595*795d594fSAndroid Build Coastguard Worker       AdvanceInt(val);
1596*795d594fSAndroid Build Coastguard Worker     } else if (HaveFloatFpr()) {
1597*795d594fSAndroid Build Coastguard Worker       fpr_index_--;
1598*795d594fSAndroid Build Coastguard Worker       if (kRegistersNeededForDouble == 1) {
1599*795d594fSAndroid Build Coastguard Worker         if (kNaNBoxing) {
1600*795d594fSAndroid Build Coastguard Worker           // NaN boxing: no widening, just use the bits, but reset upper bits to 1s.
1601*795d594fSAndroid Build Coastguard Worker           // See e.g. RISC-V manual, D extension, section "NaN Boxing of Narrower Values".
1602*795d594fSAndroid Build Coastguard Worker           PushFpr8(UINT64_C(0xFFFFFFFF00000000) | static_cast<uint64_t>(val));
1603*795d594fSAndroid Build Coastguard Worker         } else {
1604*795d594fSAndroid Build Coastguard Worker           // No widening, just use the bits.
1605*795d594fSAndroid Build Coastguard Worker           PushFpr8(static_cast<uint64_t>(val));
1606*795d594fSAndroid Build Coastguard Worker         }
1607*795d594fSAndroid Build Coastguard Worker       } else {
1608*795d594fSAndroid Build Coastguard Worker         PushFpr4(val);
1609*795d594fSAndroid Build Coastguard Worker       }
1610*795d594fSAndroid Build Coastguard Worker     } else if (kNativeSoftFloatAfterHardFloat) {
1611*795d594fSAndroid Build Coastguard Worker       // After using FP arg registers, pass FP args in general purpose registers or on the stack.
1612*795d594fSAndroid Build Coastguard Worker       AdvanceInt(val);
1613*795d594fSAndroid Build Coastguard Worker     } else {
1614*795d594fSAndroid Build Coastguard Worker       stack_entries_++;
1615*795d594fSAndroid Build Coastguard Worker       PushStack(static_cast<uintptr_t>(val));
1616*795d594fSAndroid Build Coastguard Worker       fpr_index_ = 0;
1617*795d594fSAndroid Build Coastguard Worker     }
1618*795d594fSAndroid Build Coastguard Worker   }
1619*795d594fSAndroid Build Coastguard Worker 
HaveDoubleFpr() const1620*795d594fSAndroid Build Coastguard Worker   bool HaveDoubleFpr() const {
1621*795d594fSAndroid Build Coastguard Worker     return fpr_index_ >= kRegistersNeededForDouble + (DoubleFprNeedsPadding() ? 1 : 0);
1622*795d594fSAndroid Build Coastguard Worker   }
1623*795d594fSAndroid Build Coastguard Worker 
DoubleFprNeedsPadding() const1624*795d594fSAndroid Build Coastguard Worker   bool DoubleFprNeedsPadding() const {
1625*795d594fSAndroid Build Coastguard Worker     return kRegistersNeededForDouble > 1 &&     // only pad when using multiple registers
1626*795d594fSAndroid Build Coastguard Worker         kAlignDoubleOnStack &&                  // and when it needs alignment
1627*795d594fSAndroid Build Coastguard Worker         (fpr_index_ & 1) == 1;                  // counter is odd, see constructor
1628*795d594fSAndroid Build Coastguard Worker   }
1629*795d594fSAndroid Build Coastguard Worker 
DoubleStackNeedsPadding() const1630*795d594fSAndroid Build Coastguard Worker   bool DoubleStackNeedsPadding() const {
1631*795d594fSAndroid Build Coastguard Worker     return kRegistersNeededForDouble > 1 &&     // only pad when using multiple registers
1632*795d594fSAndroid Build Coastguard Worker         kAlignDoubleOnStack &&                  // and when it needs 8B alignment
1633*795d594fSAndroid Build Coastguard Worker         (stack_entries_ & 1) == 1;              // counter is odd
1634*795d594fSAndroid Build Coastguard Worker   }
1635*795d594fSAndroid Build Coastguard Worker 
AdvanceDouble(uint64_t val)1636*795d594fSAndroid Build Coastguard Worker   void AdvanceDouble(uint64_t val) {
1637*795d594fSAndroid Build Coastguard Worker     if (kNativeSoftFloatAbi) {
1638*795d594fSAndroid Build Coastguard Worker       AdvanceLong(val);
1639*795d594fSAndroid Build Coastguard Worker     } else if (HaveDoubleFpr()) {
1640*795d594fSAndroid Build Coastguard Worker       if (DoubleFprNeedsPadding()) {
1641*795d594fSAndroid Build Coastguard Worker         PushFpr4(0);
1642*795d594fSAndroid Build Coastguard Worker         fpr_index_--;
1643*795d594fSAndroid Build Coastguard Worker       }
1644*795d594fSAndroid Build Coastguard Worker       PushFpr8(val);
1645*795d594fSAndroid Build Coastguard Worker       fpr_index_ -= kRegistersNeededForDouble;
1646*795d594fSAndroid Build Coastguard Worker     } else if (kNativeSoftFloatAfterHardFloat) {
1647*795d594fSAndroid Build Coastguard Worker       // After using FP arg registers, pass FP args in general purpose registers or on the stack.
1648*795d594fSAndroid Build Coastguard Worker       AdvanceLong(val);
1649*795d594fSAndroid Build Coastguard Worker     } else {
1650*795d594fSAndroid Build Coastguard Worker       if (DoubleStackNeedsPadding()) {
1651*795d594fSAndroid Build Coastguard Worker         PushStack(0);
1652*795d594fSAndroid Build Coastguard Worker         stack_entries_++;
1653*795d594fSAndroid Build Coastguard Worker       }
1654*795d594fSAndroid Build Coastguard Worker       if (kRegistersNeededForDouble == 1) {
1655*795d594fSAndroid Build Coastguard Worker         PushStack(static_cast<uintptr_t>(val));
1656*795d594fSAndroid Build Coastguard Worker         stack_entries_++;
1657*795d594fSAndroid Build Coastguard Worker       } else {
1658*795d594fSAndroid Build Coastguard Worker         PushStack(static_cast<uintptr_t>(val & 0xFFFFFFFF));
1659*795d594fSAndroid Build Coastguard Worker         PushStack(static_cast<uintptr_t>((val >> 32) & 0xFFFFFFFF));
1660*795d594fSAndroid Build Coastguard Worker         stack_entries_ += 2;
1661*795d594fSAndroid Build Coastguard Worker       }
1662*795d594fSAndroid Build Coastguard Worker       fpr_index_ = 0;
1663*795d594fSAndroid Build Coastguard Worker     }
1664*795d594fSAndroid Build Coastguard Worker   }
1665*795d594fSAndroid Build Coastguard Worker 
GetStackEntries() const1666*795d594fSAndroid Build Coastguard Worker   uint32_t GetStackEntries() const {
1667*795d594fSAndroid Build Coastguard Worker     return stack_entries_;
1668*795d594fSAndroid Build Coastguard Worker   }
1669*795d594fSAndroid Build Coastguard Worker 
GetNumberOfUsedGprs() const1670*795d594fSAndroid Build Coastguard Worker   uint32_t GetNumberOfUsedGprs() const {
1671*795d594fSAndroid Build Coastguard Worker     return kNumNativeGprArgs - gpr_index_;
1672*795d594fSAndroid Build Coastguard Worker   }
1673*795d594fSAndroid Build Coastguard Worker 
GetNumberOfUsedFprs() const1674*795d594fSAndroid Build Coastguard Worker   uint32_t GetNumberOfUsedFprs() const {
1675*795d594fSAndroid Build Coastguard Worker     return kNumNativeFprArgs - fpr_index_;
1676*795d594fSAndroid Build Coastguard Worker   }
1677*795d594fSAndroid Build Coastguard Worker 
1678*795d594fSAndroid Build Coastguard Worker  private:
PushGpr(uintptr_t val)1679*795d594fSAndroid Build Coastguard Worker   void PushGpr(uintptr_t val) {
1680*795d594fSAndroid Build Coastguard Worker     delegate_->PushGpr(val);
1681*795d594fSAndroid Build Coastguard Worker   }
PushFpr4(float val)1682*795d594fSAndroid Build Coastguard Worker   void PushFpr4(float val) {
1683*795d594fSAndroid Build Coastguard Worker     delegate_->PushFpr4(val);
1684*795d594fSAndroid Build Coastguard Worker   }
PushFpr8(uint64_t val)1685*795d594fSAndroid Build Coastguard Worker   void PushFpr8(uint64_t val) {
1686*795d594fSAndroid Build Coastguard Worker     delegate_->PushFpr8(val);
1687*795d594fSAndroid Build Coastguard Worker   }
PushStack(uintptr_t val)1688*795d594fSAndroid Build Coastguard Worker   void PushStack(uintptr_t val) {
1689*795d594fSAndroid Build Coastguard Worker     delegate_->PushStack(val);
1690*795d594fSAndroid Build Coastguard Worker   }
1691*795d594fSAndroid Build Coastguard Worker 
1692*795d594fSAndroid Build Coastguard Worker   uint32_t gpr_index_;      // Number of free GPRs
1693*795d594fSAndroid Build Coastguard Worker   uint32_t fpr_index_;      // Number of free FPRs
1694*795d594fSAndroid Build Coastguard Worker   uint32_t stack_entries_;  // Stack entries are in multiples of 32b, as floats are usually not
1695*795d594fSAndroid Build Coastguard Worker                             // extended
1696*795d594fSAndroid Build Coastguard Worker   T* const delegate_;             // What Push implementation gets called
1697*795d594fSAndroid Build Coastguard Worker };
1698*795d594fSAndroid Build Coastguard Worker 
1699*795d594fSAndroid Build Coastguard Worker // Computes the sizes of register stacks and call stack area. Handling of references can be extended
1700*795d594fSAndroid Build Coastguard Worker // in subclasses.
1701*795d594fSAndroid Build Coastguard Worker //
1702*795d594fSAndroid Build Coastguard Worker // To handle native pointers, use "L" in the shorty for an object reference, which simulates
1703*795d594fSAndroid Build Coastguard Worker // them with handles.
1704*795d594fSAndroid Build Coastguard Worker class ComputeNativeCallFrameSize {
1705*795d594fSAndroid Build Coastguard Worker  public:
ComputeNativeCallFrameSize()1706*795d594fSAndroid Build Coastguard Worker   ComputeNativeCallFrameSize() : num_stack_entries_(0) {}
1707*795d594fSAndroid Build Coastguard Worker 
~ComputeNativeCallFrameSize()1708*795d594fSAndroid Build Coastguard Worker   virtual ~ComputeNativeCallFrameSize() {}
1709*795d594fSAndroid Build Coastguard Worker 
GetStackSize() const1710*795d594fSAndroid Build Coastguard Worker   uint32_t GetStackSize() const {
1711*795d594fSAndroid Build Coastguard Worker     return num_stack_entries_ * sizeof(uintptr_t);
1712*795d594fSAndroid Build Coastguard Worker   }
1713*795d594fSAndroid Build Coastguard Worker 
LayoutStackArgs(uint8_t * sp8) const1714*795d594fSAndroid Build Coastguard Worker   uint8_t* LayoutStackArgs(uint8_t* sp8) const {
1715*795d594fSAndroid Build Coastguard Worker     sp8 -= GetStackSize();
1716*795d594fSAndroid Build Coastguard Worker     // Align by kStackAlignment; it is at least as strict as native stack alignment.
1717*795d594fSAndroid Build Coastguard Worker     sp8 = reinterpret_cast<uint8_t*>(RoundDown(reinterpret_cast<uintptr_t>(sp8), kStackAlignment));
1718*795d594fSAndroid Build Coastguard Worker     return sp8;
1719*795d594fSAndroid Build Coastguard Worker   }
1720*795d594fSAndroid Build Coastguard Worker 
WalkHeader(BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize> * sm)1721*795d594fSAndroid Build Coastguard Worker   virtual void WalkHeader(
1722*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm)
1723*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {}
1724*795d594fSAndroid Build Coastguard Worker 
Walk(std::string_view shorty)1725*795d594fSAndroid Build Coastguard Worker   void Walk(std::string_view shorty) REQUIRES_SHARED(Locks::mutator_lock_) {
1726*795d594fSAndroid Build Coastguard Worker     BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize> sm(this);
1727*795d594fSAndroid Build Coastguard Worker 
1728*795d594fSAndroid Build Coastguard Worker     WalkHeader(&sm);
1729*795d594fSAndroid Build Coastguard Worker 
1730*795d594fSAndroid Build Coastguard Worker     for (char c : shorty.substr(1u)) {
1731*795d594fSAndroid Build Coastguard Worker       Primitive::Type cur_type_ = Primitive::GetType(c);
1732*795d594fSAndroid Build Coastguard Worker       switch (cur_type_) {
1733*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimNot:
1734*795d594fSAndroid Build Coastguard Worker           sm.AdvancePointer(nullptr);
1735*795d594fSAndroid Build Coastguard Worker           break;
1736*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimBoolean:
1737*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimByte:
1738*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimChar:
1739*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimShort:
1740*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimInt:
1741*795d594fSAndroid Build Coastguard Worker           sm.AdvanceInt(0);
1742*795d594fSAndroid Build Coastguard Worker           break;
1743*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimFloat:
1744*795d594fSAndroid Build Coastguard Worker           sm.AdvanceFloat(0);
1745*795d594fSAndroid Build Coastguard Worker           break;
1746*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimDouble:
1747*795d594fSAndroid Build Coastguard Worker           sm.AdvanceDouble(0);
1748*795d594fSAndroid Build Coastguard Worker           break;
1749*795d594fSAndroid Build Coastguard Worker         case Primitive::kPrimLong:
1750*795d594fSAndroid Build Coastguard Worker           sm.AdvanceLong(0);
1751*795d594fSAndroid Build Coastguard Worker           break;
1752*795d594fSAndroid Build Coastguard Worker         default:
1753*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unexpected type: " << cur_type_ << " in " << shorty;
1754*795d594fSAndroid Build Coastguard Worker           UNREACHABLE();
1755*795d594fSAndroid Build Coastguard Worker       }
1756*795d594fSAndroid Build Coastguard Worker     }
1757*795d594fSAndroid Build Coastguard Worker 
1758*795d594fSAndroid Build Coastguard Worker     num_stack_entries_ = sm.GetStackEntries();
1759*795d594fSAndroid Build Coastguard Worker   }
1760*795d594fSAndroid Build Coastguard Worker 
PushGpr(uintptr_t)1761*795d594fSAndroid Build Coastguard Worker   void PushGpr(uintptr_t /* val */) {
1762*795d594fSAndroid Build Coastguard Worker     // not optimizing registers, yet
1763*795d594fSAndroid Build Coastguard Worker   }
1764*795d594fSAndroid Build Coastguard Worker 
PushFpr4(float)1765*795d594fSAndroid Build Coastguard Worker   void PushFpr4(float /* val */) {
1766*795d594fSAndroid Build Coastguard Worker     // not optimizing registers, yet
1767*795d594fSAndroid Build Coastguard Worker   }
1768*795d594fSAndroid Build Coastguard Worker 
PushFpr8(uint64_t)1769*795d594fSAndroid Build Coastguard Worker   void PushFpr8(uint64_t /* val */) {
1770*795d594fSAndroid Build Coastguard Worker     // not optimizing registers, yet
1771*795d594fSAndroid Build Coastguard Worker   }
1772*795d594fSAndroid Build Coastguard Worker 
PushStack(uintptr_t)1773*795d594fSAndroid Build Coastguard Worker   void PushStack(uintptr_t /* val */) {
1774*795d594fSAndroid Build Coastguard Worker     // counting is already done in the superclass
1775*795d594fSAndroid Build Coastguard Worker   }
1776*795d594fSAndroid Build Coastguard Worker 
1777*795d594fSAndroid Build Coastguard Worker  protected:
1778*795d594fSAndroid Build Coastguard Worker   uint32_t num_stack_entries_;
1779*795d594fSAndroid Build Coastguard Worker };
1780*795d594fSAndroid Build Coastguard Worker 
1781*795d594fSAndroid Build Coastguard Worker class ComputeGenericJniFrameSize final : public ComputeNativeCallFrameSize {
1782*795d594fSAndroid Build Coastguard Worker  public:
ComputeGenericJniFrameSize(bool critical_native)1783*795d594fSAndroid Build Coastguard Worker   explicit ComputeGenericJniFrameSize(bool critical_native)
1784*795d594fSAndroid Build Coastguard Worker     : critical_native_(critical_native) {}
1785*795d594fSAndroid Build Coastguard Worker 
ComputeLayout(ArtMethod ** managed_sp,std::string_view shorty)1786*795d594fSAndroid Build Coastguard Worker   uintptr_t* ComputeLayout(ArtMethod** managed_sp, std::string_view shorty)
1787*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
1788*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
1789*795d594fSAndroid Build Coastguard Worker 
1790*795d594fSAndroid Build Coastguard Worker     Walk(shorty);
1791*795d594fSAndroid Build Coastguard Worker 
1792*795d594fSAndroid Build Coastguard Worker     // Add space for cookie.
1793*795d594fSAndroid Build Coastguard Worker     DCHECK_ALIGNED(managed_sp, sizeof(uintptr_t));
1794*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(uintptr_t) >= sizeof(jni::LRTSegmentState));
1795*795d594fSAndroid Build Coastguard Worker     uint8_t* sp8 = reinterpret_cast<uint8_t*>(managed_sp) - sizeof(uintptr_t);
1796*795d594fSAndroid Build Coastguard Worker 
1797*795d594fSAndroid Build Coastguard Worker     // Layout stack arguments.
1798*795d594fSAndroid Build Coastguard Worker     sp8 = LayoutStackArgs(sp8);
1799*795d594fSAndroid Build Coastguard Worker 
1800*795d594fSAndroid Build Coastguard Worker     // Return the new bottom.
1801*795d594fSAndroid Build Coastguard Worker     DCHECK_ALIGNED(sp8, sizeof(uintptr_t));
1802*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<uintptr_t*>(sp8);
1803*795d594fSAndroid Build Coastguard Worker   }
1804*795d594fSAndroid Build Coastguard Worker 
GetStartGprRegs(uintptr_t * reserved_area)1805*795d594fSAndroid Build Coastguard Worker   static uintptr_t* GetStartGprRegs(uintptr_t* reserved_area) {
1806*795d594fSAndroid Build Coastguard Worker     return reserved_area;
1807*795d594fSAndroid Build Coastguard Worker   }
1808*795d594fSAndroid Build Coastguard Worker 
GetStartFprRegs(uintptr_t * reserved_area)1809*795d594fSAndroid Build Coastguard Worker   static uint32_t* GetStartFprRegs(uintptr_t* reserved_area) {
1810*795d594fSAndroid Build Coastguard Worker     constexpr size_t num_gprs =
1811*795d594fSAndroid Build Coastguard Worker         BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>::kNumNativeGprArgs;
1812*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<uint32_t*>(GetStartGprRegs(reserved_area) + num_gprs);
1813*795d594fSAndroid Build Coastguard Worker   }
1814*795d594fSAndroid Build Coastguard Worker 
GetHiddenArgSlot(uintptr_t * reserved_area)1815*795d594fSAndroid Build Coastguard Worker   static uintptr_t* GetHiddenArgSlot(uintptr_t* reserved_area) {
1816*795d594fSAndroid Build Coastguard Worker     // Note: `num_fprs` is 0 on architectures where sizeof(uintptr_t) does not match the
1817*795d594fSAndroid Build Coastguard Worker     // FP register size (it is actually 0 on all supported 32-bit architectures).
1818*795d594fSAndroid Build Coastguard Worker     constexpr size_t num_fprs =
1819*795d594fSAndroid Build Coastguard Worker         BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>::kNumNativeFprArgs;
1820*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<uintptr_t*>(GetStartFprRegs(reserved_area)) + num_fprs;
1821*795d594fSAndroid Build Coastguard Worker   }
1822*795d594fSAndroid Build Coastguard Worker 
GetOutArgsSpSlot(uintptr_t * reserved_area)1823*795d594fSAndroid Build Coastguard Worker   static uintptr_t* GetOutArgsSpSlot(uintptr_t* reserved_area) {
1824*795d594fSAndroid Build Coastguard Worker     return GetHiddenArgSlot(reserved_area) + 1;
1825*795d594fSAndroid Build Coastguard Worker   }
1826*795d594fSAndroid Build Coastguard Worker 
1827*795d594fSAndroid Build Coastguard Worker   // Add JNIEnv* and jobj/jclass before the shorty-derived elements.
1828*795d594fSAndroid Build Coastguard Worker   void WalkHeader(BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm) override
1829*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
1830*795d594fSAndroid Build Coastguard Worker 
1831*795d594fSAndroid Build Coastguard Worker  private:
1832*795d594fSAndroid Build Coastguard Worker   const bool critical_native_;
1833*795d594fSAndroid Build Coastguard Worker };
1834*795d594fSAndroid Build Coastguard Worker 
WalkHeader(BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize> * sm)1835*795d594fSAndroid Build Coastguard Worker void ComputeGenericJniFrameSize::WalkHeader(
1836*795d594fSAndroid Build Coastguard Worker     BuildNativeCallFrameStateMachine<ComputeNativeCallFrameSize>* sm) {
1837*795d594fSAndroid Build Coastguard Worker   // First 2 parameters are always excluded for @CriticalNative.
1838*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(critical_native_)) {
1839*795d594fSAndroid Build Coastguard Worker     return;
1840*795d594fSAndroid Build Coastguard Worker   }
1841*795d594fSAndroid Build Coastguard Worker 
1842*795d594fSAndroid Build Coastguard Worker   // JNIEnv
1843*795d594fSAndroid Build Coastguard Worker   sm->AdvancePointer(nullptr);
1844*795d594fSAndroid Build Coastguard Worker 
1845*795d594fSAndroid Build Coastguard Worker   // Class object or this as first argument
1846*795d594fSAndroid Build Coastguard Worker   sm->AdvancePointer(nullptr);
1847*795d594fSAndroid Build Coastguard Worker }
1848*795d594fSAndroid Build Coastguard Worker 
1849*795d594fSAndroid Build Coastguard Worker // Class to push values to three separate regions. Used to fill the native call part. Adheres to
1850*795d594fSAndroid Build Coastguard Worker // the template requirements of BuildGenericJniFrameStateMachine.
1851*795d594fSAndroid Build Coastguard Worker class FillNativeCall {
1852*795d594fSAndroid Build Coastguard Worker  public:
FillNativeCall(uintptr_t * gpr_regs,uint32_t * fpr_regs,uintptr_t * stack_args)1853*795d594fSAndroid Build Coastguard Worker   FillNativeCall(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args) :
1854*795d594fSAndroid Build Coastguard Worker       cur_gpr_reg_(gpr_regs), cur_fpr_reg_(fpr_regs), cur_stack_arg_(stack_args) {}
1855*795d594fSAndroid Build Coastguard Worker 
~FillNativeCall()1856*795d594fSAndroid Build Coastguard Worker   virtual ~FillNativeCall() {}
1857*795d594fSAndroid Build Coastguard Worker 
Reset(uintptr_t * gpr_regs,uint32_t * fpr_regs,uintptr_t * stack_args)1858*795d594fSAndroid Build Coastguard Worker   void Reset(uintptr_t* gpr_regs, uint32_t* fpr_regs, uintptr_t* stack_args) {
1859*795d594fSAndroid Build Coastguard Worker     cur_gpr_reg_ = gpr_regs;
1860*795d594fSAndroid Build Coastguard Worker     cur_fpr_reg_ = fpr_regs;
1861*795d594fSAndroid Build Coastguard Worker     cur_stack_arg_ = stack_args;
1862*795d594fSAndroid Build Coastguard Worker   }
1863*795d594fSAndroid Build Coastguard Worker 
PushGpr(uintptr_t val)1864*795d594fSAndroid Build Coastguard Worker   void PushGpr(uintptr_t val) {
1865*795d594fSAndroid Build Coastguard Worker     *cur_gpr_reg_ = val;
1866*795d594fSAndroid Build Coastguard Worker     cur_gpr_reg_++;
1867*795d594fSAndroid Build Coastguard Worker   }
1868*795d594fSAndroid Build Coastguard Worker 
PushFpr4(float val)1869*795d594fSAndroid Build Coastguard Worker   void PushFpr4(float val) {
1870*795d594fSAndroid Build Coastguard Worker     *cur_fpr_reg_ = val;
1871*795d594fSAndroid Build Coastguard Worker     cur_fpr_reg_++;
1872*795d594fSAndroid Build Coastguard Worker   }
1873*795d594fSAndroid Build Coastguard Worker 
PushFpr8(uint64_t val)1874*795d594fSAndroid Build Coastguard Worker   void PushFpr8(uint64_t val) {
1875*795d594fSAndroid Build Coastguard Worker     uint64_t* tmp = reinterpret_cast<uint64_t*>(cur_fpr_reg_);
1876*795d594fSAndroid Build Coastguard Worker     *tmp = val;
1877*795d594fSAndroid Build Coastguard Worker     cur_fpr_reg_ += 2;
1878*795d594fSAndroid Build Coastguard Worker   }
1879*795d594fSAndroid Build Coastguard Worker 
PushStack(uintptr_t val)1880*795d594fSAndroid Build Coastguard Worker   void PushStack(uintptr_t val) {
1881*795d594fSAndroid Build Coastguard Worker     *cur_stack_arg_ = val;
1882*795d594fSAndroid Build Coastguard Worker     cur_stack_arg_++;
1883*795d594fSAndroid Build Coastguard Worker   }
1884*795d594fSAndroid Build Coastguard Worker 
1885*795d594fSAndroid Build Coastguard Worker  private:
1886*795d594fSAndroid Build Coastguard Worker   uintptr_t* cur_gpr_reg_;
1887*795d594fSAndroid Build Coastguard Worker   uint32_t* cur_fpr_reg_;
1888*795d594fSAndroid Build Coastguard Worker   uintptr_t* cur_stack_arg_;
1889*795d594fSAndroid Build Coastguard Worker };
1890*795d594fSAndroid Build Coastguard Worker 
1891*795d594fSAndroid Build Coastguard Worker // Visits arguments on the stack placing them into a region lower down the stack for the benefit
1892*795d594fSAndroid Build Coastguard Worker // of transitioning into native code.
1893*795d594fSAndroid Build Coastguard Worker class BuildGenericJniFrameVisitor final : public QuickArgumentVisitor {
1894*795d594fSAndroid Build Coastguard Worker  public:
BuildGenericJniFrameVisitor(Thread * self,bool is_static,bool critical_native,std::string_view shorty,ArtMethod ** managed_sp,uintptr_t * reserved_area)1895*795d594fSAndroid Build Coastguard Worker   BuildGenericJniFrameVisitor(Thread* self,
1896*795d594fSAndroid Build Coastguard Worker                               bool is_static,
1897*795d594fSAndroid Build Coastguard Worker                               bool critical_native,
1898*795d594fSAndroid Build Coastguard Worker                               std::string_view shorty,
1899*795d594fSAndroid Build Coastguard Worker                               ArtMethod** managed_sp,
1900*795d594fSAndroid Build Coastguard Worker                               uintptr_t* reserved_area)
1901*795d594fSAndroid Build Coastguard Worker       : QuickArgumentVisitor(managed_sp, is_static, shorty),
1902*795d594fSAndroid Build Coastguard Worker         jni_call_(nullptr, nullptr, nullptr),
1903*795d594fSAndroid Build Coastguard Worker         sm_(&jni_call_),
1904*795d594fSAndroid Build Coastguard Worker         current_vreg_(nullptr) {
1905*795d594fSAndroid Build Coastguard Worker     DCHECK_ALIGNED(managed_sp, kStackAlignment);
1906*795d594fSAndroid Build Coastguard Worker     DCHECK_ALIGNED(reserved_area, sizeof(uintptr_t));
1907*795d594fSAndroid Build Coastguard Worker 
1908*795d594fSAndroid Build Coastguard Worker     ComputeGenericJniFrameSize fsc(critical_native);
1909*795d594fSAndroid Build Coastguard Worker     uintptr_t* out_args_sp = fsc.ComputeLayout(managed_sp, shorty);
1910*795d594fSAndroid Build Coastguard Worker 
1911*795d594fSAndroid Build Coastguard Worker     // Store hidden argument for @CriticalNative.
1912*795d594fSAndroid Build Coastguard Worker     uintptr_t* hidden_arg_slot = fsc.GetHiddenArgSlot(reserved_area);
1913*795d594fSAndroid Build Coastguard Worker     constexpr uintptr_t kGenericJniTag = 1u;
1914*795d594fSAndroid Build Coastguard Worker     ArtMethod* method = *managed_sp;
1915*795d594fSAndroid Build Coastguard Worker     *hidden_arg_slot = critical_native ? (reinterpret_cast<uintptr_t>(method) | kGenericJniTag)
1916*795d594fSAndroid Build Coastguard Worker                                        : 0xebad6a89u;  // Bad value.
1917*795d594fSAndroid Build Coastguard Worker 
1918*795d594fSAndroid Build Coastguard Worker     // Set out args SP.
1919*795d594fSAndroid Build Coastguard Worker     uintptr_t* out_args_sp_slot = fsc.GetOutArgsSpSlot(reserved_area);
1920*795d594fSAndroid Build Coastguard Worker     *out_args_sp_slot = reinterpret_cast<uintptr_t>(out_args_sp);
1921*795d594fSAndroid Build Coastguard Worker 
1922*795d594fSAndroid Build Coastguard Worker     // Prepare vreg pointer for spilling references.
1923*795d594fSAndroid Build Coastguard Worker     static constexpr size_t frame_size =
1924*795d594fSAndroid Build Coastguard Worker         RuntimeCalleeSaveFrame::GetFrameSize(CalleeSaveType::kSaveRefsAndArgs);
1925*795d594fSAndroid Build Coastguard Worker     current_vreg_ = reinterpret_cast<uint32_t*>(
1926*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<uint8_t*>(managed_sp) + frame_size + sizeof(ArtMethod*));
1927*795d594fSAndroid Build Coastguard Worker 
1928*795d594fSAndroid Build Coastguard Worker     jni_call_.Reset(fsc.GetStartGprRegs(reserved_area),
1929*795d594fSAndroid Build Coastguard Worker                     fsc.GetStartFprRegs(reserved_area),
1930*795d594fSAndroid Build Coastguard Worker                     out_args_sp);
1931*795d594fSAndroid Build Coastguard Worker 
1932*795d594fSAndroid Build Coastguard Worker     // First 2 parameters are always excluded for CriticalNative methods.
1933*795d594fSAndroid Build Coastguard Worker     if (LIKELY(!critical_native)) {
1934*795d594fSAndroid Build Coastguard Worker       // jni environment is always first argument
1935*795d594fSAndroid Build Coastguard Worker       sm_.AdvancePointer(self->GetJniEnv());
1936*795d594fSAndroid Build Coastguard Worker 
1937*795d594fSAndroid Build Coastguard Worker       if (is_static) {
1938*795d594fSAndroid Build Coastguard Worker         // The `jclass` is a pointer to the method's declaring class.
1939*795d594fSAndroid Build Coastguard Worker         // The declaring class must be marked.
1940*795d594fSAndroid Build Coastguard Worker         auto* declaring_class = reinterpret_cast<mirror::CompressedReference<mirror::Class>*>(
1941*795d594fSAndroid Build Coastguard Worker             method->GetDeclaringClassAddressWithoutBarrier());
1942*795d594fSAndroid Build Coastguard Worker         if (gUseReadBarrier) {
1943*795d594fSAndroid Build Coastguard Worker           artJniReadBarrier(method);
1944*795d594fSAndroid Build Coastguard Worker         }
1945*795d594fSAndroid Build Coastguard Worker         sm_.AdvancePointer(declaring_class);
1946*795d594fSAndroid Build Coastguard Worker       }  // else "this" reference is already handled by QuickArgumentVisitor.
1947*795d594fSAndroid Build Coastguard Worker     }
1948*795d594fSAndroid Build Coastguard Worker   }
1949*795d594fSAndroid Build Coastguard Worker 
1950*795d594fSAndroid Build Coastguard Worker   void Visit() REQUIRES_SHARED(Locks::mutator_lock_) override;
1951*795d594fSAndroid Build Coastguard Worker 
1952*795d594fSAndroid Build Coastguard Worker  private:
1953*795d594fSAndroid Build Coastguard Worker   FillNativeCall jni_call_;
1954*795d594fSAndroid Build Coastguard Worker   BuildNativeCallFrameStateMachine<FillNativeCall> sm_;
1955*795d594fSAndroid Build Coastguard Worker 
1956*795d594fSAndroid Build Coastguard Worker   // Pointer to the current vreg in caller's reserved out vreg area.
1957*795d594fSAndroid Build Coastguard Worker   // Used for spilling reference arguments.
1958*795d594fSAndroid Build Coastguard Worker   uint32_t* current_vreg_;
1959*795d594fSAndroid Build Coastguard Worker 
1960*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(BuildGenericJniFrameVisitor);
1961*795d594fSAndroid Build Coastguard Worker };
1962*795d594fSAndroid Build Coastguard Worker 
Visit()1963*795d594fSAndroid Build Coastguard Worker void BuildGenericJniFrameVisitor::Visit() {
1964*795d594fSAndroid Build Coastguard Worker   Primitive::Type type = GetParamPrimitiveType();
1965*795d594fSAndroid Build Coastguard Worker   switch (type) {
1966*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimLong: {
1967*795d594fSAndroid Build Coastguard Worker       jlong long_arg;
1968*795d594fSAndroid Build Coastguard Worker       if (IsSplitLongOrDouble()) {
1969*795d594fSAndroid Build Coastguard Worker         long_arg = ReadSplitLongParam();
1970*795d594fSAndroid Build Coastguard Worker       } else {
1971*795d594fSAndroid Build Coastguard Worker         long_arg = *reinterpret_cast<jlong*>(GetParamAddress());
1972*795d594fSAndroid Build Coastguard Worker       }
1973*795d594fSAndroid Build Coastguard Worker       sm_.AdvanceLong(long_arg);
1974*795d594fSAndroid Build Coastguard Worker       current_vreg_ += 2u;
1975*795d594fSAndroid Build Coastguard Worker       break;
1976*795d594fSAndroid Build Coastguard Worker     }
1977*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimDouble: {
1978*795d594fSAndroid Build Coastguard Worker       uint64_t double_arg;
1979*795d594fSAndroid Build Coastguard Worker       if (IsSplitLongOrDouble()) {
1980*795d594fSAndroid Build Coastguard Worker         // Read into union so that we don't case to a double.
1981*795d594fSAndroid Build Coastguard Worker         double_arg = ReadSplitLongParam();
1982*795d594fSAndroid Build Coastguard Worker       } else {
1983*795d594fSAndroid Build Coastguard Worker         double_arg = *reinterpret_cast<uint64_t*>(GetParamAddress());
1984*795d594fSAndroid Build Coastguard Worker       }
1985*795d594fSAndroid Build Coastguard Worker       sm_.AdvanceDouble(double_arg);
1986*795d594fSAndroid Build Coastguard Worker       current_vreg_ += 2u;
1987*795d594fSAndroid Build Coastguard Worker       break;
1988*795d594fSAndroid Build Coastguard Worker     }
1989*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimNot: {
1990*795d594fSAndroid Build Coastguard Worker       mirror::Object* obj =
1991*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress())->AsMirrorPtr();
1992*795d594fSAndroid Build Coastguard Worker       StackReference<mirror::Object>* spill_ref =
1993*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<StackReference<mirror::Object>*>(current_vreg_);
1994*795d594fSAndroid Build Coastguard Worker       spill_ref->Assign(obj);
1995*795d594fSAndroid Build Coastguard Worker       sm_.AdvancePointer(obj != nullptr ? spill_ref : nullptr);
1996*795d594fSAndroid Build Coastguard Worker       current_vreg_ += 1u;
1997*795d594fSAndroid Build Coastguard Worker       break;
1998*795d594fSAndroid Build Coastguard Worker     }
1999*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimFloat:
2000*795d594fSAndroid Build Coastguard Worker       sm_.AdvanceFloat(*reinterpret_cast<uint32_t*>(GetParamAddress()));
2001*795d594fSAndroid Build Coastguard Worker       current_vreg_ += 1u;
2002*795d594fSAndroid Build Coastguard Worker       break;
2003*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimBoolean:  // Fall-through.
2004*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimByte:     // Fall-through.
2005*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimChar:     // Fall-through.
2006*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimShort:    // Fall-through.
2007*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimInt:      // Fall-through.
2008*795d594fSAndroid Build Coastguard Worker       sm_.AdvanceInt(*reinterpret_cast<jint*>(GetParamAddress()));
2009*795d594fSAndroid Build Coastguard Worker       current_vreg_ += 1u;
2010*795d594fSAndroid Build Coastguard Worker       break;
2011*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimVoid:
2012*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "UNREACHABLE";
2013*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
2014*795d594fSAndroid Build Coastguard Worker   }
2015*795d594fSAndroid Build Coastguard Worker }
2016*795d594fSAndroid Build Coastguard Worker 
2017*795d594fSAndroid Build Coastguard Worker /*
2018*795d594fSAndroid Build Coastguard Worker  * Initializes the reserved area assumed to be directly below `managed_sp` for a native call:
2019*795d594fSAndroid Build Coastguard Worker  *
2020*795d594fSAndroid Build Coastguard Worker  * On entry, the stack has a standard callee-save frame above `managed_sp`,
2021*795d594fSAndroid Build Coastguard Worker  * and the reserved area below it. Starting below `managed_sp`, we reserve space
2022*795d594fSAndroid Build Coastguard Worker  * for local reference cookie (not present for @CriticalNative), HandleScope
2023*795d594fSAndroid Build Coastguard Worker  * (not present for @CriticalNative) and stack args (if args do not fit into
2024*795d594fSAndroid Build Coastguard Worker  * registers). At the bottom of the reserved area, there is space for register
2025*795d594fSAndroid Build Coastguard Worker  * arguments, hidden arg (for @CriticalNative) and the SP for the native call
2026*795d594fSAndroid Build Coastguard Worker  * (i.e. pointer to the stack args area), which the calling stub shall load
2027*795d594fSAndroid Build Coastguard Worker  * to perform the native call. We fill all these fields, perform class init
2028*795d594fSAndroid Build Coastguard Worker  * check (for static methods) and/or locking (for synchronized methods) if
2029*795d594fSAndroid Build Coastguard Worker  * needed and return to the stub.
2030*795d594fSAndroid Build Coastguard Worker  *
2031*795d594fSAndroid Build Coastguard Worker  * The return value is the pointer to the native code, null on failure.
2032*795d594fSAndroid Build Coastguard Worker  *
2033*795d594fSAndroid Build Coastguard Worker  * NO_THREAD_SAFETY_ANALYSIS: Depending on the use case, the trampoline may
2034*795d594fSAndroid Build Coastguard Worker  * or may not lock a synchronization object and transition out of Runnable.
2035*795d594fSAndroid Build Coastguard Worker  */
artQuickGenericJniTrampoline(Thread * self,ArtMethod ** managed_sp,uintptr_t * reserved_area)2036*795d594fSAndroid Build Coastguard Worker extern "C" const void* artQuickGenericJniTrampoline(Thread* self,
2037*795d594fSAndroid Build Coastguard Worker                                                     ArtMethod** managed_sp,
2038*795d594fSAndroid Build Coastguard Worker                                                     uintptr_t* reserved_area)
2039*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) NO_THREAD_SAFETY_ANALYSIS {
2040*795d594fSAndroid Build Coastguard Worker   // Note: We cannot walk the stack properly until fixed up below.
2041*795d594fSAndroid Build Coastguard Worker   ArtMethod* called = *managed_sp;
2042*795d594fSAndroid Build Coastguard Worker   DCHECK(called->IsNative()) << called->PrettyMethod(true);
2043*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
2044*795d594fSAndroid Build Coastguard Worker   std::string_view shorty = called->GetShortyView();
2045*795d594fSAndroid Build Coastguard Worker   bool critical_native = called->IsCriticalNative();
2046*795d594fSAndroid Build Coastguard Worker   bool fast_native = called->IsFastNative();
2047*795d594fSAndroid Build Coastguard Worker   bool normal_native = !critical_native && !fast_native;
2048*795d594fSAndroid Build Coastguard Worker 
2049*795d594fSAndroid Build Coastguard Worker   // Run the visitor and update sp.
2050*795d594fSAndroid Build Coastguard Worker   BuildGenericJniFrameVisitor visitor(self,
2051*795d594fSAndroid Build Coastguard Worker                                       called->IsStatic(),
2052*795d594fSAndroid Build Coastguard Worker                                       critical_native,
2053*795d594fSAndroid Build Coastguard Worker                                       shorty,
2054*795d594fSAndroid Build Coastguard Worker                                       managed_sp,
2055*795d594fSAndroid Build Coastguard Worker                                       reserved_area);
2056*795d594fSAndroid Build Coastguard Worker   {
2057*795d594fSAndroid Build Coastguard Worker     ScopedAssertNoThreadSuspension sants(__FUNCTION__);
2058*795d594fSAndroid Build Coastguard Worker     visitor.VisitArguments();
2059*795d594fSAndroid Build Coastguard Worker   }
2060*795d594fSAndroid Build Coastguard Worker 
2061*795d594fSAndroid Build Coastguard Worker   // Fix up managed-stack things in Thread. After this we can walk the stack.
2062*795d594fSAndroid Build Coastguard Worker   self->SetTopOfStackGenericJniTagged(managed_sp);
2063*795d594fSAndroid Build Coastguard Worker 
2064*795d594fSAndroid Build Coastguard Worker   self->VerifyStack();
2065*795d594fSAndroid Build Coastguard Worker 
2066*795d594fSAndroid Build Coastguard Worker   // We can now walk the stack if needed by JIT GC from MethodEntered() for JIT-on-first-use.
2067*795d594fSAndroid Build Coastguard Worker   jit::Jit* jit = runtime->GetJit();
2068*795d594fSAndroid Build Coastguard Worker   if (jit != nullptr) {
2069*795d594fSAndroid Build Coastguard Worker     jit->MethodEntered(self, called);
2070*795d594fSAndroid Build Coastguard Worker   }
2071*795d594fSAndroid Build Coastguard Worker 
2072*795d594fSAndroid Build Coastguard Worker   // We can set the entrypoint of a native method to generic JNI even when the
2073*795d594fSAndroid Build Coastguard Worker   // class hasn't been initialized, so we need to do the initialization check
2074*795d594fSAndroid Build Coastguard Worker   // before invoking the native code.
2075*795d594fSAndroid Build Coastguard Worker   if (called->StillNeedsClinitCheck()) {
2076*795d594fSAndroid Build Coastguard Worker     // Ensure static method's class is initialized.
2077*795d594fSAndroid Build Coastguard Worker     StackHandleScope<1> hs(self);
2078*795d594fSAndroid Build Coastguard Worker     Handle<mirror::Class> h_class = hs.NewHandle(called->GetDeclaringClass());
2079*795d594fSAndroid Build Coastguard Worker     if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
2080*795d594fSAndroid Build Coastguard Worker       DCHECK(Thread::Current()->IsExceptionPending()) << called->PrettyMethod();
2081*795d594fSAndroid Build Coastguard Worker       return nullptr;  // Report error.
2082*795d594fSAndroid Build Coastguard Worker     }
2083*795d594fSAndroid Build Coastguard Worker   }
2084*795d594fSAndroid Build Coastguard Worker 
2085*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
2086*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(instr->HasMethodEntryListeners())) {
2087*795d594fSAndroid Build Coastguard Worker     instr->MethodEnterEvent(self, called);
2088*795d594fSAndroid Build Coastguard Worker     if (self->IsExceptionPending()) {
2089*795d594fSAndroid Build Coastguard Worker       return nullptr;
2090*795d594fSAndroid Build Coastguard Worker     }
2091*795d594fSAndroid Build Coastguard Worker   }
2092*795d594fSAndroid Build Coastguard Worker 
2093*795d594fSAndroid Build Coastguard Worker   // Skip calling `artJniMethodStart()` for @CriticalNative and @FastNative.
2094*795d594fSAndroid Build Coastguard Worker   if (LIKELY(normal_native)) {
2095*795d594fSAndroid Build Coastguard Worker     // Start JNI.
2096*795d594fSAndroid Build Coastguard Worker     if (called->IsSynchronized()) {
2097*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Object> lock = GetGenericJniSynchronizationObject(self, called);
2098*795d594fSAndroid Build Coastguard Worker       DCHECK(lock != nullptr);
2099*795d594fSAndroid Build Coastguard Worker       lock->MonitorEnter(self);
2100*795d594fSAndroid Build Coastguard Worker       if (self->IsExceptionPending()) {
2101*795d594fSAndroid Build Coastguard Worker         return nullptr;  // Report error.
2102*795d594fSAndroid Build Coastguard Worker       }
2103*795d594fSAndroid Build Coastguard Worker     }
2104*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(self->ReadFlag(ThreadFlag::kMonitorJniEntryExit))) {
2105*795d594fSAndroid Build Coastguard Worker       artJniMonitoredMethodStart(self);
2106*795d594fSAndroid Build Coastguard Worker     } else {
2107*795d594fSAndroid Build Coastguard Worker       artJniMethodStart(self);
2108*795d594fSAndroid Build Coastguard Worker     }
2109*795d594fSAndroid Build Coastguard Worker   } else {
2110*795d594fSAndroid Build Coastguard Worker     DCHECK(!called->IsSynchronized())
2111*795d594fSAndroid Build Coastguard Worker         << "@FastNative/@CriticalNative and synchronize is not supported";
2112*795d594fSAndroid Build Coastguard Worker   }
2113*795d594fSAndroid Build Coastguard Worker 
2114*795d594fSAndroid Build Coastguard Worker   // Skip pushing LRT frame for @CriticalNative.
2115*795d594fSAndroid Build Coastguard Worker   if (LIKELY(!critical_native)) {
2116*795d594fSAndroid Build Coastguard Worker     // Push local reference frame.
2117*795d594fSAndroid Build Coastguard Worker     JNIEnvExt* env = self->GetJniEnv();
2118*795d594fSAndroid Build Coastguard Worker     DCHECK(env != nullptr);
2119*795d594fSAndroid Build Coastguard Worker     uint32_t cookie = bit_cast<uint32_t>(env->PushLocalReferenceFrame());
2120*795d594fSAndroid Build Coastguard Worker 
2121*795d594fSAndroid Build Coastguard Worker     // Save the cookie on the stack.
2122*795d594fSAndroid Build Coastguard Worker     uint32_t* sp32 = reinterpret_cast<uint32_t*>(managed_sp);
2123*795d594fSAndroid Build Coastguard Worker     *(sp32 - 1) = cookie;
2124*795d594fSAndroid Build Coastguard Worker   }
2125*795d594fSAndroid Build Coastguard Worker 
2126*795d594fSAndroid Build Coastguard Worker   // Retrieve the stored native code.
2127*795d594fSAndroid Build Coastguard Worker   // Note that it may point to the lookup stub or trampoline.
2128*795d594fSAndroid Build Coastguard Worker   // FIXME: This is broken for @CriticalNative as the art_jni_dlsym_lookup_stub
2129*795d594fSAndroid Build Coastguard Worker   // does not handle that case. Calls from compiled stubs are also broken.
2130*795d594fSAndroid Build Coastguard Worker   void const* nativeCode = called->GetEntryPointFromJni();
2131*795d594fSAndroid Build Coastguard Worker 
2132*795d594fSAndroid Build Coastguard Worker   VLOG(third_party_jni) << "GenericJNI: "
2133*795d594fSAndroid Build Coastguard Worker                         << called->PrettyMethod()
2134*795d594fSAndroid Build Coastguard Worker                         << " -> "
2135*795d594fSAndroid Build Coastguard Worker                         << std::hex << reinterpret_cast<uintptr_t>(nativeCode);
2136*795d594fSAndroid Build Coastguard Worker 
2137*795d594fSAndroid Build Coastguard Worker   // Return native code.
2138*795d594fSAndroid Build Coastguard Worker   return nativeCode;
2139*795d594fSAndroid Build Coastguard Worker }
2140*795d594fSAndroid Build Coastguard Worker 
2141*795d594fSAndroid Build Coastguard Worker // Defined in quick_jni_entrypoints.cc.
2142*795d594fSAndroid Build Coastguard Worker extern uint64_t GenericJniMethodEnd(Thread* self,
2143*795d594fSAndroid Build Coastguard Worker                                     uint32_t saved_local_ref_cookie,
2144*795d594fSAndroid Build Coastguard Worker                                     jvalue result,
2145*795d594fSAndroid Build Coastguard Worker                                     uint64_t result_f,
2146*795d594fSAndroid Build Coastguard Worker                                     ArtMethod* called);
2147*795d594fSAndroid Build Coastguard Worker 
2148*795d594fSAndroid Build Coastguard Worker /*
2149*795d594fSAndroid Build Coastguard Worker  * Is called after the native JNI code. Responsible for cleanup (handle scope, saved state) and
2150*795d594fSAndroid Build Coastguard Worker  * unlocking.
2151*795d594fSAndroid Build Coastguard Worker  */
artQuickGenericJniEndTrampoline(Thread * self,jvalue result,uint64_t result_f)2152*795d594fSAndroid Build Coastguard Worker extern "C" uint64_t artQuickGenericJniEndTrampoline(Thread* self,
2153*795d594fSAndroid Build Coastguard Worker                                                     jvalue result,
2154*795d594fSAndroid Build Coastguard Worker                                                     uint64_t result_f) {
2155*795d594fSAndroid Build Coastguard Worker   // We're here just back from a native call. We don't have the shared mutator lock at this point
2156*795d594fSAndroid Build Coastguard Worker   // yet until we call GoToRunnable() later in GenericJniMethodEnd(). Accessing objects or doing
2157*795d594fSAndroid Build Coastguard Worker   // anything that requires a mutator lock before that would cause problems as GC may have the
2158*795d594fSAndroid Build Coastguard Worker   // exclusive mutator lock and may be moving objects, etc.
2159*795d594fSAndroid Build Coastguard Worker   ArtMethod** sp = self->GetManagedStack()->GetTopQuickFrame();
2160*795d594fSAndroid Build Coastguard Worker   DCHECK(self->GetManagedStack()->GetTopQuickFrameGenericJniTag());
2161*795d594fSAndroid Build Coastguard Worker   uint32_t* sp32 = reinterpret_cast<uint32_t*>(sp);
2162*795d594fSAndroid Build Coastguard Worker   ArtMethod* called = *sp;
2163*795d594fSAndroid Build Coastguard Worker   uint32_t cookie = *(sp32 - 1);
2164*795d594fSAndroid Build Coastguard Worker   return GenericJniMethodEnd(self, cookie, result, result_f, called);
2165*795d594fSAndroid Build Coastguard Worker }
2166*795d594fSAndroid Build Coastguard Worker 
2167*795d594fSAndroid Build Coastguard Worker // We use TwoWordReturn to optimize scalar returns. We use the hi value for code, and the lo value
2168*795d594fSAndroid Build Coastguard Worker // for the method pointer.
2169*795d594fSAndroid Build Coastguard Worker //
2170*795d594fSAndroid Build Coastguard Worker // It is valid to use this, as at the usage points here (returns from C functions) we are assuming
2171*795d594fSAndroid Build Coastguard Worker // to hold the mutator lock (see REQUIRES_SHARED(Locks::mutator_lock_) annotations).
2172*795d594fSAndroid Build Coastguard Worker 
2173*795d594fSAndroid Build Coastguard Worker template <InvokeType type>
artInvokeCommon(uint32_t method_idx,ObjPtr<mirror::Object> this_object,Thread * self,ArtMethod ** sp)2174*795d594fSAndroid Build Coastguard Worker static TwoWordReturn artInvokeCommon(uint32_t method_idx,
2175*795d594fSAndroid Build Coastguard Worker                                      ObjPtr<mirror::Object> this_object,
2176*795d594fSAndroid Build Coastguard Worker                                      Thread* self,
2177*795d594fSAndroid Build Coastguard Worker                                      ArtMethod** sp) {
2178*795d594fSAndroid Build Coastguard Worker   ScopedQuickEntrypointChecks sqec(self);
2179*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs));
2180*795d594fSAndroid Build Coastguard Worker   uint32_t dex_pc;
2181*795d594fSAndroid Build Coastguard Worker   ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc);
2182*795d594fSAndroid Build Coastguard Worker   CodeItemInstructionAccessor accessor(caller_method->DexInstructions());
2183*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(dex_pc, accessor.InsnsSizeInCodeUnits());
2184*795d594fSAndroid Build Coastguard Worker   const Instruction& instr = accessor.InstructionAt(dex_pc);
2185*795d594fSAndroid Build Coastguard Worker   bool string_init = false;
2186*795d594fSAndroid Build Coastguard Worker   ArtMethod* method = FindMethodToCall<type>(
2187*795d594fSAndroid Build Coastguard Worker       self, caller_method, &this_object, instr, /* only_lookup_tls_cache= */ true, &string_init);
2188*795d594fSAndroid Build Coastguard Worker 
2189*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(method == nullptr)) {
2190*795d594fSAndroid Build Coastguard Worker     if (self->IsExceptionPending()) {
2191*795d594fSAndroid Build Coastguard Worker       // Return a failure if the first lookup threw an exception.
2192*795d594fSAndroid Build Coastguard Worker       return GetTwoWordFailureValue();  // Failure.
2193*795d594fSAndroid Build Coastguard Worker     }
2194*795d594fSAndroid Build Coastguard Worker     const DexFile* dex_file = caller_method->GetDexFile();
2195*795d594fSAndroid Build Coastguard Worker     std::string_view shorty =
2196*795d594fSAndroid Build Coastguard Worker         dex_file->GetMethodShortyView(dex_file->GetMethodId(method_idx));
2197*795d594fSAndroid Build Coastguard Worker     {
2198*795d594fSAndroid Build Coastguard Worker       // Remember the args in case a GC happens in FindMethodToCall.
2199*795d594fSAndroid Build Coastguard Worker       ScopedObjectAccessUnchecked soa(self->GetJniEnv());
2200*795d594fSAndroid Build Coastguard Worker       RememberForGcArgumentVisitor visitor(sp, type == kStatic, shorty, &soa);
2201*795d594fSAndroid Build Coastguard Worker       visitor.VisitArguments();
2202*795d594fSAndroid Build Coastguard Worker 
2203*795d594fSAndroid Build Coastguard Worker       method = FindMethodToCall<type>(self,
2204*795d594fSAndroid Build Coastguard Worker                                       caller_method,
2205*795d594fSAndroid Build Coastguard Worker                                       &this_object,
2206*795d594fSAndroid Build Coastguard Worker                                       instr,
2207*795d594fSAndroid Build Coastguard Worker                                       /* only_lookup_tls_cache= */ false,
2208*795d594fSAndroid Build Coastguard Worker                                       &string_init);
2209*795d594fSAndroid Build Coastguard Worker 
2210*795d594fSAndroid Build Coastguard Worker       visitor.FixupReferences();
2211*795d594fSAndroid Build Coastguard Worker     }
2212*795d594fSAndroid Build Coastguard Worker 
2213*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(method == nullptr)) {
2214*795d594fSAndroid Build Coastguard Worker       CHECK(self->IsExceptionPending());
2215*795d594fSAndroid Build Coastguard Worker       return GetTwoWordFailureValue();  // Failure.
2216*795d594fSAndroid Build Coastguard Worker     }
2217*795d594fSAndroid Build Coastguard Worker   }
2218*795d594fSAndroid Build Coastguard Worker   DCHECK(!self->IsExceptionPending());
2219*795d594fSAndroid Build Coastguard Worker   const void* code = method->GetEntryPointFromQuickCompiledCode();
2220*795d594fSAndroid Build Coastguard Worker 
2221*795d594fSAndroid Build Coastguard Worker   // When we return, the caller will branch to this address, so it had better not be 0!
2222*795d594fSAndroid Build Coastguard Worker   DCHECK(code != nullptr) << "Code was null in method: " << method->PrettyMethod()
2223*795d594fSAndroid Build Coastguard Worker                           << " location: "
2224*795d594fSAndroid Build Coastguard Worker                           << method->GetDexFile()->GetLocation();
2225*795d594fSAndroid Build Coastguard Worker 
2226*795d594fSAndroid Build Coastguard Worker   return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(code),
2227*795d594fSAndroid Build Coastguard Worker                                 reinterpret_cast<uintptr_t>(method));
2228*795d594fSAndroid Build Coastguard Worker }
2229*795d594fSAndroid Build Coastguard Worker 
2230*795d594fSAndroid Build Coastguard Worker // Explicit artInvokeCommon template function declarations to please analysis tool.
2231*795d594fSAndroid Build Coastguard Worker #define EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(type)                                            \
2232*795d594fSAndroid Build Coastguard Worker   template REQUIRES_SHARED(Locks::mutator_lock_)                                              \
2233*795d594fSAndroid Build Coastguard Worker   TwoWordReturn artInvokeCommon<type>(                                                        \
2234*795d594fSAndroid Build Coastguard Worker       uint32_t method_idx, ObjPtr<mirror::Object> his_object, Thread* self, ArtMethod** sp)
2235*795d594fSAndroid Build Coastguard Worker 
2236*795d594fSAndroid Build Coastguard Worker EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kVirtual);
2237*795d594fSAndroid Build Coastguard Worker EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kInterface);
2238*795d594fSAndroid Build Coastguard Worker EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kDirect);
2239*795d594fSAndroid Build Coastguard Worker EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kStatic);
2240*795d594fSAndroid Build Coastguard Worker EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kSuper);
2241*795d594fSAndroid Build Coastguard Worker #undef EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL
2242*795d594fSAndroid Build Coastguard Worker 
2243*795d594fSAndroid Build Coastguard Worker // See comments in runtime_support_asm.S
artInvokeInterfaceTrampolineWithAccessCheck(uint32_t method_idx,mirror::Object * this_object,Thread * self,ArtMethod ** sp)2244*795d594fSAndroid Build Coastguard Worker extern "C" TwoWordReturn artInvokeInterfaceTrampolineWithAccessCheck(
2245*795d594fSAndroid Build Coastguard Worker     uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
2246*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2247*795d594fSAndroid Build Coastguard Worker   return artInvokeCommon<kInterface>(method_idx, this_object, self, sp);
2248*795d594fSAndroid Build Coastguard Worker }
2249*795d594fSAndroid Build Coastguard Worker 
artInvokeDirectTrampolineWithAccessCheck(uint32_t method_idx,mirror::Object * this_object,Thread * self,ArtMethod ** sp)2250*795d594fSAndroid Build Coastguard Worker extern "C" TwoWordReturn artInvokeDirectTrampolineWithAccessCheck(
2251*795d594fSAndroid Build Coastguard Worker     uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
2252*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2253*795d594fSAndroid Build Coastguard Worker   return artInvokeCommon<kDirect>(method_idx, this_object, self, sp);
2254*795d594fSAndroid Build Coastguard Worker }
2255*795d594fSAndroid Build Coastguard Worker 
artInvokeStaticTrampolineWithAccessCheck(uint32_t method_idx,mirror::Object * this_object,Thread * self,ArtMethod ** sp)2256*795d594fSAndroid Build Coastguard Worker extern "C" TwoWordReturn artInvokeStaticTrampolineWithAccessCheck(
2257*795d594fSAndroid Build Coastguard Worker     uint32_t method_idx, [[maybe_unused]] mirror::Object* this_object, Thread* self, ArtMethod** sp)
2258*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2259*795d594fSAndroid Build Coastguard Worker   // For static, this_object is not required and may be random garbage. Don't pass it down so that
2260*795d594fSAndroid Build Coastguard Worker   // it doesn't cause ObjPtr alignment failure check.
2261*795d594fSAndroid Build Coastguard Worker   return artInvokeCommon<kStatic>(method_idx, nullptr, self, sp);
2262*795d594fSAndroid Build Coastguard Worker }
2263*795d594fSAndroid Build Coastguard Worker 
artInvokeSuperTrampolineWithAccessCheck(uint32_t method_idx,mirror::Object * this_object,Thread * self,ArtMethod ** sp)2264*795d594fSAndroid Build Coastguard Worker extern "C" TwoWordReturn artInvokeSuperTrampolineWithAccessCheck(
2265*795d594fSAndroid Build Coastguard Worker     uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
2266*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2267*795d594fSAndroid Build Coastguard Worker   return artInvokeCommon<kSuper>(method_idx, this_object, self, sp);
2268*795d594fSAndroid Build Coastguard Worker }
2269*795d594fSAndroid Build Coastguard Worker 
artInvokeVirtualTrampolineWithAccessCheck(uint32_t method_idx,mirror::Object * this_object,Thread * self,ArtMethod ** sp)2270*795d594fSAndroid Build Coastguard Worker extern "C" TwoWordReturn artInvokeVirtualTrampolineWithAccessCheck(
2271*795d594fSAndroid Build Coastguard Worker     uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
2272*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2273*795d594fSAndroid Build Coastguard Worker   return artInvokeCommon<kVirtual>(method_idx, this_object, self, sp);
2274*795d594fSAndroid Build Coastguard Worker }
2275*795d594fSAndroid Build Coastguard Worker 
2276*795d594fSAndroid Build Coastguard Worker // Determine target of interface dispatch. The interface method and this object are known non-null.
2277*795d594fSAndroid Build Coastguard Worker // The interface method is the method returned by the dex cache in the conflict trampoline.
artInvokeInterfaceTrampoline(ArtMethod * interface_method,mirror::Object * raw_this_object,Thread * self,ArtMethod ** sp)2278*795d594fSAndroid Build Coastguard Worker extern "C" TwoWordReturn artInvokeInterfaceTrampoline(ArtMethod* interface_method,
2279*795d594fSAndroid Build Coastguard Worker                                                       mirror::Object* raw_this_object,
2280*795d594fSAndroid Build Coastguard Worker                                                       Thread* self,
2281*795d594fSAndroid Build Coastguard Worker                                                       ArtMethod** sp)
2282*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2283*795d594fSAndroid Build Coastguard Worker   ScopedQuickEntrypointChecks sqec(self);
2284*795d594fSAndroid Build Coastguard Worker 
2285*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
2286*795d594fSAndroid Build Coastguard Worker   bool resolve_method = ((interface_method == nullptr) || interface_method->IsRuntimeMethod());
2287*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(resolve_method)) {
2288*795d594fSAndroid Build Coastguard Worker     // The interface method is unresolved, so resolve it in the dex file of the caller.
2289*795d594fSAndroid Build Coastguard Worker     // Fetch the dex_method_idx of the target interface method from the caller.
2290*795d594fSAndroid Build Coastguard Worker     StackHandleScope<1> hs(self);
2291*795d594fSAndroid Build Coastguard Worker     Handle<mirror::Object> this_object = hs.NewHandle(raw_this_object);
2292*795d594fSAndroid Build Coastguard Worker     uint32_t dex_pc;
2293*795d594fSAndroid Build Coastguard Worker     ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc);
2294*795d594fSAndroid Build Coastguard Worker     uint32_t dex_method_idx;
2295*795d594fSAndroid Build Coastguard Worker     const Instruction& instr = caller_method->DexInstructions().InstructionAt(dex_pc);
2296*795d594fSAndroid Build Coastguard Worker     Instruction::Code instr_code = instr.Opcode();
2297*795d594fSAndroid Build Coastguard Worker     DCHECK(instr_code == Instruction::INVOKE_INTERFACE ||
2298*795d594fSAndroid Build Coastguard Worker            instr_code == Instruction::INVOKE_INTERFACE_RANGE)
2299*795d594fSAndroid Build Coastguard Worker         << "Unexpected call into interface trampoline: " << instr.DumpString(nullptr);
2300*795d594fSAndroid Build Coastguard Worker     if (instr_code == Instruction::INVOKE_INTERFACE) {
2301*795d594fSAndroid Build Coastguard Worker       dex_method_idx = instr.VRegB_35c();
2302*795d594fSAndroid Build Coastguard Worker     } else {
2303*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(instr_code, Instruction::INVOKE_INTERFACE_RANGE);
2304*795d594fSAndroid Build Coastguard Worker       dex_method_idx = instr.VRegB_3rc();
2305*795d594fSAndroid Build Coastguard Worker     }
2306*795d594fSAndroid Build Coastguard Worker 
2307*795d594fSAndroid Build Coastguard Worker     const DexFile& dex_file = *caller_method->GetDexFile();
2308*795d594fSAndroid Build Coastguard Worker     std::string_view shorty =
2309*795d594fSAndroid Build Coastguard Worker         dex_file.GetMethodShortyView(dex_file.GetMethodId(dex_method_idx));
2310*795d594fSAndroid Build Coastguard Worker     {
2311*795d594fSAndroid Build Coastguard Worker       // Remember the args in case a GC happens in ClassLinker::ResolveMethod().
2312*795d594fSAndroid Build Coastguard Worker       ScopedObjectAccessUnchecked soa(self->GetJniEnv());
2313*795d594fSAndroid Build Coastguard Worker       RememberForGcArgumentVisitor visitor(sp, false, shorty, &soa);
2314*795d594fSAndroid Build Coastguard Worker       visitor.VisitArguments();
2315*795d594fSAndroid Build Coastguard Worker       ClassLinker* class_linker = runtime->GetClassLinker();
2316*795d594fSAndroid Build Coastguard Worker       interface_method = class_linker->ResolveMethodId(dex_method_idx, caller_method);
2317*795d594fSAndroid Build Coastguard Worker       visitor.FixupReferences();
2318*795d594fSAndroid Build Coastguard Worker     }
2319*795d594fSAndroid Build Coastguard Worker 
2320*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(interface_method == nullptr)) {
2321*795d594fSAndroid Build Coastguard Worker       CHECK(self->IsExceptionPending());
2322*795d594fSAndroid Build Coastguard Worker       return GetTwoWordFailureValue();  // Failure.
2323*795d594fSAndroid Build Coastguard Worker     }
2324*795d594fSAndroid Build Coastguard Worker     ArtMethod* outer_method = QuickArgumentVisitor::GetOuterMethod(sp);
2325*795d594fSAndroid Build Coastguard Worker     MaybeUpdateBssMethodEntry(
2326*795d594fSAndroid Build Coastguard Worker         interface_method, MethodReference(&dex_file, dex_method_idx), outer_method);
2327*795d594fSAndroid Build Coastguard Worker 
2328*795d594fSAndroid Build Coastguard Worker     // Refresh `raw_this_object` which may have changed after resolution.
2329*795d594fSAndroid Build Coastguard Worker     raw_this_object = this_object.Get();
2330*795d594fSAndroid Build Coastguard Worker   }
2331*795d594fSAndroid Build Coastguard Worker 
2332*795d594fSAndroid Build Coastguard Worker   // The compiler and interpreter make sure the conflict trampoline is never
2333*795d594fSAndroid Build Coastguard Worker   // called on a method that resolves to j.l.Object.
2334*795d594fSAndroid Build Coastguard Worker   DCHECK(!interface_method->GetDeclaringClass()->IsObjectClass());
2335*795d594fSAndroid Build Coastguard Worker   DCHECK(interface_method->GetDeclaringClass()->IsInterface());
2336*795d594fSAndroid Build Coastguard Worker   DCHECK(!interface_method->IsRuntimeMethod());
2337*795d594fSAndroid Build Coastguard Worker   DCHECK(!interface_method->IsCopied());
2338*795d594fSAndroid Build Coastguard Worker 
2339*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Object> obj_this = raw_this_object;
2340*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> cls = obj_this->GetClass();
2341*795d594fSAndroid Build Coastguard Worker   uint32_t imt_index = interface_method->GetImtIndex();
2342*795d594fSAndroid Build Coastguard Worker   ImTable* imt = cls->GetImt(kRuntimePointerSize);
2343*795d594fSAndroid Build Coastguard Worker   ArtMethod* conflict_method = imt->Get(imt_index, kRuntimePointerSize);
2344*795d594fSAndroid Build Coastguard Worker   DCHECK(conflict_method->IsRuntimeMethod());
2345*795d594fSAndroid Build Coastguard Worker 
2346*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(resolve_method)) {
2347*795d594fSAndroid Build Coastguard Worker     // Now that we know the interface method, look it up in the conflict table.
2348*795d594fSAndroid Build Coastguard Worker     ImtConflictTable* current_table = conflict_method->GetImtConflictTable(kRuntimePointerSize);
2349*795d594fSAndroid Build Coastguard Worker     DCHECK(current_table != nullptr);
2350*795d594fSAndroid Build Coastguard Worker     ArtMethod* method = current_table->Lookup(interface_method, kRuntimePointerSize);
2351*795d594fSAndroid Build Coastguard Worker     if (method != nullptr) {
2352*795d594fSAndroid Build Coastguard Worker       return GetTwoWordSuccessValue(
2353*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode()),
2354*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<uintptr_t>(method));
2355*795d594fSAndroid Build Coastguard Worker     }
2356*795d594fSAndroid Build Coastguard Worker     // Interface method is not in the conflict table. Continue looking up in the
2357*795d594fSAndroid Build Coastguard Worker     // iftable.
2358*795d594fSAndroid Build Coastguard Worker   }
2359*795d594fSAndroid Build Coastguard Worker 
2360*795d594fSAndroid Build Coastguard Worker   ArtMethod* method = cls->FindVirtualMethodForInterface(interface_method, kRuntimePointerSize);
2361*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(method == nullptr)) {
2362*795d594fSAndroid Build Coastguard Worker     ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
2363*795d594fSAndroid Build Coastguard Worker     ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(
2364*795d594fSAndroid Build Coastguard Worker         interface_method, obj_this.Ptr(), caller_method);
2365*795d594fSAndroid Build Coastguard Worker     return GetTwoWordFailureValue();
2366*795d594fSAndroid Build Coastguard Worker   }
2367*795d594fSAndroid Build Coastguard Worker 
2368*795d594fSAndroid Build Coastguard Worker   // We arrive here if we have found an implementation, and it is not in the ImtConflictTable.
2369*795d594fSAndroid Build Coastguard Worker   // We create a new table with the new pair { interface_method, method }.
2370*795d594fSAndroid Build Coastguard Worker 
2371*795d594fSAndroid Build Coastguard Worker   // Classes in the boot image should never need to update conflict methods in
2372*795d594fSAndroid Build Coastguard Worker   // their IMT.
2373*795d594fSAndroid Build Coastguard Worker   CHECK(!runtime->GetHeap()->ObjectIsInBootImageSpace(cls.Ptr())) << cls->PrettyClass();
2374*795d594fSAndroid Build Coastguard Worker   ArtMethod* new_conflict_method = runtime->GetClassLinker()->AddMethodToConflictTable(
2375*795d594fSAndroid Build Coastguard Worker       cls.Ptr(),
2376*795d594fSAndroid Build Coastguard Worker       conflict_method,
2377*795d594fSAndroid Build Coastguard Worker       interface_method,
2378*795d594fSAndroid Build Coastguard Worker       method);
2379*795d594fSAndroid Build Coastguard Worker   if (new_conflict_method != conflict_method) {
2380*795d594fSAndroid Build Coastguard Worker     // Update the IMT if we create a new conflict method. No fence needed here, as the
2381*795d594fSAndroid Build Coastguard Worker     // data is consistent.
2382*795d594fSAndroid Build Coastguard Worker     imt->Set(imt_index,
2383*795d594fSAndroid Build Coastguard Worker              new_conflict_method,
2384*795d594fSAndroid Build Coastguard Worker              kRuntimePointerSize);
2385*795d594fSAndroid Build Coastguard Worker   }
2386*795d594fSAndroid Build Coastguard Worker 
2387*795d594fSAndroid Build Coastguard Worker   const void* code = method->GetEntryPointFromQuickCompiledCode();
2388*795d594fSAndroid Build Coastguard Worker 
2389*795d594fSAndroid Build Coastguard Worker   // When we return, the caller will branch to this address, so it had better not be 0!
2390*795d594fSAndroid Build Coastguard Worker   DCHECK(code != nullptr) << "Code was null in method: " << method->PrettyMethod()
2391*795d594fSAndroid Build Coastguard Worker                           << " location: " << method->GetDexFile()->GetLocation();
2392*795d594fSAndroid Build Coastguard Worker 
2393*795d594fSAndroid Build Coastguard Worker   return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(code),
2394*795d594fSAndroid Build Coastguard Worker                                 reinterpret_cast<uintptr_t>(method));
2395*795d594fSAndroid Build Coastguard Worker }
2396*795d594fSAndroid Build Coastguard Worker 
2397*795d594fSAndroid Build Coastguard Worker // Returns uint64_t representing raw bits from JValue.
artInvokePolymorphic(mirror::Object * raw_receiver,Thread * self,ArtMethod ** sp)2398*795d594fSAndroid Build Coastguard Worker extern "C" uint64_t artInvokePolymorphic(mirror::Object* raw_receiver, Thread* self, ArtMethod** sp)
2399*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2400*795d594fSAndroid Build Coastguard Worker   ScopedQuickEntrypointChecks sqec(self);
2401*795d594fSAndroid Build Coastguard Worker   DCHECK(raw_receiver != nullptr);
2402*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs));
2403*795d594fSAndroid Build Coastguard Worker 
2404*795d594fSAndroid Build Coastguard Worker   // Start new JNI local reference state
2405*795d594fSAndroid Build Coastguard Worker   JNIEnvExt* env = self->GetJniEnv();
2406*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccessUnchecked soa(env);
2407*795d594fSAndroid Build Coastguard Worker   ScopedJniEnvLocalRefState env_state(env);
2408*795d594fSAndroid Build Coastguard Worker   const char* old_cause = self->StartAssertNoThreadSuspension("Making stack arguments safe.");
2409*795d594fSAndroid Build Coastguard Worker 
2410*795d594fSAndroid Build Coastguard Worker   // From the instruction, get the |callsite_shorty| and expose arguments on the stack to the GC.
2411*795d594fSAndroid Build Coastguard Worker   uint32_t dex_pc;
2412*795d594fSAndroid Build Coastguard Worker   ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc);
2413*795d594fSAndroid Build Coastguard Worker   const Instruction& inst = caller_method->DexInstructions().InstructionAt(dex_pc);
2414*795d594fSAndroid Build Coastguard Worker   DCHECK(inst.Opcode() == Instruction::INVOKE_POLYMORPHIC ||
2415*795d594fSAndroid Build Coastguard Worker          inst.Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE);
2416*795d594fSAndroid Build Coastguard Worker   const dex::ProtoIndex proto_idx(inst.VRegH());
2417*795d594fSAndroid Build Coastguard Worker   std::string_view shorty = caller_method->GetDexFile()->GetShortyView(proto_idx);
2418*795d594fSAndroid Build Coastguard Worker   static const bool kMethodIsStatic = false;  // invoke() and invokeExact() are not static.
2419*795d594fSAndroid Build Coastguard Worker   RememberForGcArgumentVisitor gc_visitor(sp, kMethodIsStatic, shorty, &soa);
2420*795d594fSAndroid Build Coastguard Worker   gc_visitor.VisitArguments();
2421*795d594fSAndroid Build Coastguard Worker 
2422*795d594fSAndroid Build Coastguard Worker   // Wrap raw_receiver in a Handle for safety.
2423*795d594fSAndroid Build Coastguard Worker   StackHandleScope<3> hs(self);
2424*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Object> receiver_handle(hs.NewHandle(raw_receiver));
2425*795d594fSAndroid Build Coastguard Worker   raw_receiver = nullptr;
2426*795d594fSAndroid Build Coastguard Worker   self->EndAssertNoThreadSuspension(old_cause);
2427*795d594fSAndroid Build Coastguard Worker 
2428*795d594fSAndroid Build Coastguard Worker   // Resolve method.
2429*795d594fSAndroid Build Coastguard Worker   ClassLinker* linker = Runtime::Current()->GetClassLinker();
2430*795d594fSAndroid Build Coastguard Worker   ArtMethod* resolved_method = linker->ResolveMethodWithChecks(
2431*795d594fSAndroid Build Coastguard Worker       inst.VRegB(), caller_method, kVirtual);
2432*795d594fSAndroid Build Coastguard Worker 
2433*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(ArtMethod::NumArgRegisters(shorty) + 1u, (uint32_t)inst.VRegA());
2434*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(resolved_method->IsStatic(), kMethodIsStatic);
2435*795d594fSAndroid Build Coastguard Worker 
2436*795d594fSAndroid Build Coastguard Worker   // Fix references before constructing the shadow frame.
2437*795d594fSAndroid Build Coastguard Worker   gc_visitor.FixupReferences();
2438*795d594fSAndroid Build Coastguard Worker 
2439*795d594fSAndroid Build Coastguard Worker   // Construct shadow frame placing arguments consecutively from |first_arg|.
2440*795d594fSAndroid Build Coastguard Worker   const bool is_range = (inst.Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE);
2441*795d594fSAndroid Build Coastguard Worker   const size_t num_vregs = is_range ? inst.VRegA_4rcc() : inst.VRegA_45cc();
2442*795d594fSAndroid Build Coastguard Worker   const size_t first_arg = 0;
2443*795d594fSAndroid Build Coastguard Worker   ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
2444*795d594fSAndroid Build Coastguard Worker       CREATE_SHADOW_FRAME(num_vregs, resolved_method, dex_pc);
2445*795d594fSAndroid Build Coastguard Worker   ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get();
2446*795d594fSAndroid Build Coastguard Worker   ScopedStackedShadowFramePusher frame_pusher(self, shadow_frame);
2447*795d594fSAndroid Build Coastguard Worker   BuildQuickShadowFrameVisitor shadow_frame_builder(sp,
2448*795d594fSAndroid Build Coastguard Worker                                                     kMethodIsStatic,
2449*795d594fSAndroid Build Coastguard Worker                                                     shorty,
2450*795d594fSAndroid Build Coastguard Worker                                                     shadow_frame,
2451*795d594fSAndroid Build Coastguard Worker                                                     first_arg);
2452*795d594fSAndroid Build Coastguard Worker   shadow_frame_builder.VisitArguments();
2453*795d594fSAndroid Build Coastguard Worker 
2454*795d594fSAndroid Build Coastguard Worker   // Push a transition back into managed code onto the linked list in thread.
2455*795d594fSAndroid Build Coastguard Worker   ManagedStack fragment;
2456*795d594fSAndroid Build Coastguard Worker   self->PushManagedStackFragment(&fragment);
2457*795d594fSAndroid Build Coastguard Worker 
2458*795d594fSAndroid Build Coastguard Worker   // Call DoInvokePolymorphic with |is_range| = true, as shadow frame has argument registers in
2459*795d594fSAndroid Build Coastguard Worker   // consecutive order.
2460*795d594fSAndroid Build Coastguard Worker   RangeInstructionOperands operands(first_arg + 1, num_vregs - 1);
2461*795d594fSAndroid Build Coastguard Worker   Intrinsics intrinsic = resolved_method->GetIntrinsic();
2462*795d594fSAndroid Build Coastguard Worker   JValue result;
2463*795d594fSAndroid Build Coastguard Worker   bool success = false;
2464*795d594fSAndroid Build Coastguard Worker   if (resolved_method->GetDeclaringClass() == GetClassRoot<mirror::MethodHandle>(linker)) {
2465*795d594fSAndroid Build Coastguard Worker     Handle<mirror::MethodType> method_type(
2466*795d594fSAndroid Build Coastguard Worker         hs.NewHandle(linker->ResolveMethodType(self, proto_idx, caller_method)));
2467*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(method_type.IsNull())) {
2468*795d594fSAndroid Build Coastguard Worker       // This implies we couldn't resolve one or more types in this method handle.
2469*795d594fSAndroid Build Coastguard Worker       CHECK(self->IsExceptionPending());
2470*795d594fSAndroid Build Coastguard Worker       return 0UL;
2471*795d594fSAndroid Build Coastguard Worker     }
2472*795d594fSAndroid Build Coastguard Worker 
2473*795d594fSAndroid Build Coastguard Worker     Handle<mirror::MethodHandle> method_handle(hs.NewHandle(
2474*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::MethodHandle>::DownCast(receiver_handle.Get())));
2475*795d594fSAndroid Build Coastguard Worker     if (intrinsic == Intrinsics::kMethodHandleInvokeExact) {
2476*795d594fSAndroid Build Coastguard Worker       success = MethodHandleInvokeExact(self,
2477*795d594fSAndroid Build Coastguard Worker                                         *shadow_frame,
2478*795d594fSAndroid Build Coastguard Worker                                         method_handle,
2479*795d594fSAndroid Build Coastguard Worker                                         method_type,
2480*795d594fSAndroid Build Coastguard Worker                                         &operands,
2481*795d594fSAndroid Build Coastguard Worker                                         &result);
2482*795d594fSAndroid Build Coastguard Worker     } else {
2483*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(static_cast<uint32_t>(intrinsic),
2484*795d594fSAndroid Build Coastguard Worker                 static_cast<uint32_t>(Intrinsics::kMethodHandleInvoke));
2485*795d594fSAndroid Build Coastguard Worker       success = MethodHandleInvoke(self,
2486*795d594fSAndroid Build Coastguard Worker                                    *shadow_frame,
2487*795d594fSAndroid Build Coastguard Worker                                    method_handle,
2488*795d594fSAndroid Build Coastguard Worker                                    method_type,
2489*795d594fSAndroid Build Coastguard Worker                                    &operands,
2490*795d594fSAndroid Build Coastguard Worker                                    &result);
2491*795d594fSAndroid Build Coastguard Worker     }
2492*795d594fSAndroid Build Coastguard Worker   } else {
2493*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(GetClassRoot<mirror::VarHandle>(linker), resolved_method->GetDeclaringClass());
2494*795d594fSAndroid Build Coastguard Worker     Handle<mirror::VarHandle> var_handle(hs.NewHandle(
2495*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::VarHandle>::DownCast(receiver_handle.Get())));
2496*795d594fSAndroid Build Coastguard Worker     mirror::VarHandle::AccessMode access_mode =
2497*795d594fSAndroid Build Coastguard Worker         mirror::VarHandle::GetAccessModeByIntrinsic(intrinsic);
2498*795d594fSAndroid Build Coastguard Worker 
2499*795d594fSAndroid Build Coastguard Worker     success = VarHandleInvokeAccessor(self,
2500*795d594fSAndroid Build Coastguard Worker                                       *shadow_frame,
2501*795d594fSAndroid Build Coastguard Worker                                       var_handle,
2502*795d594fSAndroid Build Coastguard Worker                                       caller_method,
2503*795d594fSAndroid Build Coastguard Worker                                       proto_idx,
2504*795d594fSAndroid Build Coastguard Worker                                       access_mode,
2505*795d594fSAndroid Build Coastguard Worker                                       &operands,
2506*795d594fSAndroid Build Coastguard Worker                                       &result);
2507*795d594fSAndroid Build Coastguard Worker   }
2508*795d594fSAndroid Build Coastguard Worker 
2509*795d594fSAndroid Build Coastguard Worker   DCHECK(success || self->IsExceptionPending());
2510*795d594fSAndroid Build Coastguard Worker 
2511*795d594fSAndroid Build Coastguard Worker   // Pop transition record.
2512*795d594fSAndroid Build Coastguard Worker   self->PopManagedStackFragment(fragment);
2513*795d594fSAndroid Build Coastguard Worker 
2514*795d594fSAndroid Build Coastguard Worker   bool is_ref = (shorty[0] == 'L');
2515*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->GetInstrumentation()->PushDeoptContextIfNeeded(
2516*795d594fSAndroid Build Coastguard Worker       self, DeoptimizationMethodType::kDefault, is_ref, result);
2517*795d594fSAndroid Build Coastguard Worker 
2518*795d594fSAndroid Build Coastguard Worker   return NanBoxResultIfNeeded(result.GetJ(), shorty[0]);
2519*795d594fSAndroid Build Coastguard Worker }
2520*795d594fSAndroid Build Coastguard Worker 
artInvokePolymorphicWithHiddenReceiver(mirror::Object * raw_receiver,Thread * self,ArtMethod ** sp)2521*795d594fSAndroid Build Coastguard Worker extern "C" uint64_t artInvokePolymorphicWithHiddenReceiver(mirror::Object* raw_receiver,
2522*795d594fSAndroid Build Coastguard Worker                                                            Thread* self,
2523*795d594fSAndroid Build Coastguard Worker                                                            ArtMethod** sp)
2524*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2525*795d594fSAndroid Build Coastguard Worker   ScopedQuickEntrypointChecks sqec(self);
2526*795d594fSAndroid Build Coastguard Worker   DCHECK(raw_receiver != nullptr);
2527*795d594fSAndroid Build Coastguard Worker   DCHECK(raw_receiver->InstanceOf(WellKnownClasses::java_lang_invoke_MethodHandle.Get()));
2528*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs));
2529*795d594fSAndroid Build Coastguard Worker 
2530*795d594fSAndroid Build Coastguard Worker   JNIEnvExt* env = self->GetJniEnv();
2531*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccessUnchecked soa(env);
2532*795d594fSAndroid Build Coastguard Worker   ScopedJniEnvLocalRefState env_state(env);
2533*795d594fSAndroid Build Coastguard Worker   const char* old_cause = self->StartAssertNoThreadSuspension("Making stack arguments safe.");
2534*795d594fSAndroid Build Coastguard Worker 
2535*795d594fSAndroid Build Coastguard Worker   // From the instruction, get the |callsite_shorty| and expose arguments on the stack to the GC.
2536*795d594fSAndroid Build Coastguard Worker   uint32_t dex_pc;
2537*795d594fSAndroid Build Coastguard Worker   ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc);
2538*795d594fSAndroid Build Coastguard Worker   const Instruction& inst = caller_method->DexInstructions().InstructionAt(dex_pc);
2539*795d594fSAndroid Build Coastguard Worker   DCHECK(inst.Opcode() == Instruction::INVOKE_POLYMORPHIC ||
2540*795d594fSAndroid Build Coastguard Worker          inst.Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE);
2541*795d594fSAndroid Build Coastguard Worker   const dex::ProtoIndex proto_idx(inst.VRegH());
2542*795d594fSAndroid Build Coastguard Worker   std::string_view shorty = caller_method->GetDexFile()->GetShortyView(proto_idx);
2543*795d594fSAndroid Build Coastguard Worker 
2544*795d594fSAndroid Build Coastguard Worker   // invokeExact is not a static method, but here we use custom calling convention and the receiver
2545*795d594fSAndroid Build Coastguard Worker   // (MethodHandle) object is not passed as a first argument, but through different means and hence
2546*795d594fSAndroid Build Coastguard Worker   // shorty and arguments allocation looks as-if invokeExact was static.
2547*795d594fSAndroid Build Coastguard Worker   RememberForGcArgumentVisitor gc_visitor(sp, /* is_static= */ true, shorty, &soa);
2548*795d594fSAndroid Build Coastguard Worker   gc_visitor.VisitArguments();
2549*795d594fSAndroid Build Coastguard Worker 
2550*795d594fSAndroid Build Coastguard Worker   // Wrap raw_receiver in a Handle for safety.
2551*795d594fSAndroid Build Coastguard Worker   StackHandleScope<2> hs(self);
2552*795d594fSAndroid Build Coastguard Worker   Handle<mirror::MethodHandle> method_handle(
2553*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(down_cast<mirror::MethodHandle*>(raw_receiver)));
2554*795d594fSAndroid Build Coastguard Worker 
2555*795d594fSAndroid Build Coastguard Worker   self->EndAssertNoThreadSuspension(old_cause);
2556*795d594fSAndroid Build Coastguard Worker 
2557*795d594fSAndroid Build Coastguard Worker   ClassLinker* linker = Runtime::Current()->GetClassLinker();
2558*795d594fSAndroid Build Coastguard Worker   ArtMethod* invoke_exact = WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact;
2559*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
2560*795d594fSAndroid Build Coastguard Worker     ArtMethod* resolved_method = linker->ResolveMethodWithChecks(
2561*795d594fSAndroid Build Coastguard Worker         inst.VRegB(), caller_method, kVirtual);
2562*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(resolved_method, invoke_exact);
2563*795d594fSAndroid Build Coastguard Worker   }
2564*795d594fSAndroid Build Coastguard Worker 
2565*795d594fSAndroid Build Coastguard Worker   Handle<mirror::MethodType> method_type(
2566*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(linker->ResolveMethodType(self, proto_idx, caller_method)));
2567*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(method_type.IsNull())) {
2568*795d594fSAndroid Build Coastguard Worker     // This implies we couldn't resolve one or more types in this method handle.
2569*795d594fSAndroid Build Coastguard Worker     CHECK(self->IsExceptionPending());
2570*795d594fSAndroid Build Coastguard Worker     return 0UL;
2571*795d594fSAndroid Build Coastguard Worker   }
2572*795d594fSAndroid Build Coastguard Worker 
2573*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(ArtMethod::NumArgRegisters(shorty) + 1u, (uint32_t)inst.VRegA());
2574*795d594fSAndroid Build Coastguard Worker 
2575*795d594fSAndroid Build Coastguard Worker   // Fix references before constructing the shadow frame.
2576*795d594fSAndroid Build Coastguard Worker   gc_visitor.FixupReferences();
2577*795d594fSAndroid Build Coastguard Worker 
2578*795d594fSAndroid Build Coastguard Worker   // Construct shadow frame placing arguments consecutively from |first_arg|.
2579*795d594fSAndroid Build Coastguard Worker   const bool is_range = inst.Opcode() == Instruction::INVOKE_POLYMORPHIC_RANGE;
2580*795d594fSAndroid Build Coastguard Worker   const size_t num_vregs = is_range ? inst.VRegA_4rcc() : inst.VRegA_45cc();
2581*795d594fSAndroid Build Coastguard Worker   const size_t first_arg = 0;
2582*795d594fSAndroid Build Coastguard Worker   ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
2583*795d594fSAndroid Build Coastguard Worker       CREATE_SHADOW_FRAME(num_vregs, invoke_exact, dex_pc);
2584*795d594fSAndroid Build Coastguard Worker   ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get();
2585*795d594fSAndroid Build Coastguard Worker   ScopedStackedShadowFramePusher frame_pusher(self, shadow_frame);
2586*795d594fSAndroid Build Coastguard Worker   // Pretend the method is static, see the gc_visitor comment above.
2587*795d594fSAndroid Build Coastguard Worker   BuildQuickShadowFrameVisitor shadow_frame_builder(sp,
2588*795d594fSAndroid Build Coastguard Worker                                                     /* is_static= */ true,
2589*795d594fSAndroid Build Coastguard Worker                                                     shorty,
2590*795d594fSAndroid Build Coastguard Worker                                                     shadow_frame,
2591*795d594fSAndroid Build Coastguard Worker                                                     first_arg);
2592*795d594fSAndroid Build Coastguard Worker   // Receiver is not passed as a regular argument, adding it to ShadowFrame manually.
2593*795d594fSAndroid Build Coastguard Worker   shadow_frame_builder.SetReceiver(method_handle.Get());
2594*795d594fSAndroid Build Coastguard Worker   shadow_frame_builder.VisitArguments();
2595*795d594fSAndroid Build Coastguard Worker 
2596*795d594fSAndroid Build Coastguard Worker   // Push a transition back into managed code onto the linked list in thread.
2597*795d594fSAndroid Build Coastguard Worker   ManagedStack fragment;
2598*795d594fSAndroid Build Coastguard Worker   self->PushManagedStackFragment(&fragment);
2599*795d594fSAndroid Build Coastguard Worker 
2600*795d594fSAndroid Build Coastguard Worker   RangeInstructionOperands operands(first_arg + 1, num_vregs - 1);
2601*795d594fSAndroid Build Coastguard Worker   JValue result;
2602*795d594fSAndroid Build Coastguard Worker   bool success = MethodHandleInvokeExact(self,
2603*795d594fSAndroid Build Coastguard Worker                                          *shadow_frame,
2604*795d594fSAndroid Build Coastguard Worker                                          method_handle,
2605*795d594fSAndroid Build Coastguard Worker                                          method_type,
2606*795d594fSAndroid Build Coastguard Worker                                          &operands,
2607*795d594fSAndroid Build Coastguard Worker                                          &result);
2608*795d594fSAndroid Build Coastguard Worker 
2609*795d594fSAndroid Build Coastguard Worker   DCHECK(success || self->IsExceptionPending());
2610*795d594fSAndroid Build Coastguard Worker 
2611*795d594fSAndroid Build Coastguard Worker   // Pop transition record.
2612*795d594fSAndroid Build Coastguard Worker   self->PopManagedStackFragment(fragment);
2613*795d594fSAndroid Build Coastguard Worker 
2614*795d594fSAndroid Build Coastguard Worker   bool is_ref = shorty[0] == 'L';
2615*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->GetInstrumentation()->PushDeoptContextIfNeeded(
2616*795d594fSAndroid Build Coastguard Worker       self, DeoptimizationMethodType::kDefault, is_ref, result);
2617*795d594fSAndroid Build Coastguard Worker 
2618*795d594fSAndroid Build Coastguard Worker   return NanBoxResultIfNeeded(result.GetJ(), shorty[0]);
2619*795d594fSAndroid Build Coastguard Worker }
2620*795d594fSAndroid Build Coastguard Worker 
2621*795d594fSAndroid Build Coastguard Worker // Returns uint64_t representing raw bits from JValue.
artInvokeCustom(uint32_t call_site_idx,Thread * self,ArtMethod ** sp)2622*795d594fSAndroid Build Coastguard Worker extern "C" uint64_t artInvokeCustom(uint32_t call_site_idx, Thread* self, ArtMethod** sp)
2623*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2624*795d594fSAndroid Build Coastguard Worker   ScopedQuickEntrypointChecks sqec(self);
2625*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs));
2626*795d594fSAndroid Build Coastguard Worker 
2627*795d594fSAndroid Build Coastguard Worker   // invoke-custom is effectively a static call (no receiver).
2628*795d594fSAndroid Build Coastguard Worker   static constexpr bool kMethodIsStatic = true;
2629*795d594fSAndroid Build Coastguard Worker 
2630*795d594fSAndroid Build Coastguard Worker   // Start new JNI local reference state
2631*795d594fSAndroid Build Coastguard Worker   JNIEnvExt* env = self->GetJniEnv();
2632*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccessUnchecked soa(env);
2633*795d594fSAndroid Build Coastguard Worker   ScopedJniEnvLocalRefState env_state(env);
2634*795d594fSAndroid Build Coastguard Worker 
2635*795d594fSAndroid Build Coastguard Worker   const char* old_cause = self->StartAssertNoThreadSuspension("Making stack arguments safe.");
2636*795d594fSAndroid Build Coastguard Worker 
2637*795d594fSAndroid Build Coastguard Worker   // From the instruction, get the |callsite_shorty| and expose arguments on the stack to the GC.
2638*795d594fSAndroid Build Coastguard Worker   uint32_t dex_pc;
2639*795d594fSAndroid Build Coastguard Worker   ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethodAndDexPc(sp, &dex_pc);
2640*795d594fSAndroid Build Coastguard Worker   const DexFile* dex_file = caller_method->GetDexFile();
2641*795d594fSAndroid Build Coastguard Worker   const dex::ProtoIndex proto_idx(dex_file->GetProtoIndexForCallSite(call_site_idx));
2642*795d594fSAndroid Build Coastguard Worker   std::string_view shorty = caller_method->GetDexFile()->GetShortyView(proto_idx);
2643*795d594fSAndroid Build Coastguard Worker 
2644*795d594fSAndroid Build Coastguard Worker   // Construct the shadow frame placing arguments consecutively from |first_arg|.
2645*795d594fSAndroid Build Coastguard Worker   const size_t first_arg = 0;
2646*795d594fSAndroid Build Coastguard Worker   const size_t num_vregs = ArtMethod::NumArgRegisters(shorty);
2647*795d594fSAndroid Build Coastguard Worker   ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
2648*795d594fSAndroid Build Coastguard Worker       CREATE_SHADOW_FRAME(num_vregs, caller_method, dex_pc);
2649*795d594fSAndroid Build Coastguard Worker   ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get();
2650*795d594fSAndroid Build Coastguard Worker   ScopedStackedShadowFramePusher frame_pusher(self, shadow_frame);
2651*795d594fSAndroid Build Coastguard Worker   BuildQuickShadowFrameVisitor shadow_frame_builder(sp,
2652*795d594fSAndroid Build Coastguard Worker                                                     kMethodIsStatic,
2653*795d594fSAndroid Build Coastguard Worker                                                     shorty,
2654*795d594fSAndroid Build Coastguard Worker                                                     shadow_frame,
2655*795d594fSAndroid Build Coastguard Worker                                                     first_arg);
2656*795d594fSAndroid Build Coastguard Worker   shadow_frame_builder.VisitArguments();
2657*795d594fSAndroid Build Coastguard Worker 
2658*795d594fSAndroid Build Coastguard Worker   // Push a transition back into managed code onto the linked list in thread.
2659*795d594fSAndroid Build Coastguard Worker   ManagedStack fragment;
2660*795d594fSAndroid Build Coastguard Worker   self->PushManagedStackFragment(&fragment);
2661*795d594fSAndroid Build Coastguard Worker   self->EndAssertNoThreadSuspension(old_cause);
2662*795d594fSAndroid Build Coastguard Worker 
2663*795d594fSAndroid Build Coastguard Worker   // Perform the invoke-custom operation.
2664*795d594fSAndroid Build Coastguard Worker   RangeInstructionOperands operands(first_arg, num_vregs);
2665*795d594fSAndroid Build Coastguard Worker   JValue result;
2666*795d594fSAndroid Build Coastguard Worker   bool success =
2667*795d594fSAndroid Build Coastguard Worker       interpreter::DoInvokeCustom(self, *shadow_frame, call_site_idx, &operands, &result);
2668*795d594fSAndroid Build Coastguard Worker   DCHECK(success || self->IsExceptionPending());
2669*795d594fSAndroid Build Coastguard Worker 
2670*795d594fSAndroid Build Coastguard Worker   // Pop transition record.
2671*795d594fSAndroid Build Coastguard Worker   self->PopManagedStackFragment(fragment);
2672*795d594fSAndroid Build Coastguard Worker 
2673*795d594fSAndroid Build Coastguard Worker   bool is_ref = (shorty[0] == 'L');
2674*795d594fSAndroid Build Coastguard Worker   Runtime::Current()->GetInstrumentation()->PushDeoptContextIfNeeded(
2675*795d594fSAndroid Build Coastguard Worker       self, DeoptimizationMethodType::kDefault, is_ref, result);
2676*795d594fSAndroid Build Coastguard Worker 
2677*795d594fSAndroid Build Coastguard Worker   return NanBoxResultIfNeeded(result.GetJ(), shorty[0]);
2678*795d594fSAndroid Build Coastguard Worker }
2679*795d594fSAndroid Build Coastguard Worker 
artJniMethodEntryHook(Thread * self)2680*795d594fSAndroid Build Coastguard Worker extern "C" void artJniMethodEntryHook(Thread* self)
2681*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2682*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
2683*795d594fSAndroid Build Coastguard Worker   ArtMethod* method = *self->GetManagedStack()->GetTopQuickFrame();
2684*795d594fSAndroid Build Coastguard Worker   instr->MethodEnterEvent(self, method);
2685*795d594fSAndroid Build Coastguard Worker }
2686*795d594fSAndroid Build Coastguard Worker 
artMethodEntryHook(ArtMethod * method,Thread * self,ArtMethod ** sp)2687*795d594fSAndroid Build Coastguard Worker extern "C" Context* artMethodEntryHook(ArtMethod* method, Thread* self, ArtMethod** sp)
2688*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
2689*795d594fSAndroid Build Coastguard Worker   ScopedQuickEntrypointChecks sqec(self);
2690*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
2691*795d594fSAndroid Build Coastguard Worker   if (instr->HasFastMethodEntryListenersOnly()) {
2692*795d594fSAndroid Build Coastguard Worker     instr->MethodEnterEvent(self, method);
2693*795d594fSAndroid Build Coastguard Worker     // No exception or deoptimization.
2694*795d594fSAndroid Build Coastguard Worker     return nullptr;
2695*795d594fSAndroid Build Coastguard Worker   }
2696*795d594fSAndroid Build Coastguard Worker 
2697*795d594fSAndroid Build Coastguard Worker   if (instr->HasMethodEntryListeners()) {
2698*795d594fSAndroid Build Coastguard Worker     instr->MethodEnterEvent(self, method);
2699*795d594fSAndroid Build Coastguard Worker     // MethodEnter callback could have requested a deopt for ex: by setting a breakpoint, so
2700*795d594fSAndroid Build Coastguard Worker     // check if we need a deopt here.
2701*795d594fSAndroid Build Coastguard Worker     if (instr->ShouldDeoptimizeCaller(self, sp) || instr->IsDeoptimized(method)) {
2702*795d594fSAndroid Build Coastguard Worker       // Instrumentation can request deoptimizing only a particular method (for ex: when
2703*795d594fSAndroid Build Coastguard Worker       // there are break points on the method). In such cases deoptimize only this method.
2704*795d594fSAndroid Build Coastguard Worker       // FullFrame deoptimizations are handled on method exits.
2705*795d594fSAndroid Build Coastguard Worker       return artDeoptimizeFromCompiledCode(DeoptimizationKind::kDebugging, self);
2706*795d594fSAndroid Build Coastguard Worker     }
2707*795d594fSAndroid Build Coastguard Worker   } else {
2708*795d594fSAndroid Build Coastguard Worker     DCHECK(!instr->IsDeoptimized(method));
2709*795d594fSAndroid Build Coastguard Worker   }
2710*795d594fSAndroid Build Coastguard Worker   // No exception or deoptimization.
2711*795d594fSAndroid Build Coastguard Worker   return nullptr;
2712*795d594fSAndroid Build Coastguard Worker }
2713*795d594fSAndroid Build Coastguard Worker 
artMethodExitHook(Thread * self,ArtMethod ** sp,uint64_t * gpr_result,uint64_t * fpr_result,uint32_t frame_size)2714*795d594fSAndroid Build Coastguard Worker extern "C" Context* artMethodExitHook(Thread* self,
2715*795d594fSAndroid Build Coastguard Worker                                       ArtMethod** sp,
2716*795d594fSAndroid Build Coastguard Worker                                       uint64_t* gpr_result,
2717*795d594fSAndroid Build Coastguard Worker                                       uint64_t* fpr_result,
2718*795d594fSAndroid Build Coastguard Worker                                       uint32_t frame_size)
2719*795d594fSAndroid Build Coastguard Worker   REQUIRES_SHARED(Locks::mutator_lock_) {
2720*795d594fSAndroid Build Coastguard Worker   ScopedQuickEntrypointChecks sqec(self);
2721*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(reinterpret_cast<uintptr_t>(self), reinterpret_cast<uintptr_t>(Thread::Current()));
2722*795d594fSAndroid Build Coastguard Worker   // Instrumentation exit stub must not be entered with a pending exception.
2723*795d594fSAndroid Build Coastguard Worker   CHECK(!self->IsExceptionPending())
2724*795d594fSAndroid Build Coastguard Worker       << "Enter instrumentation exit stub with pending exception " << self->GetException()->Dump();
2725*795d594fSAndroid Build Coastguard Worker 
2726*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
2727*795d594fSAndroid Build Coastguard Worker   DCHECK(instr->RunExitHooks());
2728*795d594fSAndroid Build Coastguard Worker 
2729*795d594fSAndroid Build Coastguard Worker   ArtMethod* method = *sp;
2730*795d594fSAndroid Build Coastguard Worker   if (instr->HasFastMethodExitListenersOnly()) {
2731*795d594fSAndroid Build Coastguard Worker     // Fast method listeners are only used for tracing which don't need any deoptimization checks
2732*795d594fSAndroid Build Coastguard Worker     // or a return value.
2733*795d594fSAndroid Build Coastguard Worker     JValue return_value;
2734*795d594fSAndroid Build Coastguard Worker     instr->MethodExitEvent(self, method, /* frame= */ {}, return_value);
2735*795d594fSAndroid Build Coastguard Worker     // No exception or deoptimization.
2736*795d594fSAndroid Build Coastguard Worker     return nullptr;
2737*795d594fSAndroid Build Coastguard Worker   }
2738*795d594fSAndroid Build Coastguard Worker 
2739*795d594fSAndroid Build Coastguard Worker   bool is_ref = false;
2740*795d594fSAndroid Build Coastguard Worker   if (instr->HasMethodExitListeners()) {
2741*795d594fSAndroid Build Coastguard Worker     StackHandleScope<1> hs(self);
2742*795d594fSAndroid Build Coastguard Worker 
2743*795d594fSAndroid Build Coastguard Worker     CHECK(gpr_result != nullptr);
2744*795d594fSAndroid Build Coastguard Worker     CHECK(fpr_result != nullptr);
2745*795d594fSAndroid Build Coastguard Worker 
2746*795d594fSAndroid Build Coastguard Worker     JValue return_value = instr->GetReturnValue(method, &is_ref, gpr_result, fpr_result);
2747*795d594fSAndroid Build Coastguard Worker     MutableHandle<mirror::Object> res(hs.NewHandle<mirror::Object>(nullptr));
2748*795d594fSAndroid Build Coastguard Worker     if (is_ref) {
2749*795d594fSAndroid Build Coastguard Worker       // Take a handle to the return value so we won't lose it if we suspend.
2750*795d594fSAndroid Build Coastguard Worker       res.Assign(return_value.GetL());
2751*795d594fSAndroid Build Coastguard Worker     }
2752*795d594fSAndroid Build Coastguard Worker     DCHECK(!method->IsRuntimeMethod());
2753*795d594fSAndroid Build Coastguard Worker 
2754*795d594fSAndroid Build Coastguard Worker     // If we need a deoptimization MethodExitEvent will be called by the interpreter when it
2755*795d594fSAndroid Build Coastguard Worker     // re-executes the return instruction. For native methods we have to process method exit
2756*795d594fSAndroid Build Coastguard Worker     // events here since deoptimization just removes the native frame.
2757*795d594fSAndroid Build Coastguard Worker     instr->MethodExitEvent(self, method, /* frame= */ {}, return_value);
2758*795d594fSAndroid Build Coastguard Worker 
2759*795d594fSAndroid Build Coastguard Worker     if (is_ref) {
2760*795d594fSAndroid Build Coastguard Worker       // Restore the return value if it's a reference since it might have moved.
2761*795d594fSAndroid Build Coastguard Worker       *reinterpret_cast<mirror::Object**>(gpr_result) = res.Get();
2762*795d594fSAndroid Build Coastguard Worker       return_value.SetL(res.Get());
2763*795d594fSAndroid Build Coastguard Worker     }
2764*795d594fSAndroid Build Coastguard Worker   }
2765*795d594fSAndroid Build Coastguard Worker 
2766*795d594fSAndroid Build Coastguard Worker   if (self->IsExceptionPending() || self->ObserveAsyncException()) {
2767*795d594fSAndroid Build Coastguard Worker     // The exception was thrown from the method exit callback. We should not call method unwind
2768*795d594fSAndroid Build Coastguard Worker     // callbacks for this case.
2769*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<Context> context =
2770*795d594fSAndroid Build Coastguard Worker         self->QuickDeliverException(/* is_method_exit_exception= */ true);
2771*795d594fSAndroid Build Coastguard Worker     DCHECK(context != nullptr);
2772*795d594fSAndroid Build Coastguard Worker     return context.release();
2773*795d594fSAndroid Build Coastguard Worker   }
2774*795d594fSAndroid Build Coastguard Worker 
2775*795d594fSAndroid Build Coastguard Worker   // We should deoptimize here if the caller requires a deoptimization or if the current method
2776*795d594fSAndroid Build Coastguard Worker   // needs a deoptimization. We may need deoptimization for the current method if method exit
2777*795d594fSAndroid Build Coastguard Worker   // hooks requested this frame to be popped. IsForcedInterpreterNeededForUpcall checks for that.
2778*795d594fSAndroid Build Coastguard Worker   const bool deoptimize = instr->ShouldDeoptimizeCaller(self, sp, frame_size) ||
2779*795d594fSAndroid Build Coastguard Worker                           Dbg::IsForcedInterpreterNeededForUpcall(self, method);
2780*795d594fSAndroid Build Coastguard Worker   if (deoptimize) {
2781*795d594fSAndroid Build Coastguard Worker     JValue ret_val = instr->GetReturnValue(method, &is_ref, gpr_result, fpr_result);
2782*795d594fSAndroid Build Coastguard Worker     DeoptimizationMethodType deopt_method_type = instr->GetDeoptimizationMethodType(method);
2783*795d594fSAndroid Build Coastguard Worker     self->PushDeoptimizationContext(
2784*795d594fSAndroid Build Coastguard Worker         ret_val, is_ref, self->GetException(), false, deopt_method_type);
2785*795d594fSAndroid Build Coastguard Worker     // Method exit callback has already been run for this method. So tell the deoptimizer to skip
2786*795d594fSAndroid Build Coastguard Worker     // callbacks for this frame.
2787*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<Context> context = self->Deoptimize(DeoptimizationKind::kFullFrame,
2788*795d594fSAndroid Build Coastguard Worker                                                         /* single_frame= */ false,
2789*795d594fSAndroid Build Coastguard Worker                                                         /* skip_method_exit_callbacks= */ true);
2790*795d594fSAndroid Build Coastguard Worker     DCHECK(context != nullptr);
2791*795d594fSAndroid Build Coastguard Worker     return context.release();
2792*795d594fSAndroid Build Coastguard Worker   }
2793*795d594fSAndroid Build Coastguard Worker 
2794*795d594fSAndroid Build Coastguard Worker   // No exception or deoptimization.
2795*795d594fSAndroid Build Coastguard Worker   return nullptr;
2796*795d594fSAndroid Build Coastguard Worker }
2797*795d594fSAndroid Build Coastguard Worker 
2798*795d594fSAndroid Build Coastguard Worker }  // namespace art
2799