1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_METHOD_HANDLES_INL_H_
18 #define ART_RUNTIME_METHOD_HANDLES_INL_H_
19 
20 #include "method_handles.h"
21 
22 #include "common_throws.h"
23 #include "dex/dex_instruction.h"
24 #include "interpreter/interpreter_common.h"
25 #include "interpreter/shadow_frame-inl.h"
26 #include "jvalue-inl.h"
27 #include "mirror/class.h"
28 #include "mirror/method_type-inl.h"
29 #include "mirror/object.h"
30 #include "reflection.h"
31 #include "stack.h"
32 
33 namespace art {
34 
35 // A convenience class that allows for iteration through a list of
36 // input argument registers. This is used to iterate over input
37 // arguments while performing standard argument conversions.
38 class ShadowFrameGetter {
39  public:
40   ShadowFrameGetter(const ShadowFrame& shadow_frame,
41                     const InstructionOperands* const operands,
42                     size_t operand_index = 0u)
shadow_frame_(shadow_frame)43       : shadow_frame_(shadow_frame), operands_(operands), operand_index_(operand_index)  {}
44 
Get()45   ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) {
46     return shadow_frame_.GetVReg(Next());
47   }
48 
GetLong()49   ALWAYS_INLINE int64_t GetLong() REQUIRES_SHARED(Locks::mutator_lock_) {
50     return shadow_frame_.GetVRegLong(NextLong());
51   }
52 
GetReference()53   ALWAYS_INLINE ObjPtr<mirror::Object> GetReference() REQUIRES_SHARED(Locks::mutator_lock_) {
54     return shadow_frame_.GetVRegReference(Next());
55   }
56 
57  private:
Next()58   uint32_t Next() {
59     const uint32_t next = operands_->GetOperand(operand_index_);
60     operand_index_ += 1;
61     return next;
62   }
63 
NextLong()64   uint32_t NextLong() {
65     const uint32_t next = operands_->GetOperand(operand_index_);
66     operand_index_ += 2;
67     return next;
68   }
69 
70   const ShadowFrame& shadow_frame_;
71   const InstructionOperands* const operands_;  // the set of register operands to read
72   size_t operand_index_;  // the next register operand to read from frame
73 };
74 
75 // A convenience class that allows values to be written to a given shadow frame,
76 // starting at location |first_dst_reg|.
77 class ShadowFrameSetter {
78  public:
ShadowFrameSetter(ShadowFrame * shadow_frame,size_t first_dst_reg)79   ShadowFrameSetter(ShadowFrame* shadow_frame, size_t first_dst_reg)
80       : shadow_frame_(shadow_frame), arg_index_(first_dst_reg) {}
81 
Set(uint32_t value)82   ALWAYS_INLINE void Set(uint32_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
83     DCHECK_LT(arg_index_, shadow_frame_->NumberOfVRegs());
84     shadow_frame_->SetVReg(arg_index_++, value);
85   }
86 
SetReference(ObjPtr<mirror::Object> value)87   ALWAYS_INLINE void SetReference(ObjPtr<mirror::Object> value)
88       REQUIRES_SHARED(Locks::mutator_lock_) {
89     DCHECK_LT(arg_index_, shadow_frame_->NumberOfVRegs());
90     shadow_frame_->SetVRegReference(arg_index_++, value);
91   }
92 
SetLong(int64_t value)93   ALWAYS_INLINE void SetLong(int64_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
94     DCHECK_LT(arg_index_, shadow_frame_->NumberOfVRegs());
95     shadow_frame_->SetVRegLong(arg_index_, value);
96     arg_index_ += 2;
97   }
98 
Done()99   ALWAYS_INLINE bool Done() const {
100     return arg_index_ == shadow_frame_->NumberOfVRegs();
101   }
102 
103  private:
104   ShadowFrame* shadow_frame_;
105   size_t arg_index_;
106 };
107 
ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,ObjPtr<mirror::Class> from_class,ObjPtr<mirror::Class> to_class,JValue * value)108 inline bool ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,
109                                  Handle<mirror::MethodType> callee_type,
110                                  ObjPtr<mirror::Class> from_class,
111                                  ObjPtr<mirror::Class> to_class,
112                                  JValue* value) REQUIRES_SHARED(Locks::mutator_lock_) {
113   if (from_class == to_class) {
114     return true;
115   }
116 
117   // |value| may contain a bare heap pointer which is generally
118   // |unsafe. ConvertJValueCommon() saves |value|, |from_class|, and
119   // |to_class| to Handles where necessary to avoid issues if the heap
120   // changes.
121   if (ConvertJValueCommon(callsite_type, callee_type, from_class, to_class, value)) {
122     DCHECK(!Thread::Current()->IsExceptionPending());
123     return true;
124   } else {
125     DCHECK(Thread::Current()->IsExceptionPending());
126     value->SetJ(0);
127     return false;
128   }
129 }
130 
ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,int index,JValue * value)131 inline bool ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,
132                                  Handle<mirror::MethodType> callee_type,
133                                  int index,
134                                  JValue* value) REQUIRES_SHARED(Locks::mutator_lock_) {
135   return ConvertArgumentValue(callsite_type,
136                               callee_type,
137                               callsite_type->GetPTypes()->GetWithoutChecks(index),
138                               callee_type->GetPTypes()->GetWithoutChecks(index),
139                               value);
140 }
141 
ConvertReturnValue(Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,JValue * value)142 inline bool ConvertReturnValue(Handle<mirror::MethodType> callsite_type,
143                                Handle<mirror::MethodType> callee_type,
144                                JValue* value)  REQUIRES_SHARED(Locks::mutator_lock_) {
145   ObjPtr<mirror::Class> from_class(callee_type->GetRType());
146   ObjPtr<mirror::Class> to_class(callsite_type->GetRType());
147   if (to_class->GetPrimitiveType() == Primitive::kPrimVoid || from_class == to_class) {
148     return true;
149   }
150 
151   // |value| may contain a bare heap pointer which is generally
152   // unsafe. ConvertJValueCommon() saves |value|, |from_class|, and
153   // |to_class| to Handles where necessary to avoid issues if the heap
154   // changes.
155   if (ConvertJValueCommon(callsite_type, callee_type, from_class, to_class, value)) {
156     DCHECK(!Thread::Current()->IsExceptionPending());
157     return true;
158   } else {
159     DCHECK(Thread::Current()->IsExceptionPending());
160     value->SetJ(0);
161     return false;
162   }
163 }
164 
165 template <typename G, typename S>
PerformConversions(Thread * self,Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,G * getter,S * setter,int32_t start_index,int32_t end_index)166 bool PerformConversions(Thread* self,
167                         Handle<mirror::MethodType> callsite_type,
168                         Handle<mirror::MethodType> callee_type,
169                         G* getter,
170                         S* setter,
171                         int32_t start_index,
172                         int32_t end_index) REQUIRES_SHARED(Locks::mutator_lock_) {
173   StackHandleScope<2> hs(self);
174   Handle<mirror::ObjectArray<mirror::Class>> from_types(hs.NewHandle(callsite_type->GetPTypes()));
175   Handle<mirror::ObjectArray<mirror::Class>> to_types(hs.NewHandle(callee_type->GetPTypes()));
176 
177   for (int32_t i = start_index; i < end_index; ++i) {
178     ObjPtr<mirror::Class> from(from_types->GetWithoutChecks(i));
179     ObjPtr<mirror::Class> to(to_types->GetWithoutChecks(i - start_index));
180     const Primitive::Type from_type = from->GetPrimitiveType();
181     const Primitive::Type to_type = to->GetPrimitiveType();
182     if (from == to) {
183       // Easy case - the types are identical. Nothing left to do except to pass
184       // the arguments along verbatim.
185       if (Primitive::Is64BitType(from_type)) {
186         setter->SetLong(getter->GetLong());
187       } else if (from_type == Primitive::kPrimNot) {
188         setter->SetReference(getter->GetReference());
189       } else {
190         setter->Set(getter->Get());
191       }
192     } else {
193       JValue value;
194       if (Primitive::Is64BitType(from_type)) {
195         value.SetJ(getter->GetLong());
196       } else if (from_type == Primitive::kPrimNot) {
197         value.SetL(getter->GetReference());
198       } else {
199         value.SetI(getter->Get());
200       }
201       // Caveat emptor - ObjPtr's not guaranteed valid after this call.
202       if (!ConvertArgumentValue(callsite_type, callee_type, from, to, &value)) {
203         DCHECK(self->IsExceptionPending());
204         return false;
205       }
206       if (Primitive::Is64BitType(to_type)) {
207         setter->SetLong(value.GetJ());
208       } else if (to_type == Primitive::kPrimNot) {
209         setter->SetReference(value.GetL());
210       } else {
211         setter->Set(value.GetI());
212       }
213     }
214   }
215   return true;
216 }
217 
218 template <typename G, typename S>
PerformConversions(Thread * self,Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,G * getter,S * setter,int32_t num_conversions)219 bool PerformConversions(Thread* self,
220                         Handle<mirror::MethodType> callsite_type,
221                         Handle<mirror::MethodType> callee_type,
222                         G* getter,
223                         S* setter,
224                         int32_t num_conversions)
225     REQUIRES_SHARED(Locks::mutator_lock_) {
226   return PerformConversions(self, callsite_type, callee_type, getter, setter, 0, num_conversions);
227 }
228 
229 template <typename G, typename S>
PerformConversions(Thread * self,Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,G * getter,S * setter)230 bool PerformConversions(Thread* self,
231                         Handle<mirror::MethodType> callsite_type,
232                         Handle<mirror::MethodType> callee_type,
233                         G* getter,
234                         S* setter)
235     REQUIRES_SHARED(Locks::mutator_lock_) {
236   int32_t num_conversions = callee_type->GetPTypes()->GetLength();
237   return PerformConversions(self, callsite_type, callee_type, getter, setter, 0, num_conversions);
238 }
239 
240 }  // namespace art
241 
242 #endif  // ART_RUNTIME_METHOD_HANDLES_INL_H_
243