blob: aeeb05b62c11c1ffa0395309468b33ba6d6dce53 [file] [log] [blame]
Orion Hodsonba28f9f2016-10-26 10:56:25 +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
Orion Hodsonba28f9f2016-10-26 10:56:25 +010017#include "method_handles-inl.h"
Andreas Gampe46ee31b2016-12-14 10:11:49 -080018
19#include "android-base/stringprintf.h"
20
Vladimir Markoc7aa87e2018-05-24 15:19:52 +010021#include "class_root.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000022#include "common_dex_operations.h"
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010023#include "interpreter/shadow_frame-inl.h"
Orion Hodsonba28f9f2016-10-26 10:56:25 +010024#include "jvalue-inl.h"
Andreas Gampe88dbad32018-06-26 19:54:12 -070025#include "mirror/class-inl.h"
Vladimir Marko423bebb2019-03-26 15:17:21 +000026#include "mirror/emulated_stack_frame-inl.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080027#include "mirror/method_handle_impl-inl.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000028#include "mirror/method_type.h"
Orion Hodsonb8b93872018-01-30 07:51:10 +000029#include "mirror/var_handle.h"
Orion Hodsonba28f9f2016-10-26 10:56:25 +010030#include "reflection-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070031#include "reflection.h"
Orion Hodson1a06f9f2016-11-09 08:32:42 +000032#include "well_known_classes.h"
Orion Hodsonba28f9f2016-10-26 10:56:25 +010033
34namespace art {
35
Andreas Gampe46ee31b2016-12-14 10:11:49 -080036using android::base::StringPrintf;
37
Orion Hodsonba28f9f2016-10-26 10:56:25 +010038namespace {
39
Orion Hodson1a06f9f2016-11-09 08:32:42 +000040#define PRIMITIVES_LIST(V) \
41 V(Primitive::kPrimBoolean, Boolean, Boolean, Z) \
42 V(Primitive::kPrimByte, Byte, Byte, B) \
43 V(Primitive::kPrimChar, Char, Character, C) \
44 V(Primitive::kPrimShort, Short, Short, S) \
45 V(Primitive::kPrimInt, Int, Integer, I) \
46 V(Primitive::kPrimLong, Long, Long, J) \
47 V(Primitive::kPrimFloat, Float, Float, F) \
48 V(Primitive::kPrimDouble, Double, Double, D)
Orion Hodsonba28f9f2016-10-26 10:56:25 +010049
50// Assigns |type| to the primitive type associated with |klass|. Returns
51// true iff. |klass| was a boxed type (Integer, Long etc.), false otherwise.
52bool GetUnboxedPrimitiveType(ObjPtr<mirror::Class> klass, Primitive::Type* type)
53 REQUIRES_SHARED(Locks::mutator_lock_) {
54 ScopedAssertNoThreadSuspension ants(__FUNCTION__);
Orion Hodsona1be7132017-03-21 10:04:12 +000055 std::string storage;
56 const char* descriptor = klass->GetDescriptor(&storage);
57 static const char kJavaLangPrefix[] = "Ljava/lang/";
58 static const size_t kJavaLangPrefixSize = sizeof(kJavaLangPrefix) - 1;
59 if (strncmp(descriptor, kJavaLangPrefix, kJavaLangPrefixSize) != 0) {
60 return false;
61 }
62
63 descriptor += kJavaLangPrefixSize;
64#define LOOKUP_PRIMITIVE(primitive, _, java_name, ___) \
65 if (strcmp(descriptor, #java_name ";") == 0) { \
66 *type = primitive; \
67 return true; \
Orion Hodsonba28f9f2016-10-26 10:56:25 +010068 }
Orion Hodsonba28f9f2016-10-26 10:56:25 +010069
Orion Hodson1a06f9f2016-11-09 08:32:42 +000070 PRIMITIVES_LIST(LOOKUP_PRIMITIVE);
71#undef LOOKUP_PRIMITIVE
Orion Hodsonba28f9f2016-10-26 10:56:25 +010072 return false;
73}
74
Orion Hodson1a06f9f2016-11-09 08:32:42 +000075ObjPtr<mirror::Class> GetBoxedPrimitiveClass(Primitive::Type type)
Orion Hodsonba28f9f2016-10-26 10:56:25 +010076 REQUIRES_SHARED(Locks::mutator_lock_) {
Orion Hodson1a06f9f2016-11-09 08:32:42 +000077 ScopedAssertNoThreadSuspension ants(__FUNCTION__);
78 jmethodID m = nullptr;
79 switch (type) {
80#define CASE_PRIMITIVE(primitive, _, java_name, __) \
81 case primitive: \
82 m = WellKnownClasses::java_lang_ ## java_name ## _valueOf; \
83 break;
84 PRIMITIVES_LIST(CASE_PRIMITIVE);
85#undef CASE_PRIMITIVE
86 case Primitive::Type::kPrimNot:
87 case Primitive::Type::kPrimVoid:
88 return nullptr;
Orion Hodsonba28f9f2016-10-26 10:56:25 +010089 }
Orion Hodson1a06f9f2016-11-09 08:32:42 +000090 return jni::DecodeArtMethod(m)->GetDeclaringClass();
91}
Orion Hodsonba28f9f2016-10-26 10:56:25 +010092
Orion Hodson1a06f9f2016-11-09 08:32:42 +000093bool GetUnboxedTypeAndValue(ObjPtr<mirror::Object> o, Primitive::Type* type, JValue* value)
94 REQUIRES_SHARED(Locks::mutator_lock_) {
95 ScopedAssertNoThreadSuspension ants(__FUNCTION__);
Orion Hodsonba28f9f2016-10-26 10:56:25 +010096 ObjPtr<mirror::Class> klass = o->GetClass();
Orion Hodsonba28f9f2016-10-26 10:56:25 +010097 ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0);
Orion Hodson1a06f9f2016-11-09 08:32:42 +000098#define CASE_PRIMITIVE(primitive, abbrev, _, shorthand) \
99 if (klass == GetBoxedPrimitiveClass(primitive)) { \
100 *type = primitive; \
101 value->Set ## shorthand(primitive_field->Get ## abbrev(o)); \
102 return true; \
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100103 }
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000104 PRIMITIVES_LIST(CASE_PRIMITIVE)
105#undef CASE_PRIMITIVE
106 return false;
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100107}
108
109inline bool IsReferenceType(Primitive::Type type) {
110 return type == Primitive::kPrimNot;
111}
112
113inline bool IsPrimitiveType(Primitive::Type type) {
114 return !IsReferenceType(type);
115}
116
117} // namespace
118
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000119bool IsParameterTypeConvertible(ObjPtr<mirror::Class> from, ObjPtr<mirror::Class> to)
120 REQUIRES_SHARED(Locks::mutator_lock_) {
121 // This function returns true if there's any conceivable conversion
122 // between |from| and |to|. It's expected this method will be used
123 // to determine if a WrongMethodTypeException should be raised. The
124 // decision logic follows the documentation for MethodType.asType().
125 if (from == to) {
126 return true;
127 }
128
129 Primitive::Type from_primitive = from->GetPrimitiveType();
130 Primitive::Type to_primitive = to->GetPrimitiveType();
131 DCHECK(from_primitive != Primitive::Type::kPrimVoid);
132 DCHECK(to_primitive != Primitive::Type::kPrimVoid);
133
134 // If |to| and |from| are references.
135 if (IsReferenceType(from_primitive) && IsReferenceType(to_primitive)) {
136 // Assignability is determined during parameter conversion when
137 // invoking the associated method handle.
138 return true;
139 }
140
141 // If |to| and |from| are primitives and a widening conversion exists.
142 if (Primitive::IsWidenable(from_primitive, to_primitive)) {
143 return true;
144 }
145
146 // If |to| is a reference and |from| is a primitive, then boxing conversion.
147 if (IsReferenceType(to_primitive) && IsPrimitiveType(from_primitive)) {
148 return to->IsAssignableFrom(GetBoxedPrimitiveClass(from_primitive));
149 }
150
151 // If |from| is a reference and |to| is a primitive, then unboxing conversion.
152 if (IsPrimitiveType(to_primitive) && IsReferenceType(from_primitive)) {
153 if (from->DescriptorEquals("Ljava/lang/Object;")) {
154 // Object might be converted into a primitive during unboxing.
155 return true;
Orion Hodsona1be7132017-03-21 10:04:12 +0000156 }
157
158 if (Primitive::IsNumericType(to_primitive) && from->DescriptorEquals("Ljava/lang/Number;")) {
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000159 // Number might be unboxed into any of the number primitive types.
160 return true;
161 }
Orion Hodsona1be7132017-03-21 10:04:12 +0000162
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000163 Primitive::Type unboxed_type;
164 if (GetUnboxedPrimitiveType(from, &unboxed_type)) {
Orion Hodsonf1412b42016-11-11 12:03:29 +0000165 if (unboxed_type == to_primitive) {
166 // Straightforward unboxing conversion such as Boolean => boolean.
167 return true;
Orion Hodsonf1412b42016-11-11 12:03:29 +0000168 }
Orion Hodsona1be7132017-03-21 10:04:12 +0000169
170 // Check if widening operations for numeric primitives would work,
171 // such as Byte => byte => long.
172 return Primitive::IsWidenable(unboxed_type, to_primitive);
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000173 }
174 }
175
176 return false;
177}
178
179bool IsReturnTypeConvertible(ObjPtr<mirror::Class> from, ObjPtr<mirror::Class> to)
180 REQUIRES_SHARED(Locks::mutator_lock_) {
181 if (to->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
182 // Result will be ignored.
183 return true;
184 } else if (from->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
185 // Returned value will be 0 / null.
186 return true;
187 } else {
188 // Otherwise apply usual parameter conversion rules.
189 return IsParameterTypeConvertible(from, to);
190 }
191}
192
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100193bool ConvertJValueCommon(
194 Handle<mirror::MethodType> callsite_type,
195 Handle<mirror::MethodType> callee_type,
196 ObjPtr<mirror::Class> from,
197 ObjPtr<mirror::Class> to,
198 JValue* value) {
199 // The reader maybe concerned about the safety of the heap object
200 // that may be in |value|. There is only one case where allocation
201 // is obviously needed and that's for boxing. However, in the case
202 // of boxing |value| contains a non-reference type.
203
204 const Primitive::Type from_type = from->GetPrimitiveType();
205 const Primitive::Type to_type = to->GetPrimitiveType();
206
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000207 // Put incoming value into |src_value| and set return value to 0.
208 // Errors and conversions from void require the return value to be 0.
209 const JValue src_value(*value);
210 value->SetJ(0);
211
212 // Conversion from void set result to zero.
213 if (from_type == Primitive::kPrimVoid) {
214 return true;
215 }
216
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100217 // This method must be called only when the types don't match.
218 DCHECK(from != to);
219
220 if (IsPrimitiveType(from_type) && IsPrimitiveType(to_type)) {
221 // The source and target types are both primitives.
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000222 if (UNLIKELY(!ConvertPrimitiveValueNoThrow(from_type, to_type, src_value, value))) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100223 ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100224 return false;
225 }
226 return true;
227 } else if (IsReferenceType(from_type) && IsReferenceType(to_type)) {
228 // They're both reference types. If "from" is null, we can pass it
229 // through unchanged. If not, we must generate a cast exception if
230 // |to| is not assignable from the dynamic type of |ref|.
231 //
232 // Playing it safe with StackHandleScope here, not expecting any allocation
233 // in mirror::Class::IsAssignable().
234 StackHandleScope<2> hs(Thread::Current());
235 Handle<mirror::Class> h_to(hs.NewHandle(to));
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000236 Handle<mirror::Object> h_obj(hs.NewHandle(src_value.GetL()));
Orion Hodsonc1d3bac2018-01-26 14:38:55 +0000237 if (UNLIKELY(!h_obj.IsNull() && !to->IsAssignableFrom(h_obj->GetClass()))) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100238 ThrowClassCastException(h_to.Get(), h_obj->GetClass());
239 return false;
240 }
241 value->SetL(h_obj.Get());
242 return true;
243 } else if (IsReferenceType(to_type)) {
244 DCHECK(IsPrimitiveType(from_type));
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100245 // The source type is a primitive and the target type is a reference, so we must box.
246 // The target type maybe a super class of the boxed source type, for example,
247 // if the source type is int, it's boxed type is java.lang.Integer, and the target
248 // type could be java.lang.Number.
249 Primitive::Type type;
250 if (!GetUnboxedPrimitiveType(to, &type)) {
251 ObjPtr<mirror::Class> boxed_from_class = GetBoxedPrimitiveClass(from_type);
Orion Hodsonc1d3bac2018-01-26 14:38:55 +0000252 if (LIKELY(boxed_from_class->IsSubClass(to))) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100253 type = from_type;
254 } else {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100255 ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
256 return false;
257 }
258 }
259
260 if (UNLIKELY(from_type != type)) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100261 ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
262 return false;
263 }
264
Orion Hodsonc1d3bac2018-01-26 14:38:55 +0000265 if (UNLIKELY(!ConvertPrimitiveValueNoThrow(from_type, type, src_value, value))) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100266 ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
267 return false;
268 }
269
270 // Then perform the actual boxing, and then set the reference.
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000271 ObjPtr<mirror::Object> boxed = BoxPrimitive(type, src_value);
Vladimir Markobcf17522018-06-01 13:14:32 +0100272 value->SetL(boxed);
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100273 return true;
274 } else {
275 // The source type is a reference and the target type is a primitive, so we must unbox.
276 DCHECK(IsReferenceType(from_type));
277 DCHECK(IsPrimitiveType(to_type));
278
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000279 ObjPtr<mirror::Object> from_obj(src_value.GetL());
Orion Hodsonc1d3bac2018-01-26 14:38:55 +0000280 if (UNLIKELY(from_obj.IsNull())) {
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000281 ThrowNullPointerException(
282 StringPrintf("Expected to unbox a '%s' primitive type but was returned null",
283 from->PrettyDescriptor().c_str()).c_str());
284 return false;
285 }
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100286
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000287 Primitive::Type unboxed_type;
288 JValue unboxed_value;
289 if (UNLIKELY(!GetUnboxedTypeAndValue(from_obj, &unboxed_type, &unboxed_value))) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100290 ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
291 return false;
292 }
293
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000294 if (UNLIKELY(!ConvertPrimitiveValueNoThrow(unboxed_type, to_type, unboxed_value, value))) {
Orion Hodsonc1d3bac2018-01-26 14:38:55 +0000295 if (from->IsAssignableFrom(GetBoxedPrimitiveClass(to_type))) {
296 // CallSite may be Number, but the Number object is
297 // incompatible, e.g. Number (Integer) for a short.
298 ThrowClassCastException(from, to);
299 } else {
300 // CallSite is incompatible, e.g. Integer for a short.
301 ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
302 }
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100303 return false;
304 }
305
Orion Hodson1a06f9f2016-11-09 08:32:42 +0000306 return true;
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100307 }
308}
309
Orion Hodson811bd5f2016-12-07 11:35:37 +0000310namespace {
311
Orion Hodson811bd5f2016-12-07 11:35:37 +0000312inline void CopyArgumentsFromCallerFrame(const ShadowFrame& caller_frame,
313 ShadowFrame* callee_frame,
Orion Hodson960d4f72017-11-10 15:32:38 +0000314 const InstructionOperands* const operands,
315 const size_t first_dst_reg)
Orion Hodson811bd5f2016-12-07 11:35:37 +0000316 REQUIRES_SHARED(Locks::mutator_lock_) {
Orion Hodson960d4f72017-11-10 15:32:38 +0000317 for (size_t i = 0; i < operands->GetNumberOfOperands(); ++i) {
Orion Hodson811bd5f2016-12-07 11:35:37 +0000318 size_t dst_reg = first_dst_reg + i;
Orion Hodson960d4f72017-11-10 15:32:38 +0000319 size_t src_reg = operands->GetOperand(i);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000320 // Uint required, so that sign extension does not make this wrong on 64-bit systems
321 uint32_t src_value = caller_frame.GetVReg(src_reg);
322 ObjPtr<mirror::Object> o = caller_frame.GetVRegReference<kVerifyNone>(src_reg);
323 // If both register locations contains the same value, the register probably holds a reference.
324 // Note: As an optimization, non-moving collectors leave a stale reference value
325 // in the references array even after the original vreg was overwritten to a non-reference.
326 if (src_value == reinterpret_cast<uintptr_t>(o.Ptr())) {
Vladimir Markobcf17522018-06-01 13:14:32 +0100327 callee_frame->SetVRegReference(dst_reg, o);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000328 } else {
329 callee_frame->SetVReg(dst_reg, src_value);
330 }
331 }
332}
333
Orion Hodson811bd5f2016-12-07 11:35:37 +0000334inline bool ConvertAndCopyArgumentsFromCallerFrame(
335 Thread* self,
336 Handle<mirror::MethodType> callsite_type,
337 Handle<mirror::MethodType> callee_type,
338 const ShadowFrame& caller_frame,
Orion Hodson960d4f72017-11-10 15:32:38 +0000339 uint32_t first_dest_reg,
340 const InstructionOperands* const operands,
Orion Hodson811bd5f2016-12-07 11:35:37 +0000341 ShadowFrame* callee_frame)
342 REQUIRES_SHARED(Locks::mutator_lock_) {
343 ObjPtr<mirror::ObjectArray<mirror::Class>> from_types(callsite_type->GetPTypes());
344 ObjPtr<mirror::ObjectArray<mirror::Class>> to_types(callee_type->GetPTypes());
345
346 const int32_t num_method_params = from_types->GetLength();
347 if (to_types->GetLength() != num_method_params) {
348 ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get());
349 return false;
350 }
351
Orion Hodson928033d2018-02-07 05:30:54 +0000352 ShadowFrameGetter getter(caller_frame, operands);
Orion Hodson960d4f72017-11-10 15:32:38 +0000353 ShadowFrameSetter setter(callee_frame, first_dest_reg);
354 return PerformConversions<ShadowFrameGetter, ShadowFrameSetter>(self,
355 callsite_type,
356 callee_type,
357 &getter,
358 &setter,
359 num_method_params);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000360}
361
Orion Hodson811bd5f2016-12-07 11:35:37 +0000362inline bool IsInvoke(const mirror::MethodHandle::Kind handle_kind) {
363 return handle_kind <= mirror::MethodHandle::Kind::kLastInvokeKind;
364}
365
366inline bool IsInvokeTransform(const mirror::MethodHandle::Kind handle_kind) {
367 return (handle_kind == mirror::MethodHandle::Kind::kInvokeTransform
368 || handle_kind == mirror::MethodHandle::Kind::kInvokeCallSiteTransform);
369}
370
Orion Hodsonb8b93872018-01-30 07:51:10 +0000371inline bool IsInvokeVarHandle(const mirror::MethodHandle::Kind handle_kind) {
372 return (handle_kind == mirror::MethodHandle::Kind::kInvokeVarHandle ||
373 handle_kind == mirror::MethodHandle::Kind::kInvokeVarHandleExact);
374}
375
Orion Hodson811bd5f2016-12-07 11:35:37 +0000376inline bool IsFieldAccess(mirror::MethodHandle::Kind handle_kind) {
377 return (handle_kind >= mirror::MethodHandle::Kind::kFirstAccessorKind
378 && handle_kind <= mirror::MethodHandle::Kind::kLastAccessorKind);
379}
380
381// Calculate the number of ins for a proxy or native method, where we
382// can't just look at the code item.
383static inline size_t GetInsForProxyOrNativeMethod(ArtMethod* method)
384 REQUIRES_SHARED(Locks::mutator_lock_) {
385 DCHECK(method->IsNative() || method->IsProxyMethod());
Orion Hodson811bd5f2016-12-07 11:35:37 +0000386 method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
Orion Hodsona1be7132017-03-21 10:04:12 +0000387 uint32_t shorty_length = 0;
388 const char* shorty = method->GetShorty(&shorty_length);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000389
Orion Hodsona1be7132017-03-21 10:04:12 +0000390 // Static methods do not include the receiver. The receiver isn't included
391 // in the shorty_length though the return value is.
392 size_t num_ins = method->IsStatic() ? shorty_length - 1 : shorty_length;
393 for (const char* c = shorty + 1; *c != '\0'; ++c) {
394 if (*c == 'J' || *c == 'D') {
Orion Hodson811bd5f2016-12-07 11:35:37 +0000395 ++num_ins;
396 }
397 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000398 return num_ins;
399}
400
401// Returns true iff. the callsite type for a polymorphic invoke is transformer
402// like, i.e that it has a single input argument whose type is
403// dalvik.system.EmulatedStackFrame.
404static inline bool IsCallerTransformer(Handle<mirror::MethodType> callsite_type)
405 REQUIRES_SHARED(Locks::mutator_lock_) {
406 ObjPtr<mirror::ObjectArray<mirror::Class>> param_types(callsite_type->GetPTypes());
407 if (param_types->GetLength() == 1) {
408 ObjPtr<mirror::Class> param(param_types->GetWithoutChecks(0));
Orion Hodsona1be7132017-03-21 10:04:12 +0000409 // NB Comparing descriptor here as it appears faster in cycle simulation than using:
410 // param == WellKnownClasses::ToClass(WellKnownClasses::dalvik_system_EmulatedStackFrame)
411 // Costs are 98 vs 173 cycles per invocation.
412 return param->DescriptorEquals("Ldalvik/system/EmulatedStackFrame;");
Orion Hodson811bd5f2016-12-07 11:35:37 +0000413 }
414
415 return false;
416}
417
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100418static inline bool MethodHandleInvokeMethod(ArtMethod* called_method,
419 Handle<mirror::MethodType> callsite_type,
420 Handle<mirror::MethodType> target_type,
421 Thread* self,
422 ShadowFrame& shadow_frame,
Orion Hodson960d4f72017-11-10 15:32:38 +0000423 const InstructionOperands* const operands,
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100424 JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
Orion Hodson811bd5f2016-12-07 11:35:37 +0000425 // Compute method information.
David Sehr0225f8e2018-01-31 08:52:24 +0000426 CodeItemDataAccessor accessor(called_method->DexInstructionData());
Orion Hodson811bd5f2016-12-07 11:35:37 +0000427
428 // Number of registers for the callee's call frame. Note that for non-exact
429 // invokes, we always derive this information from the callee method. We
430 // cannot guarantee during verification that the number of registers encoded
431 // in the invoke is equal to the number of ins for the callee. This is because
432 // some transformations (such as boxing a long -> Long or wideining an
433 // int -> long will change that number.
434 uint16_t num_regs;
435 size_t num_input_regs;
436 size_t first_dest_reg;
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800437 if (LIKELY(accessor.HasCodeItem())) {
438 num_regs = accessor.RegistersSize();
439 first_dest_reg = num_regs - accessor.InsSize();
440 num_input_regs = accessor.InsSize();
Orion Hodson811bd5f2016-12-07 11:35:37 +0000441 // Parameter registers go at the end of the shadow frame.
442 DCHECK_NE(first_dest_reg, (size_t)-1);
443 } else {
444 // No local regs for proxy and native methods.
445 DCHECK(called_method->IsNative() || called_method->IsProxyMethod());
446 num_regs = num_input_regs = GetInsForProxyOrNativeMethod(called_method);
447 first_dest_reg = 0;
448 }
449
450 // Allocate shadow frame on the stack.
451 ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
452 CREATE_SHADOW_FRAME(num_regs, &shadow_frame, called_method, /* dex pc */ 0);
453 ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get();
454
455 // Whether this polymorphic invoke was issued by a transformer method.
456 bool is_caller_transformer = false;
457 // Thread might be suspended during PerformArgumentConversions due to the
458 // allocations performed during boxing.
459 {
460 ScopedStackedShadowFramePusher pusher(
461 self, new_shadow_frame, StackedShadowFrameType::kShadowFrameUnderConstruction);
462 if (callsite_type->IsExactMatch(target_type.Get())) {
463 // This is an exact invoke, we can take the fast path of just copying all
464 // registers without performing any argument conversions.
Orion Hodson960d4f72017-11-10 15:32:38 +0000465 CopyArgumentsFromCallerFrame(shadow_frame,
466 new_shadow_frame,
467 operands,
468 first_dest_reg);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000469 } else {
470 // This includes the case where we're entering this invoke-polymorphic
471 // from a transformer method. In that case, the callsite_type will contain
472 // a single argument of type dalvik.system.EmulatedStackFrame. In that
473 // case, we'll have to unmarshal the EmulatedStackFrame into the
474 // new_shadow_frame and perform argument conversions on it.
475 if (IsCallerTransformer(callsite_type)) {
476 is_caller_transformer = true;
477 // The emulated stack frame is the first and only argument when we're coming
478 // through from a transformer.
Orion Hodson960d4f72017-11-10 15:32:38 +0000479 size_t first_arg_register = operands->GetOperand(0);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000480 ObjPtr<mirror::EmulatedStackFrame> emulated_stack_frame(
Vladimir Marko4bb2af52019-03-22 11:09:19 +0000481 ObjPtr<mirror::EmulatedStackFrame>::DownCast(MakeObjPtr(
482 shadow_frame.GetVRegReference(first_arg_register))));
Orion Hodson811bd5f2016-12-07 11:35:37 +0000483 if (!emulated_stack_frame->WriteToShadowFrame(self,
484 target_type,
485 first_dest_reg,
486 new_shadow_frame)) {
487 DCHECK(self->IsExceptionPending());
Yi Kong4b22b342018-08-02 14:43:21 -0700488 result->SetL(nullptr);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000489 return false;
490 }
Orion Hodsona1be7132017-03-21 10:04:12 +0000491 } else {
492 if (!callsite_type->IsConvertible(target_type.Get())) {
493 ThrowWrongMethodTypeException(target_type.Get(), callsite_type.Get());
494 return false;
495 }
Orion Hodson960d4f72017-11-10 15:32:38 +0000496 if (!ConvertAndCopyArgumentsFromCallerFrame(self,
497 callsite_type,
498 target_type,
499 shadow_frame,
500 first_dest_reg,
501 operands,
502 new_shadow_frame)) {
Orion Hodsona1be7132017-03-21 10:04:12 +0000503 DCHECK(self->IsExceptionPending());
Yi Kong4b22b342018-08-02 14:43:21 -0700504 result->SetL(nullptr);
Orion Hodsona1be7132017-03-21 10:04:12 +0000505 return false;
506 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000507 }
508 }
509 }
510
Jeff Hao5ea84132017-05-05 16:59:29 -0700511 bool use_interpreter_entrypoint = ClassLinker::ShouldUseInterpreterEntrypoint(
512 called_method, called_method->GetEntryPointFromQuickCompiledCode());
513 PerformCall(self,
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800514 accessor,
Jeff Hao5ea84132017-05-05 16:59:29 -0700515 shadow_frame.GetMethod(),
516 first_dest_reg,
517 new_shadow_frame,
518 result,
519 use_interpreter_entrypoint);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000520 if (self->IsExceptionPending()) {
521 return false;
522 }
523
524 // If the caller of this signature polymorphic method was a transformer,
525 // we need to copy the result back out to the emulated stack frame.
526 if (is_caller_transformer) {
527 StackHandleScope<2> hs(self);
Orion Hodson960d4f72017-11-10 15:32:38 +0000528 size_t first_callee_register = operands->GetOperand(0);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000529 Handle<mirror::EmulatedStackFrame> emulated_stack_frame(
Vladimir Marko4bb2af52019-03-22 11:09:19 +0000530 hs.NewHandle(ObjPtr<mirror::EmulatedStackFrame>::DownCast(MakeObjPtr(
531 shadow_frame.GetVRegReference(first_callee_register)))));
Orion Hodson811bd5f2016-12-07 11:35:37 +0000532 Handle<mirror::MethodType> emulated_stack_type(hs.NewHandle(emulated_stack_frame->GetType()));
533 JValue local_result;
534 local_result.SetJ(result->GetJ());
535
536 if (ConvertReturnValue(emulated_stack_type, target_type, &local_result)) {
537 emulated_stack_frame->SetReturnValue(self, local_result);
538 return true;
Orion Hodson811bd5f2016-12-07 11:35:37 +0000539 }
Orion Hodsona1be7132017-03-21 10:04:12 +0000540
541 DCHECK(self->IsExceptionPending());
542 return false;
Orion Hodson811bd5f2016-12-07 11:35:37 +0000543 }
Orion Hodsona1be7132017-03-21 10:04:12 +0000544
545 return ConvertReturnValue(callsite_type, target_type, result);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000546}
547
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100548static inline bool MethodHandleInvokeTransform(ArtMethod* called_method,
549 Handle<mirror::MethodType> callsite_type,
550 Handle<mirror::MethodType> callee_type,
551 Thread* self,
552 ShadowFrame& shadow_frame,
553 Handle<mirror::MethodHandle> receiver,
Orion Hodson960d4f72017-11-10 15:32:38 +0000554 const InstructionOperands* const operands,
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100555 JValue* result)
Orion Hodson811bd5f2016-12-07 11:35:37 +0000556 REQUIRES_SHARED(Locks::mutator_lock_) {
557 // This can be fixed to two, because the method we're calling here
558 // (MethodHandle.transformInternal) doesn't have any locals and the signature
559 // is known :
560 //
561 // private MethodHandle.transformInternal(EmulatedStackFrame sf);
562 //
563 // This means we need only two vregs :
564 // - One for the receiver object.
565 // - One for the only method argument (an EmulatedStackFrame).
566 static constexpr size_t kNumRegsForTransform = 2;
567
David Sehr0225f8e2018-01-31 08:52:24 +0000568 CodeItemDataAccessor accessor(called_method->DexInstructionData());
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800569 DCHECK_EQ(kNumRegsForTransform, accessor.RegistersSize());
570 DCHECK_EQ(kNumRegsForTransform, accessor.InsSize());
Orion Hodson811bd5f2016-12-07 11:35:37 +0000571
572 ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
573 CREATE_SHADOW_FRAME(kNumRegsForTransform, &shadow_frame, called_method, /* dex pc */ 0);
574 ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get();
575
576 StackHandleScope<1> hs(self);
577 MutableHandle<mirror::EmulatedStackFrame> sf(hs.NewHandle<mirror::EmulatedStackFrame>(nullptr));
578 if (IsCallerTransformer(callsite_type)) {
579 // If we're entering this transformer from another transformer, we can pass
580 // through the handle directly to the callee, instead of having to
581 // instantiate a new stack frame based on the shadow frame.
Orion Hodson960d4f72017-11-10 15:32:38 +0000582 size_t first_callee_register = operands->GetOperand(0);
Vladimir Marko4bb2af52019-03-22 11:09:19 +0000583 sf.Assign(ObjPtr<mirror::EmulatedStackFrame>::DownCast(MakeObjPtr(
584 shadow_frame.GetVRegReference(first_callee_register))));
Orion Hodson811bd5f2016-12-07 11:35:37 +0000585 } else {
Orion Hodson960d4f72017-11-10 15:32:38 +0000586 sf.Assign(mirror::EmulatedStackFrame::CreateFromShadowFrameAndArgs(self,
587 callsite_type,
588 callee_type,
589 shadow_frame,
590 operands));
Orion Hodson811bd5f2016-12-07 11:35:37 +0000591
592 // Something went wrong while creating the emulated stack frame, we should
593 // throw the pending exception.
Andreas Gampefa4333d2017-02-14 11:10:34 -0800594 if (sf == nullptr) {
Orion Hodson811bd5f2016-12-07 11:35:37 +0000595 DCHECK(self->IsExceptionPending());
596 return false;
597 }
598 }
599
600 new_shadow_frame->SetVRegReference(0, receiver.Get());
601 new_shadow_frame->SetVRegReference(1, sf.Get());
602
Jeff Hao5ea84132017-05-05 16:59:29 -0700603 bool use_interpreter_entrypoint = ClassLinker::ShouldUseInterpreterEntrypoint(
604 called_method, called_method->GetEntryPointFromQuickCompiledCode());
Orion Hodson811bd5f2016-12-07 11:35:37 +0000605 PerformCall(self,
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800606 accessor,
Orion Hodson811bd5f2016-12-07 11:35:37 +0000607 shadow_frame.GetMethod(),
608 0 /* first destination register */,
609 new_shadow_frame,
Jeff Hao5ea84132017-05-05 16:59:29 -0700610 result,
611 use_interpreter_entrypoint);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000612 if (self->IsExceptionPending()) {
613 return false;
614 }
615
616 // If the called transformer method we called has returned a value, then we
617 // need to copy it back to |result|.
618 sf->GetReturnValue(self, result);
619 return ConvertReturnValue(callsite_type, callee_type, result);
620}
621
622inline static ObjPtr<mirror::Class> GetAndInitializeDeclaringClass(Thread* self, ArtField* field)
623 REQUIRES_SHARED(Locks::mutator_lock_) {
624 // Method handle invocations on static fields should ensure class is
625 // initialized. This usually happens when an instance is constructed
626 // or class members referenced, but this is not guaranteed when
627 // looking up method handles.
628 ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
629 if (UNLIKELY(!klass->IsInitialized())) {
630 StackHandleScope<1> hs(self);
631 HandleWrapperObjPtr<mirror::Class> h(hs.NewHandleWrapper(&klass));
632 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h, true, true)) {
633 DCHECK(self->IsExceptionPending());
634 return nullptr;
635 }
636 }
637 return klass;
638}
639
Orion Hodsona1be7132017-03-21 10:04:12 +0000640ArtMethod* RefineTargetMethod(Thread* self,
641 ShadowFrame& shadow_frame,
642 const mirror::MethodHandle::Kind& handle_kind,
643 Handle<mirror::MethodType> handle_type,
644 Handle<mirror::MethodType> callsite_type,
645 const uint32_t receiver_reg,
646 ArtMethod* target_method)
647 REQUIRES_SHARED(Locks::mutator_lock_) {
648 if (handle_kind == mirror::MethodHandle::Kind::kInvokeVirtual ||
649 handle_kind == mirror::MethodHandle::Kind::kInvokeInterface) {
650 // For virtual and interface methods ensure target_method points to
651 // the actual method to invoke.
652 ObjPtr<mirror::Object> receiver(shadow_frame.GetVRegReference(receiver_reg));
653 if (IsCallerTransformer(callsite_type)) {
654 // The current receiver is an emulated stack frame, the method's
655 // receiver needs to be fetched from there as the emulated frame
656 // will be unpacked into a new frame.
657 receiver = ObjPtr<mirror::EmulatedStackFrame>::DownCast(receiver)->GetReceiver();
658 }
659
660 ObjPtr<mirror::Class> declaring_class(target_method->GetDeclaringClass());
661 if (receiver == nullptr || receiver->GetClass() != declaring_class) {
662 // Verify that _vRegC is an object reference and of the type expected by
663 // the receiver.
664 if (!VerifyObjectIsClass(receiver, declaring_class)) {
665 DCHECK(self->IsExceptionPending());
666 return nullptr;
667 }
668 return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(
669 target_method, kRuntimePointerSize);
670 }
671 } else if (handle_kind == mirror::MethodHandle::Kind::kInvokeDirect) {
672 // String constructors are a special case, they are replaced with
673 // StringFactory methods.
674 if (target_method->IsConstructor() && target_method->GetDeclaringClass()->IsStringClass()) {
675 DCHECK(handle_type->GetRType()->IsStringClass());
676 return WellKnownClasses::StringInitToStringFactory(target_method);
677 }
678 } else if (handle_kind == mirror::MethodHandle::Kind::kInvokeSuper) {
Orion Hodsona1be7132017-03-21 10:04:12 +0000679 // Note that we're not dynamically dispatching on the type of the receiver
680 // here. We use the static type of the "receiver" object that we've
681 // recorded in the method handle's type, which will be the same as the
682 // special caller that was specified at the point of lookup.
683 ObjPtr<mirror::Class> referrer_class = handle_type->GetPTypes()->Get(0);
Orion Hodson0f595742018-04-10 14:49:28 +0100684 ObjPtr<mirror::Class> declaring_class = target_method->GetDeclaringClass();
685 if (referrer_class == declaring_class) {
686 return target_method;
687 }
Orion Hodsona1be7132017-03-21 10:04:12 +0000688 if (!declaring_class->IsInterface()) {
689 ObjPtr<mirror::Class> super_class = referrer_class->GetSuperClass();
690 uint16_t vtable_index = target_method->GetMethodIndex();
691 DCHECK(super_class != nullptr);
692 DCHECK(super_class->HasVTable());
693 // Note that super_class is a super of referrer_class and target_method
694 // will always be declared by super_class (or one of its super classes).
695 DCHECK_LT(vtable_index, super_class->GetVTableLength());
696 return super_class->GetVTableEntry(vtable_index, kRuntimePointerSize);
Orion Hodsona1be7132017-03-21 10:04:12 +0000697 }
698 }
699 return target_method;
700}
701
Orion Hodsona1be7132017-03-21 10:04:12 +0000702bool DoInvokePolymorphicMethod(Thread* self,
703 ShadowFrame& shadow_frame,
704 Handle<mirror::MethodHandle> method_handle,
705 Handle<mirror::MethodType> callsite_type,
Orion Hodson960d4f72017-11-10 15:32:38 +0000706 const InstructionOperands* const operands,
Orion Hodsona1be7132017-03-21 10:04:12 +0000707 JValue* result)
Orion Hodson811bd5f2016-12-07 11:35:37 +0000708 REQUIRES_SHARED(Locks::mutator_lock_) {
709 StackHandleScope<1> hs(self);
710 Handle<mirror::MethodType> handle_type(hs.NewHandle(method_handle->GetMethodType()));
711 const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();
Orion Hodsona1be7132017-03-21 10:04:12 +0000712 DCHECK(IsInvoke(handle_kind));
Orion Hodson811bd5f2016-12-07 11:35:37 +0000713
Orion Hodsona1be7132017-03-21 10:04:12 +0000714 // Get the method we're actually invoking along with the kind of
715 // invoke that is desired. We don't need to perform access checks at this
716 // point because they would have been performed on our behalf at the point
717 // of creation of the method handle.
718 ArtMethod* target_method = method_handle->GetTargetMethod();
Orion Hodson960d4f72017-11-10 15:32:38 +0000719 uint32_t receiver_reg = (operands->GetNumberOfOperands() > 0) ? operands->GetOperand(0) : 0u;
Orion Hodsona1be7132017-03-21 10:04:12 +0000720 ArtMethod* called_method = RefineTargetMethod(self,
721 shadow_frame,
722 handle_kind,
723 handle_type,
724 callsite_type,
725 receiver_reg,
726 target_method);
727 if (called_method == nullptr) {
728 DCHECK(self->IsExceptionPending());
729 return false;
730 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000731
Orion Hodsona1be7132017-03-21 10:04:12 +0000732 if (IsInvokeTransform(handle_kind)) {
733 // There are two cases here - method handles representing regular
734 // transforms and those representing call site transforms. Method
735 // handles for call site transforms adapt their MethodType to match
736 // the call site. For these, the |callee_type| is the same as the
737 // |callsite_type|. The VarargsCollector is such a tranform, its
738 // method type depends on the call site, ie. x(a) or x(a, b), or
739 // x(a, b, c). The VarargsCollector invokes a variable arity method
740 // with the arity arguments in an array.
741 Handle<mirror::MethodType> callee_type =
742 (handle_kind == mirror::MethodHandle::Kind::kInvokeCallSiteTransform) ? callsite_type
743 : handle_type;
Orion Hodson960d4f72017-11-10 15:32:38 +0000744 return MethodHandleInvokeTransform(called_method,
745 callsite_type,
746 callee_type,
747 self,
748 shadow_frame,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700749 /* receiver= */ method_handle,
Orion Hodson960d4f72017-11-10 15:32:38 +0000750 operands,
751 result);
Orion Hodsona1be7132017-03-21 10:04:12 +0000752 } else {
Orion Hodson960d4f72017-11-10 15:32:38 +0000753 return MethodHandleInvokeMethod(called_method,
754 callsite_type,
755 handle_type,
756 self,
757 shadow_frame,
758 operands,
759 result);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000760 }
761}
762
763// Helper for getters in invoke-polymorphic.
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100764inline static void MethodHandleFieldGet(Thread* self,
765 const ShadowFrame& shadow_frame,
766 ObjPtr<mirror::Object>& obj,
767 ArtField* field,
768 Primitive::Type field_type,
769 JValue* result)
Orion Hodson811bd5f2016-12-07 11:35:37 +0000770 REQUIRES_SHARED(Locks::mutator_lock_) {
771 switch (field_type) {
772 case Primitive::kPrimBoolean:
773 DoFieldGetCommon<Primitive::kPrimBoolean>(self, shadow_frame, obj, field, result);
774 break;
775 case Primitive::kPrimByte:
776 DoFieldGetCommon<Primitive::kPrimByte>(self, shadow_frame, obj, field, result);
777 break;
778 case Primitive::kPrimChar:
779 DoFieldGetCommon<Primitive::kPrimChar>(self, shadow_frame, obj, field, result);
780 break;
781 case Primitive::kPrimShort:
782 DoFieldGetCommon<Primitive::kPrimShort>(self, shadow_frame, obj, field, result);
783 break;
784 case Primitive::kPrimInt:
785 DoFieldGetCommon<Primitive::kPrimInt>(self, shadow_frame, obj, field, result);
786 break;
787 case Primitive::kPrimLong:
788 DoFieldGetCommon<Primitive::kPrimLong>(self, shadow_frame, obj, field, result);
789 break;
790 case Primitive::kPrimFloat:
791 DoFieldGetCommon<Primitive::kPrimInt>(self, shadow_frame, obj, field, result);
792 break;
793 case Primitive::kPrimDouble:
794 DoFieldGetCommon<Primitive::kPrimLong>(self, shadow_frame, obj, field, result);
795 break;
796 case Primitive::kPrimNot:
797 DoFieldGetCommon<Primitive::kPrimNot>(self, shadow_frame, obj, field, result);
798 break;
799 case Primitive::kPrimVoid:
800 LOG(FATAL) << "Unreachable: " << field_type;
801 UNREACHABLE();
802 }
803}
804
805// Helper for setters in invoke-polymorphic.
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100806inline bool MethodHandleFieldPut(Thread* self,
807 ShadowFrame& shadow_frame,
808 ObjPtr<mirror::Object>& obj,
809 ArtField* field,
810 Primitive::Type field_type,
811 JValue& value)
Orion Hodson811bd5f2016-12-07 11:35:37 +0000812 REQUIRES_SHARED(Locks::mutator_lock_) {
Orion Hodsonc069a302017-01-18 09:23:12 +0000813 DCHECK(!Runtime::Current()->IsActiveTransaction());
814 static const bool kTransaction = false; // Not in a transaction.
815 static const bool kAssignabilityCheck = false; // No access check.
Orion Hodson811bd5f2016-12-07 11:35:37 +0000816 switch (field_type) {
817 case Primitive::kPrimBoolean:
Orion Hodsonc069a302017-01-18 09:23:12 +0000818 return
819 DoFieldPutCommon<Primitive::kPrimBoolean, kAssignabilityCheck, kTransaction>(
820 self, shadow_frame, obj, field, value);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000821 case Primitive::kPrimByte:
Orion Hodsonc069a302017-01-18 09:23:12 +0000822 return DoFieldPutCommon<Primitive::kPrimByte, kAssignabilityCheck, kTransaction>(
Orion Hodson811bd5f2016-12-07 11:35:37 +0000823 self, shadow_frame, obj, field, value);
824 case Primitive::kPrimChar:
Orion Hodsonc069a302017-01-18 09:23:12 +0000825 return DoFieldPutCommon<Primitive::kPrimChar, kAssignabilityCheck, kTransaction>(
Orion Hodson811bd5f2016-12-07 11:35:37 +0000826 self, shadow_frame, obj, field, value);
827 case Primitive::kPrimShort:
Orion Hodsonc069a302017-01-18 09:23:12 +0000828 return DoFieldPutCommon<Primitive::kPrimShort, kAssignabilityCheck, kTransaction>(
Orion Hodson811bd5f2016-12-07 11:35:37 +0000829 self, shadow_frame, obj, field, value);
830 case Primitive::kPrimInt:
831 case Primitive::kPrimFloat:
Orion Hodsonc069a302017-01-18 09:23:12 +0000832 return DoFieldPutCommon<Primitive::kPrimInt, kAssignabilityCheck, kTransaction>(
Orion Hodson811bd5f2016-12-07 11:35:37 +0000833 self, shadow_frame, obj, field, value);
834 case Primitive::kPrimLong:
835 case Primitive::kPrimDouble:
Orion Hodsonc069a302017-01-18 09:23:12 +0000836 return DoFieldPutCommon<Primitive::kPrimLong, kAssignabilityCheck, kTransaction>(
Orion Hodson811bd5f2016-12-07 11:35:37 +0000837 self, shadow_frame, obj, field, value);
838 case Primitive::kPrimNot:
Orion Hodsonc069a302017-01-18 09:23:12 +0000839 return DoFieldPutCommon<Primitive::kPrimNot, kAssignabilityCheck, kTransaction>(
Orion Hodson811bd5f2016-12-07 11:35:37 +0000840 self, shadow_frame, obj, field, value);
841 case Primitive::kPrimVoid:
842 LOG(FATAL) << "Unreachable: " << field_type;
843 UNREACHABLE();
844 }
845}
846
847static JValue GetValueFromShadowFrame(const ShadowFrame& shadow_frame,
848 Primitive::Type field_type,
849 uint32_t vreg)
850 REQUIRES_SHARED(Locks::mutator_lock_) {
851 JValue field_value;
852 switch (field_type) {
853 case Primitive::kPrimBoolean:
854 field_value.SetZ(static_cast<uint8_t>(shadow_frame.GetVReg(vreg)));
855 break;
856 case Primitive::kPrimByte:
857 field_value.SetB(static_cast<int8_t>(shadow_frame.GetVReg(vreg)));
858 break;
859 case Primitive::kPrimChar:
860 field_value.SetC(static_cast<uint16_t>(shadow_frame.GetVReg(vreg)));
861 break;
862 case Primitive::kPrimShort:
863 field_value.SetS(static_cast<int16_t>(shadow_frame.GetVReg(vreg)));
864 break;
865 case Primitive::kPrimInt:
866 case Primitive::kPrimFloat:
867 field_value.SetI(shadow_frame.GetVReg(vreg));
868 break;
869 case Primitive::kPrimLong:
870 case Primitive::kPrimDouble:
871 field_value.SetJ(shadow_frame.GetVRegLong(vreg));
872 break;
873 case Primitive::kPrimNot:
874 field_value.SetL(shadow_frame.GetVRegReference(vreg));
875 break;
876 case Primitive::kPrimVoid:
877 LOG(FATAL) << "Unreachable: " << field_type;
878 UNREACHABLE();
879 }
880 return field_value;
881}
882
Orion Hodson960d4f72017-11-10 15:32:38 +0000883template <bool do_conversions>
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100884bool MethodHandleFieldAccess(Thread* self,
885 ShadowFrame& shadow_frame,
886 Handle<mirror::MethodHandle> method_handle,
887 Handle<mirror::MethodType> callsite_type,
Orion Hodson960d4f72017-11-10 15:32:38 +0000888 const InstructionOperands* const operands,
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100889 JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
Orion Hodson811bd5f2016-12-07 11:35:37 +0000890 StackHandleScope<1> hs(self);
891 Handle<mirror::MethodType> handle_type(hs.NewHandle(method_handle->GetMethodType()));
892 const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();
893 ArtField* field = method_handle->GetTargetField();
894 Primitive::Type field_type = field->GetTypeAsPrimitiveType();
Orion Hodson811bd5f2016-12-07 11:35:37 +0000895 switch (handle_kind) {
896 case mirror::MethodHandle::kInstanceGet: {
Orion Hodson960d4f72017-11-10 15:32:38 +0000897 size_t obj_reg = operands->GetOperand(0);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000898 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(obj_reg);
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100899 MethodHandleFieldGet(self, shadow_frame, obj, field, field_type, result);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000900 if (do_conversions && !ConvertReturnValue(callsite_type, handle_type, result)) {
901 DCHECK(self->IsExceptionPending());
902 return false;
903 }
904 return true;
905 }
906 case mirror::MethodHandle::kStaticGet: {
907 ObjPtr<mirror::Object> obj = GetAndInitializeDeclaringClass(self, field);
908 if (obj == nullptr) {
909 DCHECK(self->IsExceptionPending());
910 return false;
911 }
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100912 MethodHandleFieldGet(self, shadow_frame, obj, field, field_type, result);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000913 if (do_conversions && !ConvertReturnValue(callsite_type, handle_type, result)) {
914 DCHECK(self->IsExceptionPending());
915 return false;
916 }
917 return true;
918 }
919 case mirror::MethodHandle::kInstancePut: {
Orion Hodson960d4f72017-11-10 15:32:38 +0000920 size_t obj_reg = operands->GetOperand(0);
921 size_t value_reg = operands->GetOperand(1);
Mathieu Chartier71b17082017-04-17 20:12:29 -0700922 const size_t kPTypeIndex = 1;
923 // Use ptypes instead of field type since we may be unboxing a reference for a primitive
924 // field. The field type is incorrect for this case.
925 JValue value = GetValueFromShadowFrame(
926 shadow_frame,
927 callsite_type->GetPTypes()->Get(kPTypeIndex)->GetPrimitiveType(),
928 value_reg);
929 if (do_conversions && !ConvertArgumentValue(callsite_type,
930 handle_type,
931 kPTypeIndex,
932 &value)) {
Orion Hodson811bd5f2016-12-07 11:35:37 +0000933 DCHECK(self->IsExceptionPending());
934 return false;
935 }
936 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(obj_reg);
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100937 return MethodHandleFieldPut(self, shadow_frame, obj, field, field_type, value);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000938 }
939 case mirror::MethodHandle::kStaticPut: {
940 ObjPtr<mirror::Object> obj = GetAndInitializeDeclaringClass(self, field);
941 if (obj == nullptr) {
942 DCHECK(self->IsExceptionPending());
943 return false;
944 }
Orion Hodson960d4f72017-11-10 15:32:38 +0000945 size_t value_reg = operands->GetOperand(0);
Mathieu Chartier71b17082017-04-17 20:12:29 -0700946 const size_t kPTypeIndex = 0;
947 // Use ptypes instead of field type since we may be unboxing a reference for a primitive
948 // field. The field type is incorrect for this case.
949 JValue value = GetValueFromShadowFrame(
950 shadow_frame,
951 callsite_type->GetPTypes()->Get(kPTypeIndex)->GetPrimitiveType(),
952 value_reg);
953 if (do_conversions && !ConvertArgumentValue(callsite_type,
954 handle_type,
955 kPTypeIndex,
956 &value)) {
Orion Hodson811bd5f2016-12-07 11:35:37 +0000957 DCHECK(self->IsExceptionPending());
958 return false;
959 }
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100960 return MethodHandleFieldPut(self, shadow_frame, obj, field, field_type, value);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000961 }
962 default:
963 LOG(FATAL) << "Unreachable: " << handle_kind;
964 UNREACHABLE();
965 }
966}
967
Orion Hodsonb8b93872018-01-30 07:51:10 +0000968bool DoVarHandleInvokeTranslationUnchecked(Thread* self,
969 ShadowFrame& shadow_frame,
970 mirror::VarHandle::AccessMode access_mode,
971 Handle<mirror::VarHandle> vh,
972 Handle<mirror::MethodType> vh_type,
973 Handle<mirror::MethodType> callsite_type,
974 const InstructionOperands* const operands,
975 JValue* result)
976 REQUIRES_SHARED(Locks::mutator_lock_) {
977 DCHECK_EQ(operands->GetNumberOfOperands(), static_cast<uint32_t>(vh_type->GetNumberOfPTypes()));
978 DCHECK_EQ(operands->GetNumberOfOperands(),
979 static_cast<uint32_t>(callsite_type->GetNumberOfPTypes()));
980 const size_t vreg_count = vh_type->NumberOfVRegs();
981 ShadowFrameAllocaUniquePtr accessor_frame =
982 CREATE_SHADOW_FRAME(vreg_count, nullptr, shadow_frame.GetMethod(), shadow_frame.GetDexPC());
983 ShadowFrameGetter getter(shadow_frame, operands);
984 static const uint32_t kFirstAccessorReg = 0;
985 ShadowFrameSetter setter(accessor_frame.get(), kFirstAccessorReg);
986 if (!PerformConversions(self, callsite_type, vh_type, &getter, &setter)) {
987 return false;
988 }
989 RangeInstructionOperands accessor_operands(kFirstAccessorReg, kFirstAccessorReg + vreg_count);
990 if (!vh->Access(access_mode, accessor_frame.get(), &accessor_operands, result)) {
991 return false;
992 }
993 return ConvertReturnValue(callsite_type, vh_type, result);
994}
995
996bool DoVarHandleInvokeTranslation(Thread* self,
997 ShadowFrame& shadow_frame,
998 bool invokeExact,
999 Handle<mirror::MethodHandle> method_handle,
1000 Handle<mirror::MethodType> callsite_type,
1001 const InstructionOperands* const operands,
1002 JValue* result)
1003 REQUIRES_SHARED(Locks::mutator_lock_) {
1004 if (!invokeExact) {
1005 // Exact invokes are checked for compatability higher up. The
1006 // non-exact invoke path doesn't have a similar check due to
1007 // transformers which have EmulatedStack frame arguments with the
1008 // actual method type associated with the frame.
1009 if (UNLIKELY(!callsite_type->IsConvertible(method_handle->GetMethodType()))) {
1010 ThrowWrongMethodTypeException(method_handle->GetMethodType(), callsite_type.Get());
1011 return false;
1012 }
1013 }
1014
1015 //
1016 // Basic checks that apply in all cases.
1017 //
1018 StackHandleScope<6> hs(self);
1019 Handle<mirror::ObjectArray<mirror::Class>>
1020 callsite_ptypes(hs.NewHandle(callsite_type->GetPTypes()));
1021 Handle<mirror::ObjectArray<mirror::Class>>
1022 mh_ptypes(hs.NewHandle(method_handle->GetMethodType()->GetPTypes()));
1023
1024 // Check that the first parameter is a VarHandle
1025 if (callsite_ptypes->GetLength() < 1 ||
1026 !mh_ptypes->Get(0)->IsAssignableFrom(callsite_ptypes->Get(0)) ||
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001027 mh_ptypes->Get(0) != GetClassRoot<mirror::VarHandle>()) {
Orion Hodsonb8b93872018-01-30 07:51:10 +00001028 ThrowWrongMethodTypeException(method_handle->GetMethodType(), callsite_type.Get());
1029 return false;
1030 }
1031
1032 // Get the receiver
Vladimir Marko4bb2af52019-03-22 11:09:19 +00001033 ObjPtr<mirror::Object> receiver = shadow_frame.GetVRegReference(operands->GetOperand(0));
Orion Hodsonb8b93872018-01-30 07:51:10 +00001034 if (receiver == nullptr) {
1035 ThrowNullPointerException("Expected argument 1 to be a non-null VarHandle");
1036 return false;
1037 }
1038
1039 // Cast to VarHandle instance
Vladimir Marko4bb2af52019-03-22 11:09:19 +00001040 Handle<mirror::VarHandle> vh(hs.NewHandle(ObjPtr<mirror::VarHandle>::DownCast(receiver)));
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001041 DCHECK(GetClassRoot<mirror::VarHandle>()->IsAssignableFrom(vh->GetClass()));
Orion Hodsonb8b93872018-01-30 07:51:10 +00001042
1043 // Determine the accessor kind to dispatch
1044 ArtMethod* target_method = method_handle->GetTargetMethod();
1045 int intrinsic_index = target_method->GetIntrinsic();
1046 mirror::VarHandle::AccessMode access_mode =
1047 mirror::VarHandle::GetAccessModeByIntrinsic(static_cast<Intrinsics>(intrinsic_index));
1048 Handle<mirror::MethodType> vh_type =
1049 hs.NewHandle(vh->GetMethodTypeForAccessMode(self, access_mode));
1050 Handle<mirror::MethodType> mh_invoke_type = hs.NewHandle(
1051 mirror::MethodType::CloneWithoutLeadingParameter(self, method_handle->GetMethodType()));
1052 if (method_handle->GetHandleKind() == mirror::MethodHandle::Kind::kInvokeVarHandleExact) {
1053 if (!mh_invoke_type->IsExactMatch(vh_type.Get())) {
1054 ThrowWrongMethodTypeException(vh_type.Get(), mh_invoke_type.Get());
1055 return false;
1056 }
1057 } else {
1058 DCHECK_EQ(method_handle->GetHandleKind(), mirror::MethodHandle::Kind::kInvokeVarHandle);
1059 if (!mh_invoke_type->IsConvertible(vh_type.Get())) {
1060 ThrowWrongMethodTypeException(vh_type.Get(), mh_invoke_type.Get());
1061 return false;
1062 }
1063 }
1064
1065 Handle<mirror::MethodType> callsite_type_without_varhandle =
1066 hs.NewHandle(mirror::MethodType::CloneWithoutLeadingParameter(self, callsite_type.Get()));
1067 NoReceiverInstructionOperands varhandle_operands(operands);
1068 DCHECK_EQ(static_cast<int32_t>(varhandle_operands.GetNumberOfOperands()),
1069 callsite_type_without_varhandle->GetPTypes()->GetLength());
1070 return DoVarHandleInvokeTranslationUnchecked(self,
1071 shadow_frame,
1072 access_mode,
1073 vh,
1074 vh_type,
1075 callsite_type_without_varhandle,
1076 &varhandle_operands,
1077 result);
1078}
1079
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001080static inline bool MethodHandleInvokeInternal(Thread* self,
1081 ShadowFrame& shadow_frame,
1082 Handle<mirror::MethodHandle> method_handle,
1083 Handle<mirror::MethodType> callsite_type,
Orion Hodson960d4f72017-11-10 15:32:38 +00001084 const InstructionOperands* const operands,
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001085 JValue* result)
Orion Hodson811bd5f2016-12-07 11:35:37 +00001086 REQUIRES_SHARED(Locks::mutator_lock_) {
1087 const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();
Orion Hodsona1be7132017-03-21 10:04:12 +00001088 if (IsFieldAccess(handle_kind)) {
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001089 ObjPtr<mirror::MethodType> handle_type(method_handle->GetMethodType());
Orion Hodsona1be7132017-03-21 10:04:12 +00001090 DCHECK(!callsite_type->IsExactMatch(handle_type.Ptr()));
1091 if (!callsite_type->IsConvertible(handle_type.Ptr())) {
Orion Hodson811bd5f2016-12-07 11:35:37 +00001092 ThrowWrongMethodTypeException(handle_type.Ptr(), callsite_type.Get());
1093 return false;
1094 }
Orion Hodsona1be7132017-03-21 10:04:12 +00001095 const bool do_convert = true;
Orion Hodson960d4f72017-11-10 15:32:38 +00001096 return MethodHandleFieldAccess<do_convert>(
Orion Hodsona1be7132017-03-21 10:04:12 +00001097 self,
1098 shadow_frame,
1099 method_handle,
1100 callsite_type,
Orion Hodson960d4f72017-11-10 15:32:38 +00001101 operands,
Orion Hodsona1be7132017-03-21 10:04:12 +00001102 result);
Orion Hodson811bd5f2016-12-07 11:35:37 +00001103 }
Orion Hodsonb8b93872018-01-30 07:51:10 +00001104 if (IsInvokeVarHandle(handle_kind)) {
1105 return DoVarHandleInvokeTranslation(self,
1106 shadow_frame,
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001107 /*invokeExact=*/ false,
Orion Hodsonb8b93872018-01-30 07:51:10 +00001108 method_handle,
1109 callsite_type,
1110 operands,
1111 result);
1112 }
Orion Hodson960d4f72017-11-10 15:32:38 +00001113 return DoInvokePolymorphicMethod(self,
1114 shadow_frame,
1115 method_handle,
1116 callsite_type,
1117 operands,
1118 result);
Orion Hodson811bd5f2016-12-07 11:35:37 +00001119}
1120
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001121static inline bool MethodHandleInvokeExactInternal(
1122 Thread* self,
1123 ShadowFrame& shadow_frame,
1124 Handle<mirror::MethodHandle> method_handle,
1125 Handle<mirror::MethodType> callsite_type,
Orion Hodson960d4f72017-11-10 15:32:38 +00001126 const InstructionOperands* const operands,
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001127 JValue* result)
Orion Hodson811bd5f2016-12-07 11:35:37 +00001128 REQUIRES_SHARED(Locks::mutator_lock_) {
Orion Hodsona1be7132017-03-21 10:04:12 +00001129 StackHandleScope<1> hs(self);
Orion Hodsona1be7132017-03-21 10:04:12 +00001130 Handle<mirror::MethodType> method_handle_type(hs.NewHandle(method_handle->GetMethodType()));
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001131 if (!callsite_type->IsExactMatch(method_handle_type.Get())) {
1132 ThrowWrongMethodTypeException(method_handle_type.Get(), callsite_type.Get());
1133 return false;
1134 }
1135
1136 const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind();
Orion Hodson811bd5f2016-12-07 11:35:37 +00001137 if (IsFieldAccess(handle_kind)) {
1138 const bool do_convert = false;
Orion Hodson960d4f72017-11-10 15:32:38 +00001139 return MethodHandleFieldAccess<do_convert>(self,
1140 shadow_frame,
1141 method_handle,
1142 callsite_type,
1143 operands,
1144 result);
Orion Hodson811bd5f2016-12-07 11:35:37 +00001145 }
1146
Orion Hodsona1be7132017-03-21 10:04:12 +00001147 // Slow-path check.
Orion Hodsonb8b93872018-01-30 07:51:10 +00001148 if (IsInvokeTransform(handle_kind) ||
1149 IsCallerTransformer(callsite_type)) {
Orion Hodson960d4f72017-11-10 15:32:38 +00001150 return DoInvokePolymorphicMethod(self,
1151 shadow_frame,
1152 method_handle,
1153 callsite_type,
1154 operands,
1155 result);
Orion Hodsonb8b93872018-01-30 07:51:10 +00001156 } else if (IsInvokeVarHandle(handle_kind)) {
1157 return DoVarHandleInvokeTranslation(self,
1158 shadow_frame,
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001159 /*invokeExact=*/ true,
Orion Hodsonb8b93872018-01-30 07:51:10 +00001160 method_handle,
1161 callsite_type,
1162 operands,
1163 result);
Orion Hodsona1be7132017-03-21 10:04:12 +00001164 }
1165
1166 // On the fast-path. This is equivalent to DoCallPolymoprhic without the conversion paths.
1167 ArtMethod* target_method = method_handle->GetTargetMethod();
Orion Hodson960d4f72017-11-10 15:32:38 +00001168 uint32_t receiver_reg = (operands->GetNumberOfOperands() > 0) ? operands->GetOperand(0) : 0u;
Orion Hodsona1be7132017-03-21 10:04:12 +00001169 ArtMethod* called_method = RefineTargetMethod(self,
Orion Hodson811bd5f2016-12-07 11:35:37 +00001170 shadow_frame,
Orion Hodsona1be7132017-03-21 10:04:12 +00001171 handle_kind,
1172 method_handle_type,
Orion Hodson811bd5f2016-12-07 11:35:37 +00001173 callsite_type,
Orion Hodsona1be7132017-03-21 10:04:12 +00001174 receiver_reg,
1175 target_method);
1176 if (called_method == nullptr) {
1177 DCHECK(self->IsExceptionPending());
1178 return false;
1179 }
1180
1181 // Compute method information.
David Sehr0225f8e2018-01-31 08:52:24 +00001182 CodeItemDataAccessor accessor(called_method->DexInstructionData());
Orion Hodsona1be7132017-03-21 10:04:12 +00001183 uint16_t num_regs;
1184 size_t num_input_regs;
1185 size_t first_dest_reg;
Mathieu Chartier808c7a52017-12-15 11:19:33 -08001186 if (LIKELY(accessor.HasCodeItem())) {
1187 num_regs = accessor.RegistersSize();
1188 first_dest_reg = num_regs - accessor.InsSize();
1189 num_input_regs = accessor.InsSize();
Orion Hodsona1be7132017-03-21 10:04:12 +00001190 // Parameter registers go at the end of the shadow frame.
1191 DCHECK_NE(first_dest_reg, (size_t)-1);
1192 } else {
1193 // No local regs for proxy and native methods.
1194 DCHECK(called_method->IsNative() || called_method->IsProxyMethod());
1195 num_regs = num_input_regs = GetInsForProxyOrNativeMethod(called_method);
1196 first_dest_reg = 0;
1197 }
1198
1199 // Allocate shadow frame on the stack.
1200 const char* old_cause = self->StartAssertNoThreadSuspension("DoCallCommon");
1201 ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
1202 CREATE_SHADOW_FRAME(num_regs, &shadow_frame, called_method, /* dex pc */ 0);
1203 ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get();
Orion Hodson960d4f72017-11-10 15:32:38 +00001204 CopyArgumentsFromCallerFrame(shadow_frame,
1205 new_shadow_frame,
1206 operands,
1207 first_dest_reg);
Orion Hodsona1be7132017-03-21 10:04:12 +00001208 self->EndAssertNoThreadSuspension(old_cause);
1209
Jeff Hao5ea84132017-05-05 16:59:29 -07001210 bool use_interpreter_entrypoint = ClassLinker::ShouldUseInterpreterEntrypoint(
1211 called_method, called_method->GetEntryPointFromQuickCompiledCode());
1212 PerformCall(self,
Mathieu Chartier808c7a52017-12-15 11:19:33 -08001213 accessor,
Jeff Hao5ea84132017-05-05 16:59:29 -07001214 shadow_frame.GetMethod(),
1215 first_dest_reg,
1216 new_shadow_frame,
1217 result,
1218 use_interpreter_entrypoint);
Orion Hodsona1be7132017-03-21 10:04:12 +00001219 if (self->IsExceptionPending()) {
1220 return false;
1221 }
1222 return true;
Orion Hodson811bd5f2016-12-07 11:35:37 +00001223}
1224
1225} // namespace
1226
Orion Hodson960d4f72017-11-10 15:32:38 +00001227bool MethodHandleInvoke(Thread* self,
1228 ShadowFrame& shadow_frame,
1229 Handle<mirror::MethodHandle> method_handle,
1230 Handle<mirror::MethodType> callsite_type,
1231 const InstructionOperands* const operands,
1232 JValue* result)
Orion Hodson811bd5f2016-12-07 11:35:37 +00001233 REQUIRES_SHARED(Locks::mutator_lock_) {
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001234 if (UNLIKELY(callsite_type->IsExactMatch(method_handle->GetMethodType()))) {
1235 // A non-exact invoke that can be invoked exactly.
Orion Hodson960d4f72017-11-10 15:32:38 +00001236 return MethodHandleInvokeExactInternal(self,
1237 shadow_frame,
1238 method_handle,
1239 callsite_type,
1240 operands,
1241 result);
Orion Hodson811bd5f2016-12-07 11:35:37 +00001242 } else {
Orion Hodson960d4f72017-11-10 15:32:38 +00001243 return MethodHandleInvokeInternal(self,
1244 shadow_frame,
1245 method_handle,
1246 callsite_type,
1247 operands,
1248 result);
Orion Hodson811bd5f2016-12-07 11:35:37 +00001249 }
1250}
1251
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001252bool MethodHandleInvokeExact(Thread* self,
Orion Hodson960d4f72017-11-10 15:32:38 +00001253 ShadowFrame& shadow_frame,
1254 Handle<mirror::MethodHandle> method_handle,
1255 Handle<mirror::MethodType> callsite_type,
1256 const InstructionOperands* const operands,
1257 JValue* result)
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001258 REQUIRES_SHARED(Locks::mutator_lock_) {
1259 // We need to check the nominal type of the handle in addition to the
1260 // real type. The "nominal" type is present when MethodHandle.asType is
1261 // called any handle, and results in the declared type of the handle
1262 // changing.
1263 ObjPtr<mirror::MethodType> nominal_type(method_handle->GetNominalType());
1264 if (UNLIKELY(nominal_type != nullptr)) {
1265 if (UNLIKELY(!callsite_type->IsExactMatch(nominal_type.Ptr()))) {
1266 ThrowWrongMethodTypeException(nominal_type.Ptr(), callsite_type.Get());
1267 return false;
1268 }
1269 if (LIKELY(!nominal_type->IsExactMatch(method_handle->GetMethodType()))) {
1270 // Different nominal type means we have to treat as non-exact.
Orion Hodson960d4f72017-11-10 15:32:38 +00001271 return MethodHandleInvokeInternal(self,
1272 shadow_frame,
1273 method_handle,
1274 callsite_type,
1275 operands,
1276 result);
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001277 }
1278 }
Orion Hodson960d4f72017-11-10 15:32:38 +00001279 return MethodHandleInvokeExactInternal(self,
1280 shadow_frame,
1281 method_handle,
1282 callsite_type,
1283 operands,
1284 result);
Orion Hodson43f0cdb2017-10-10 14:47:32 +01001285}
1286
Orion Hodsonba28f9f2016-10-26 10:56:25 +01001287} // namespace art