1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 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 #ifndef ART_RUNTIME_METHOD_HANDLES_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_METHOD_HANDLES_INL_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include "method_handles.h"
21*795d594fSAndroid Build Coastguard Worker
22*795d594fSAndroid Build Coastguard Worker #include "common_throws.h"
23*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction.h"
24*795d594fSAndroid Build Coastguard Worker #include "interpreter/interpreter_common.h"
25*795d594fSAndroid Build Coastguard Worker #include "interpreter/shadow_frame-inl.h"
26*795d594fSAndroid Build Coastguard Worker #include "jvalue-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
28*795d594fSAndroid Build Coastguard Worker #include "mirror/method_type-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "mirror/object.h"
30*795d594fSAndroid Build Coastguard Worker #include "reflection.h"
31*795d594fSAndroid Build Coastguard Worker #include "stack.h"
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
34*795d594fSAndroid Build Coastguard Worker
35*795d594fSAndroid Build Coastguard Worker // A convenience class that allows for iteration through a list of
36*795d594fSAndroid Build Coastguard Worker // input argument registers. This is used to iterate over input
37*795d594fSAndroid Build Coastguard Worker // arguments while performing standard argument conversions.
38*795d594fSAndroid Build Coastguard Worker class ShadowFrameGetter {
39*795d594fSAndroid Build Coastguard Worker public:
40*795d594fSAndroid Build Coastguard Worker ShadowFrameGetter(const ShadowFrame& shadow_frame,
41*795d594fSAndroid Build Coastguard Worker const InstructionOperands* const operands,
42*795d594fSAndroid Build Coastguard Worker size_t operand_index = 0u)
shadow_frame_(shadow_frame)43*795d594fSAndroid Build Coastguard Worker : shadow_frame_(shadow_frame), operands_(operands), operand_index_(operand_index) {}
44*795d594fSAndroid Build Coastguard Worker
Get()45*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) {
46*795d594fSAndroid Build Coastguard Worker return shadow_frame_.GetVReg(Next());
47*795d594fSAndroid Build Coastguard Worker }
48*795d594fSAndroid Build Coastguard Worker
GetLong()49*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE int64_t GetLong() REQUIRES_SHARED(Locks::mutator_lock_) {
50*795d594fSAndroid Build Coastguard Worker return shadow_frame_.GetVRegLong(NextLong());
51*795d594fSAndroid Build Coastguard Worker }
52*795d594fSAndroid Build Coastguard Worker
GetReference()53*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE ObjPtr<mirror::Object> GetReference() REQUIRES_SHARED(Locks::mutator_lock_) {
54*795d594fSAndroid Build Coastguard Worker return shadow_frame_.GetVRegReference(Next());
55*795d594fSAndroid Build Coastguard Worker }
56*795d594fSAndroid Build Coastguard Worker
57*795d594fSAndroid Build Coastguard Worker private:
Next()58*795d594fSAndroid Build Coastguard Worker uint32_t Next() {
59*795d594fSAndroid Build Coastguard Worker const uint32_t next = operands_->GetOperand(operand_index_);
60*795d594fSAndroid Build Coastguard Worker operand_index_ += 1;
61*795d594fSAndroid Build Coastguard Worker return next;
62*795d594fSAndroid Build Coastguard Worker }
63*795d594fSAndroid Build Coastguard Worker
NextLong()64*795d594fSAndroid Build Coastguard Worker uint32_t NextLong() {
65*795d594fSAndroid Build Coastguard Worker const uint32_t next = operands_->GetOperand(operand_index_);
66*795d594fSAndroid Build Coastguard Worker operand_index_ += 2;
67*795d594fSAndroid Build Coastguard Worker return next;
68*795d594fSAndroid Build Coastguard Worker }
69*795d594fSAndroid Build Coastguard Worker
70*795d594fSAndroid Build Coastguard Worker const ShadowFrame& shadow_frame_;
71*795d594fSAndroid Build Coastguard Worker const InstructionOperands* const operands_; // the set of register operands to read
72*795d594fSAndroid Build Coastguard Worker size_t operand_index_; // the next register operand to read from frame
73*795d594fSAndroid Build Coastguard Worker };
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Worker // A convenience class that allows values to be written to a given shadow frame,
76*795d594fSAndroid Build Coastguard Worker // starting at location |first_dst_reg|.
77*795d594fSAndroid Build Coastguard Worker class ShadowFrameSetter {
78*795d594fSAndroid Build Coastguard Worker public:
ShadowFrameSetter(ShadowFrame * shadow_frame,size_t first_dst_reg)79*795d594fSAndroid Build Coastguard Worker ShadowFrameSetter(ShadowFrame* shadow_frame, size_t first_dst_reg)
80*795d594fSAndroid Build Coastguard Worker : shadow_frame_(shadow_frame), arg_index_(first_dst_reg) {}
81*795d594fSAndroid Build Coastguard Worker
Set(uint32_t value)82*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void Set(uint32_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
83*795d594fSAndroid Build Coastguard Worker DCHECK_LT(arg_index_, shadow_frame_->NumberOfVRegs());
84*795d594fSAndroid Build Coastguard Worker shadow_frame_->SetVReg(arg_index_++, value);
85*795d594fSAndroid Build Coastguard Worker }
86*795d594fSAndroid Build Coastguard Worker
SetReference(ObjPtr<mirror::Object> value)87*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void SetReference(ObjPtr<mirror::Object> value)
88*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
89*795d594fSAndroid Build Coastguard Worker DCHECK_LT(arg_index_, shadow_frame_->NumberOfVRegs());
90*795d594fSAndroid Build Coastguard Worker shadow_frame_->SetVRegReference(arg_index_++, value);
91*795d594fSAndroid Build Coastguard Worker }
92*795d594fSAndroid Build Coastguard Worker
SetLong(int64_t value)93*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void SetLong(int64_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
94*795d594fSAndroid Build Coastguard Worker DCHECK_LT(arg_index_, shadow_frame_->NumberOfVRegs());
95*795d594fSAndroid Build Coastguard Worker shadow_frame_->SetVRegLong(arg_index_, value);
96*795d594fSAndroid Build Coastguard Worker arg_index_ += 2;
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker
Done()99*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool Done() const {
100*795d594fSAndroid Build Coastguard Worker return arg_index_ == shadow_frame_->NumberOfVRegs();
101*795d594fSAndroid Build Coastguard Worker }
102*795d594fSAndroid Build Coastguard Worker
103*795d594fSAndroid Build Coastguard Worker private:
104*795d594fSAndroid Build Coastguard Worker ShadowFrame* shadow_frame_;
105*795d594fSAndroid Build Coastguard Worker size_t arg_index_;
106*795d594fSAndroid Build Coastguard Worker };
107*795d594fSAndroid Build Coastguard Worker
ConvertArgumentValue(const ThrowWrongMethodTypeFunction & throw_wmt,ObjPtr<mirror::Class> from,ObjPtr<mirror::Class> to,JValue * value)108*795d594fSAndroid Build Coastguard Worker inline bool ConvertArgumentValue(const ThrowWrongMethodTypeFunction& throw_wmt,
109*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> from,
110*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> to,
111*795d594fSAndroid Build Coastguard Worker /*inout*/ JValue* value) {
112*795d594fSAndroid Build Coastguard Worker if (from == to) {
113*795d594fSAndroid Build Coastguard Worker return true;
114*795d594fSAndroid Build Coastguard Worker }
115*795d594fSAndroid Build Coastguard Worker
116*795d594fSAndroid Build Coastguard Worker // `*value` may contain a bare heap pointer which is generally unsafe.
117*795d594fSAndroid Build Coastguard Worker // `ConvertJValueCommon()` saves `*value`, `from`, and `to` to Handles
118*795d594fSAndroid Build Coastguard Worker // where necessary to avoid issues if the heap changes.
119*795d594fSAndroid Build Coastguard Worker if (ConvertJValueCommon(throw_wmt, from, to, value)) {
120*795d594fSAndroid Build Coastguard Worker DCHECK(!Thread::Current()->IsExceptionPending());
121*795d594fSAndroid Build Coastguard Worker return true;
122*795d594fSAndroid Build Coastguard Worker } else {
123*795d594fSAndroid Build Coastguard Worker DCHECK(Thread::Current()->IsExceptionPending());
124*795d594fSAndroid Build Coastguard Worker value->SetJ(0);
125*795d594fSAndroid Build Coastguard Worker return false;
126*795d594fSAndroid Build Coastguard Worker }
127*795d594fSAndroid Build Coastguard Worker }
128*795d594fSAndroid Build Coastguard Worker
ConvertReturnValue(const ThrowWrongMethodTypeFunction & throw_wmt,ObjPtr<mirror::Class> from,ObjPtr<mirror::Class> to,JValue * value)129*795d594fSAndroid Build Coastguard Worker inline bool ConvertReturnValue(const ThrowWrongMethodTypeFunction& throw_wmt,
130*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> from,
131*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> to,
132*795d594fSAndroid Build Coastguard Worker /*inout*/ JValue* value) {
133*795d594fSAndroid Build Coastguard Worker if (to->GetPrimitiveType() == Primitive::kPrimVoid || from == to) {
134*795d594fSAndroid Build Coastguard Worker return true;
135*795d594fSAndroid Build Coastguard Worker }
136*795d594fSAndroid Build Coastguard Worker
137*795d594fSAndroid Build Coastguard Worker // `*value` may contain a bare heap pointer which is generally unsafe.
138*795d594fSAndroid Build Coastguard Worker // `ConvertJValueCommon()` saves `*value`, `from`, and `to` to Handles
139*795d594fSAndroid Build Coastguard Worker // where necessary to avoid issues if the heap changes.
140*795d594fSAndroid Build Coastguard Worker if (ConvertJValueCommon(throw_wmt, from, to, value)) {
141*795d594fSAndroid Build Coastguard Worker DCHECK(!Thread::Current()->IsExceptionPending());
142*795d594fSAndroid Build Coastguard Worker return true;
143*795d594fSAndroid Build Coastguard Worker } else {
144*795d594fSAndroid Build Coastguard Worker DCHECK(Thread::Current()->IsExceptionPending());
145*795d594fSAndroid Build Coastguard Worker value->SetJ(0);
146*795d594fSAndroid Build Coastguard Worker return false;
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker }
149*795d594fSAndroid Build Coastguard Worker
150*795d594fSAndroid Build Coastguard Worker template <typename FromPTypes, typename ToPTypes, typename G, typename S>
PerformConversions(const ThrowWrongMethodTypeFunction & throw_wmt,FromPTypes from_types,ToPTypes to_types,G * getter,S * setter)151*795d594fSAndroid Build Coastguard Worker bool PerformConversions(const ThrowWrongMethodTypeFunction& throw_wmt,
152*795d594fSAndroid Build Coastguard Worker FromPTypes from_types,
153*795d594fSAndroid Build Coastguard Worker ToPTypes to_types,
154*795d594fSAndroid Build Coastguard Worker G* getter,
155*795d594fSAndroid Build Coastguard Worker S* setter) {
156*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(from_types.GetLength(), to_types.GetLength());
157*795d594fSAndroid Build Coastguard Worker for (int32_t i = 0, length = to_types.GetLength(); i != length; ++i) {
158*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> from = from_types.Get(i);
159*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> to = to_types.Get(i);
160*795d594fSAndroid Build Coastguard Worker const Primitive::Type from_type = from->GetPrimitiveType();
161*795d594fSAndroid Build Coastguard Worker const Primitive::Type to_type = to->GetPrimitiveType();
162*795d594fSAndroid Build Coastguard Worker if (from == to) {
163*795d594fSAndroid Build Coastguard Worker // Easy case - the types are identical. Nothing left to do except to pass
164*795d594fSAndroid Build Coastguard Worker // the arguments along verbatim.
165*795d594fSAndroid Build Coastguard Worker if (Primitive::Is64BitType(from_type)) {
166*795d594fSAndroid Build Coastguard Worker setter->SetLong(getter->GetLong());
167*795d594fSAndroid Build Coastguard Worker } else if (from_type == Primitive::kPrimNot) {
168*795d594fSAndroid Build Coastguard Worker setter->SetReference(getter->GetReference());
169*795d594fSAndroid Build Coastguard Worker } else {
170*795d594fSAndroid Build Coastguard Worker setter->Set(getter->Get());
171*795d594fSAndroid Build Coastguard Worker }
172*795d594fSAndroid Build Coastguard Worker } else {
173*795d594fSAndroid Build Coastguard Worker JValue value;
174*795d594fSAndroid Build Coastguard Worker if (Primitive::Is64BitType(from_type)) {
175*795d594fSAndroid Build Coastguard Worker value.SetJ(getter->GetLong());
176*795d594fSAndroid Build Coastguard Worker } else if (from_type == Primitive::kPrimNot) {
177*795d594fSAndroid Build Coastguard Worker value.SetL(getter->GetReference());
178*795d594fSAndroid Build Coastguard Worker } else {
179*795d594fSAndroid Build Coastguard Worker value.SetI(getter->Get());
180*795d594fSAndroid Build Coastguard Worker }
181*795d594fSAndroid Build Coastguard Worker // Caveat emptor - ObjPtr's not guaranteed valid after this call.
182*795d594fSAndroid Build Coastguard Worker if (!ConvertArgumentValue(throw_wmt, from, to, &value)) {
183*795d594fSAndroid Build Coastguard Worker DCHECK(Thread::Current()->IsExceptionPending());
184*795d594fSAndroid Build Coastguard Worker return false;
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker if (Primitive::Is64BitType(to_type)) {
187*795d594fSAndroid Build Coastguard Worker setter->SetLong(value.GetJ());
188*795d594fSAndroid Build Coastguard Worker } else if (to_type == Primitive::kPrimNot) {
189*795d594fSAndroid Build Coastguard Worker setter->SetReference(value.GetL());
190*795d594fSAndroid Build Coastguard Worker } else {
191*795d594fSAndroid Build Coastguard Worker setter->Set(value.GetI());
192*795d594fSAndroid Build Coastguard Worker }
193*795d594fSAndroid Build Coastguard Worker }
194*795d594fSAndroid Build Coastguard Worker }
195*795d594fSAndroid Build Coastguard Worker return true;
196*795d594fSAndroid Build Coastguard Worker }
197*795d594fSAndroid Build Coastguard Worker
198*795d594fSAndroid Build Coastguard Worker template <typename G, typename S>
CopyArguments(Thread * self,Handle<mirror::MethodType> method_type,G * getter,S * setter)199*795d594fSAndroid Build Coastguard Worker bool CopyArguments(Thread* self,
200*795d594fSAndroid Build Coastguard Worker Handle<mirror::MethodType> method_type,
201*795d594fSAndroid Build Coastguard Worker G* getter,
202*795d594fSAndroid Build Coastguard Worker S* setter) REQUIRES_SHARED(Locks::mutator_lock_) {
203*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(self);
204*795d594fSAndroid Build Coastguard Worker Handle<mirror::ObjectArray<mirror::Class>> ptypes(hs.NewHandle(method_type->GetPTypes()));
205*795d594fSAndroid Build Coastguard Worker int32_t ptypes_length = ptypes->GetLength();
206*795d594fSAndroid Build Coastguard Worker
207*795d594fSAndroid Build Coastguard Worker for (int32_t i = 0; i < ptypes_length; ++i) {
208*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> ptype(ptypes->GetWithoutChecks(i));
209*795d594fSAndroid Build Coastguard Worker Primitive::Type primitive = ptype->GetPrimitiveType();
210*795d594fSAndroid Build Coastguard Worker if (Primitive::Is64BitType(primitive)) {
211*795d594fSAndroid Build Coastguard Worker setter->SetLong(getter->GetLong());
212*795d594fSAndroid Build Coastguard Worker } else if (primitive == Primitive::kPrimNot) {
213*795d594fSAndroid Build Coastguard Worker setter->SetReference(getter->GetReference());
214*795d594fSAndroid Build Coastguard Worker } else {
215*795d594fSAndroid Build Coastguard Worker setter->Set(getter->Get());
216*795d594fSAndroid Build Coastguard Worker }
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker return true;
219*795d594fSAndroid Build Coastguard Worker }
220*795d594fSAndroid Build Coastguard Worker
221*795d594fSAndroid Build Coastguard Worker } // namespace art
222*795d594fSAndroid Build Coastguard Worker
223*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_METHOD_HANDLES_INL_H_
224