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