blob: 7a77bda2626214eb0dc272d3bbf4aae0b9a962a9 [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"
23#include "dex_instruction.h"
24#include "interpreter/interpreter_common.h"
25#include "jvalue.h"
26#include "mirror/class.h"
27#include "mirror/method_type.h"
28#include "mirror/object.h"
29#include "reflection.h"
30#include "stack.h"
31
32namespace art {
33
34// Assigns |type| to the primitive type associated with |dst_class|. Returns
35// true iff. |dst_class| was a boxed type (Integer, Long etc.), false otherwise.
36REQUIRES_SHARED(Locks::mutator_lock_)
37static inline bool GetPrimitiveType(ObjPtr<mirror::Class> dst_class, Primitive::Type* type) {
38 if (dst_class->DescriptorEquals("Ljava/lang/Boolean;")) {
39 (*type) = Primitive::kPrimBoolean;
40 return true;
41 } else if (dst_class->DescriptorEquals("Ljava/lang/Byte;")) {
42 (*type) = Primitive::kPrimByte;
43 return true;
44 } else if (dst_class->DescriptorEquals("Ljava/lang/Character;")) {
45 (*type) = Primitive::kPrimChar;
46 return true;
47 } else if (dst_class->DescriptorEquals("Ljava/lang/Float;")) {
48 (*type) = Primitive::kPrimFloat;
49 return true;
50 } else if (dst_class->DescriptorEquals("Ljava/lang/Double;")) {
51 (*type) = Primitive::kPrimDouble;
52 return true;
53 } else if (dst_class->DescriptorEquals("Ljava/lang/Integer;")) {
54 (*type) = Primitive::kPrimInt;
55 return true;
56 } else if (dst_class->DescriptorEquals("Ljava/lang/Long;")) {
57 (*type) = Primitive::kPrimLong;
58 return true;
59 } else if (dst_class->DescriptorEquals("Ljava/lang/Short;")) {
60 (*type) = Primitive::kPrimShort;
61 return true;
62 } else {
63 return false;
64 }
65}
66
67// A convenience class that allows for iteration through a list of
68// input argument registers |arg| for non-range invokes or a list of
69// consecutive registers starting with a given based for range
70// invokes.
71template <bool is_range> class ArgIterator {
72 public:
73 ArgIterator(size_t first_src_reg,
74 const uint32_t (&arg)[Instruction::kMaxVarArgRegs]) :
75 first_src_reg_(first_src_reg),
76 arg_(arg),
77 arg_index_(0) {
78 }
79
80 uint32_t Next() {
81 const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
82 ++arg_index_;
83
84 return next;
85 }
86
87 uint32_t NextPair() {
88 const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]);
89 arg_index_ += 2;
90
91 return next;
92 }
93
94 private:
95 const size_t first_src_reg_;
96 const uint32_t (&arg_)[Instruction::kMaxVarArgRegs];
97 size_t arg_index_;
98};
99
Narayan Kamathda246502016-10-20 18:39:22 +0100100REQUIRES_SHARED(Locks::mutator_lock_)
101bool ConvertJValue(Handle<mirror::Class> from,
102 Handle<mirror::Class> to,
103 const JValue& from_value,
104 JValue* to_value) {
105 const Primitive::Type from_type = from->GetPrimitiveType();
106 const Primitive::Type to_type = to->GetPrimitiveType();
107
108 // This method must be called only when the types don't match.
109 DCHECK(from.Get() != to.Get());
110
111 if ((from_type != Primitive::kPrimNot) && (to_type != Primitive::kPrimNot)) {
112 // Throws a ClassCastException if we're unable to convert a primitive value.
113 return ConvertPrimitiveValue(false, from_type, to_type, from_value, to_value);
114 } else if ((from_type == Primitive::kPrimNot) && (to_type == Primitive::kPrimNot)) {
115 // They're both reference types. If "from" is null, we can pass it
116 // through unchanged. If not, we must generate a cast exception if
117 // |to| is not assignable from the dynamic type of |ref|.
118 mirror::Object* const ref = from_value.GetL();
119 if (ref == nullptr || to->IsAssignableFrom(ref->GetClass())) {
120 to_value->SetL(ref);
121 return true;
122 } else {
123 ThrowClassCastException(to.Get(), ref->GetClass());
124 return false;
125 }
126 } else {
127 // Precisely one of the source or the destination are reference types.
128 // We must box or unbox.
129 if (to_type == Primitive::kPrimNot) {
130 // The target type is a reference, we must box.
131 Primitive::Type type;
132 // TODO(narayan): This is a CHECK for now. There might be a few corner cases
133 // here that we might not have handled yet. For exmple, if |to| is java/lang/Number;,
134 // we will need to box this "naturally".
135 CHECK(GetPrimitiveType(to.Get(), &type));
136 // First perform a primitive conversion to the unboxed equivalent of the target,
137 // if necessary. This should be for the rarer cases like (int->Long) etc.
138 if (UNLIKELY(from_type != type)) {
139 if (!ConvertPrimitiveValue(false, from_type, type, from_value, to_value)) {
140 return false;
141 }
142 } else {
143 *to_value = from_value;
144 }
145
146 // Then perform the actual boxing, and then set the reference.
147 ObjPtr<mirror::Object> boxed = BoxPrimitive(type, from_value);
148 to_value->SetL(boxed.Ptr());
149 return true;
150 } else {
151 // The target type is a primitive, we must unbox.
152 ObjPtr<mirror::Object> ref(from_value.GetL());
153
154 // Note that UnboxPrimitiveForResult already performs all of the type
155 // conversions that we want, based on |to|.
156 JValue unboxed_value;
157 return UnboxPrimitiveForResult(ref, to.Get(), to_value);
158 }
159 }
160
161 return true;
162}
163
Narayan Kamath208f8572016-08-03 12:46:58 +0100164template <bool is_range>
165bool PerformArgumentConversions(Thread* self,
166 Handle<mirror::MethodType> callsite_type,
167 Handle<mirror::MethodType> callee_type,
168 const ShadowFrame& caller_frame,
169 uint32_t first_src_reg,
170 uint32_t first_dest_reg,
171 const uint32_t (&arg)[Instruction::kMaxVarArgRegs],
Narayan Kamathda246502016-10-20 18:39:22 +0100172 ShadowFrame* callee_frame) {
Narayan Kamath208f8572016-08-03 12:46:58 +0100173 StackHandleScope<4> 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 const int32_t num_method_params = from_types->GetLength();
178 if (to_types->GetLength() != num_method_params) {
179 ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
Narayan Kamath208f8572016-08-03 12:46:58 +0100180 return false;
181 }
182
183 ArgIterator<is_range> input_args(first_src_reg, arg);
184 size_t to_arg_index = 0;
185 MutableHandle<mirror::Class> from(hs.NewHandle<mirror::Class>(nullptr));
186 MutableHandle<mirror::Class> to(hs.NewHandle<mirror::Class>(nullptr));
187 for (int32_t i = 0; i < num_method_params; ++i) {
188 from.Assign(from_types->GetWithoutChecks(i));
189 to.Assign(to_types->GetWithoutChecks(i));
190
191 const Primitive::Type from_type = from->GetPrimitiveType();
192 const Primitive::Type to_type = to->GetPrimitiveType();
193
194 // Easy case - the types are identical. Nothing left to do except to pass
195 // the arguments along verbatim.
196 if (from.Get() == to.Get()) {
197 interpreter::AssignRegister(callee_frame,
198 caller_frame,
199 first_dest_reg + to_arg_index,
200 input_args.Next());
201 ++to_arg_index;
202
203 // This is a wide argument, we must use the second half of the register
204 // pair as well.
205 if (Primitive::Is64BitType(from_type)) {
206 interpreter::AssignRegister(callee_frame,
207 caller_frame,
208 first_dest_reg + to_arg_index,
209 input_args.Next());
210 ++to_arg_index;
211 }
212
213 continue;
Narayan Kamathda246502016-10-20 18:39:22 +0100214 } else {
Narayan Kamath208f8572016-08-03 12:46:58 +0100215 JValue from_value;
216 JValue to_value;
217
218 if (Primitive::Is64BitType(from_type)) {
219 from_value.SetJ(caller_frame.GetVRegLong(input_args.NextPair()));
Narayan Kamathda246502016-10-20 18:39:22 +0100220 } else if (from_type == Primitive::kPrimNot) {
221 from_value.SetL(caller_frame.GetVRegReference(input_args.Next()));
Narayan Kamath208f8572016-08-03 12:46:58 +0100222 } else {
223 from_value.SetI(caller_frame.GetVReg(input_args.Next()));
224 }
225
Narayan Kamathda246502016-10-20 18:39:22 +0100226 if (!ConvertJValue(from, to, from_value, &to_value)) {
Narayan Kamath208f8572016-08-03 12:46:58 +0100227 DCHECK(self->IsExceptionPending());
Narayan Kamath208f8572016-08-03 12:46:58 +0100228 return false;
229 }
230
231 if (Primitive::Is64BitType(to_type)) {
232 callee_frame->SetVRegLong(first_dest_reg + to_arg_index, to_value.GetJ());
233 to_arg_index += 2;
Narayan Kamathda246502016-10-20 18:39:22 +0100234 } else if (to_type == Primitive::kPrimNot) {
235 callee_frame->SetVRegReference(first_dest_reg + to_arg_index, to_value.GetL());
236 ++to_arg_index;
Narayan Kamath208f8572016-08-03 12:46:58 +0100237 } else {
238 callee_frame->SetVReg(first_dest_reg + to_arg_index, to_value.GetI());
239 ++to_arg_index;
240 }
Narayan Kamath208f8572016-08-03 12:46:58 +0100241 }
242 }
243
244 return true;
245}
246
247} // namespace art
248
249#endif // ART_RUNTIME_METHOD_HANDLES_INL_H_