blob: 4bd4df10d2dd82a4ce1b3cb4d14dfff99eafa8c8 [file] [log] [blame]
Narayan Kamath208f8572016-08-03 12:46:58 +01001/*
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"
David Sehr9e734c72018-01-04 17:56:19 -080023#include "dex/dex_instruction.h"
Narayan Kamath208f8572016-08-03 12:46:58 +010024#include "interpreter/interpreter_common.h"
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010025#include "interpreter/shadow_frame-inl.h"
Andreas Gampec5b75642018-05-16 15:12:11 -070026#include "jvalue-inl.h"
Narayan Kamath208f8572016-08-03 12:46:58 +010027#include "mirror/class.h"
Vladimir Marko5aead702019-03-27 11:00:36 +000028#include "mirror/method_type-inl.h"
Narayan Kamath208f8572016-08-03 12:46:58 +010029#include "mirror/object.h"
30#include "reflection.h"
31#include "stack.h"
32
33namespace art {
34
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010035// 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.
38class ShadowFrameGetter {
39 public:
40 ShadowFrameGetter(const ShadowFrame& shadow_frame,
41 const InstructionOperands* const operands,
42 size_t operand_index = 0u)
43 : shadow_frame_(shadow_frame), operands_(operands), operand_index_(operand_index) {}
44
45 ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) {
46 return shadow_frame_.GetVReg(Next());
47 }
48
49 ALWAYS_INLINE int64_t GetLong() REQUIRES_SHARED(Locks::mutator_lock_) {
50 return shadow_frame_.GetVRegLong(NextLong());
51 }
52
53 ALWAYS_INLINE ObjPtr<mirror::Object> GetReference() REQUIRES_SHARED(Locks::mutator_lock_) {
54 return shadow_frame_.GetVRegReference(Next());
55 }
56
57 private:
58 uint32_t Next() {
59 const uint32_t next = operands_->GetOperand(operand_index_);
60 operand_index_ += 1;
61 return next;
62 }
63
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|.
77class ShadowFrameSetter {
78 public:
79 ShadowFrameSetter(ShadowFrame* shadow_frame, size_t first_dst_reg)
80 : shadow_frame_(shadow_frame), arg_index_(first_dst_reg) {}
81
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
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
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
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
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100108inline bool ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,
109 Handle<mirror::MethodType> callee_type,
Orion Hodsonb8b93872018-01-30 07:51:10 +0000110 ObjPtr<mirror::Class> from_class,
111 ObjPtr<mirror::Class> to_class,
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100112 JValue* value) REQUIRES_SHARED(Locks::mutator_lock_) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100113 if (from_class == to_class) {
Narayan Kamath208f8572016-08-03 12:46:58 +0100114 return true;
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100115 }
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());
Narayan Kamath208f8572016-08-03 12:46:58 +0100123 return true;
124 } else {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100125 DCHECK(Thread::Current()->IsExceptionPending());
126 value->SetJ(0);
Narayan Kamath208f8572016-08-03 12:46:58 +0100127 return false;
128 }
129}
130
Orion Hodsonb8b93872018-01-30 07:51:10 +0000131inline 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
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100142inline 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;
Narayan Kamathda246502016-10-20 18:39:22 +0100149 }
150
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100151 // |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 }
Narayan Kamathda246502016-10-20 18:39:22 +0100163}
164
Narayan Kamath000e1882016-10-24 17:14:25 +0100165template <typename G, typename S>
166bool PerformConversions(Thread* self,
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100167 Handle<mirror::MethodType> callsite_type,
168 Handle<mirror::MethodType> callee_type,
Narayan Kamath000e1882016-10-24 17:14:25 +0100169 G* getter,
170 S* setter,
Orion Hodsonb8b93872018-01-30 07:51:10 +0000171 int32_t start_index,
172 int32_t end_index) REQUIRES_SHARED(Locks::mutator_lock_) {
Narayan Kamath000e1882016-10-24 17:14:25 +0100173 StackHandleScope<2> hs(self);
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100174 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()));
Narayan Kamath000e1882016-10-24 17:14:25 +0100176
Orion Hodsonb8b93872018-01-30 07:51:10 +0000177 for (int32_t i = start_index; i < end_index; ++i) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100178 ObjPtr<mirror::Class> from(from_types->GetWithoutChecks(i));
Orion Hodsonb8b93872018-01-30 07:51:10 +0000179 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();
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100182 if (from == to) {
Narayan Kamath000e1882016-10-24 17:14:25 +0100183 // 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 }
Narayan Kamath000e1882016-10-24 17:14:25 +0100192 } else {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100193 JValue value;
Narayan Kamath000e1882016-10-24 17:14:25 +0100194 if (Primitive::Is64BitType(from_type)) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100195 value.SetJ(getter->GetLong());
Narayan Kamath000e1882016-10-24 17:14:25 +0100196 } else if (from_type == Primitive::kPrimNot) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100197 value.SetL(getter->GetReference());
Narayan Kamath000e1882016-10-24 17:14:25 +0100198 } else {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100199 value.SetI(getter->Get());
Narayan Kamath000e1882016-10-24 17:14:25 +0100200 }
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100201 // Caveat emptor - ObjPtr's not guaranteed valid after this call.
Orion Hodsonb8b93872018-01-30 07:51:10 +0000202 if (!ConvertArgumentValue(callsite_type, callee_type, from, to, &value)) {
Narayan Kamath000e1882016-10-24 17:14:25 +0100203 DCHECK(self->IsExceptionPending());
204 return false;
205 }
Narayan Kamath000e1882016-10-24 17:14:25 +0100206 if (Primitive::Is64BitType(to_type)) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100207 setter->SetLong(value.GetJ());
Narayan Kamath000e1882016-10-24 17:14:25 +0100208 } else if (to_type == Primitive::kPrimNot) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100209 setter->SetReference(value.GetL());
Narayan Kamath000e1882016-10-24 17:14:25 +0100210 } else {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100211 setter->Set(value.GetI());
Narayan Kamath000e1882016-10-24 17:14:25 +0100212 }
213 }
214 }
Narayan Kamath000e1882016-10-24 17:14:25 +0100215 return true;
216}
217
Orion Hodsonb8b93872018-01-30 07:51:10 +0000218template <typename G, typename S>
219bool 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
229template <typename G, typename S>
230bool 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
Narayan Kamath208f8572016-08-03 12:46:58 +0100240} // namespace art
241
242#endif // ART_RUNTIME_METHOD_HANDLES_INL_H_