diff options
-rw-r--r-- | runtime/class_linker_test.cc | 1 | ||||
-rw-r--r-- | runtime/method_handles-inl.h | 23 | ||||
-rw-r--r-- | runtime/method_handles.cc | 175 | ||||
-rw-r--r-- | runtime/method_handles.h | 7 | ||||
-rw-r--r-- | runtime/mirror/emulated_stack_frame.cc | 37 | ||||
-rw-r--r-- | runtime/mirror/emulated_stack_frame.h | 5 | ||||
-rw-r--r-- | runtime/mirror/method_handle_impl.h | 1 |
7 files changed, 53 insertions, 196 deletions
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index a789831238..010b384498 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -769,7 +769,6 @@ struct MethodHandlesLookupOffsets : public CheckOffsets<mirror::MethodHandlesLoo struct EmulatedStackFrameOffsets : public CheckOffsets<mirror::EmulatedStackFrame> { EmulatedStackFrameOffsets() : CheckOffsets<mirror::EmulatedStackFrame>( false, "Ldalvik/system/EmulatedStackFrame;") { - addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, callsite_type_), "callsiteType"); addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, references_), "references"); addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, stack_frame_), "stackFrame"); addOffset(OFFSETOF_MEMBER(mirror::EmulatedStackFrame, type_), "type"); diff --git a/runtime/method_handles-inl.h b/runtime/method_handles-inl.h index 4bd4df10d2..1a1507a06c 100644 --- a/runtime/method_handles-inl.h +++ b/runtime/method_handles-inl.h @@ -237,6 +237,29 @@ bool PerformConversions(Thread* self, return PerformConversions(self, callsite_type, callee_type, getter, setter, 0, num_conversions); } +template <typename G, typename S> +bool CopyArguments(Thread* self, + Handle<mirror::MethodType> method_type, + G* getter, + S* setter) REQUIRES_SHARED(Locks::mutator_lock_) { + StackHandleScope<2> hs(self); + Handle<mirror::ObjectArray<mirror::Class>> ptypes(hs.NewHandle(method_type->GetPTypes())); + int32_t ptypes_length = ptypes->GetLength(); + + for (int32_t i = 0; i < ptypes_length; ++i) { + ObjPtr<mirror::Class> ptype(ptypes->GetWithoutChecks(i)); + Primitive::Type primitive = ptype->GetPrimitiveType(); + if (Primitive::Is64BitType(primitive)) { + setter->SetLong(getter->GetLong()); + } else if (primitive == Primitive::kPrimNot) { + setter->SetReference(getter->GetReference()); + } else { + setter->Set(getter->Get()); + } + } + return true; +} + } // namespace art #endif // ART_RUNTIME_METHOD_HANDLES_INL_H_ diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc index 2f24abf00d..c8e6287804 100644 --- a/runtime/method_handles.cc +++ b/runtime/method_handles.cc @@ -336,41 +336,12 @@ inline void CopyArgumentsFromCallerFrame(const ShadowFrame& caller_frame, } } -inline bool ConvertAndCopyArgumentsFromCallerFrame( - Thread* self, - Handle<mirror::MethodType> callsite_type, - Handle<mirror::MethodType> callee_type, - const ShadowFrame& caller_frame, - uint32_t first_dest_reg, - const InstructionOperands* const operands, - ShadowFrame* callee_frame) - REQUIRES_SHARED(Locks::mutator_lock_) { - ObjPtr<mirror::ObjectArray<mirror::Class>> from_types(callsite_type->GetPTypes()); - ObjPtr<mirror::ObjectArray<mirror::Class>> to_types(callee_type->GetPTypes()); - - const int32_t num_method_params = from_types->GetLength(); - if (to_types->GetLength() != num_method_params) { - ThrowWrongMethodTypeException(callee_type.Get(), callsite_type.Get()); - return false; - } - - ShadowFrameGetter getter(caller_frame, operands); - ShadowFrameSetter setter(callee_frame, first_dest_reg); - return PerformConversions<ShadowFrameGetter, ShadowFrameSetter>(self, - callsite_type, - callee_type, - &getter, - &setter, - num_method_params); -} - inline bool IsInvoke(const mirror::MethodHandle::Kind handle_kind) { return handle_kind <= mirror::MethodHandle::Kind::kLastInvokeKind; } inline bool IsInvokeTransform(const mirror::MethodHandle::Kind handle_kind) { - return (handle_kind == mirror::MethodHandle::Kind::kInvokeTransform - || handle_kind == mirror::MethodHandle::Kind::kInvokeCallSiteTransform); + return (handle_kind == mirror::MethodHandle::Kind::kInvokeTransform); } inline bool IsInvokeVarHandle(const mirror::MethodHandle::Kind handle_kind) { @@ -421,130 +392,31 @@ static inline bool InvokedFromTransform(Handle<mirror::MethodType> callsite_type } static inline bool MethodHandleInvokeMethod(ArtMethod* called_method, - Handle<mirror::MethodType> callsite_type, - Handle<mirror::MethodType> target_type, Thread* self, - ShadowFrame& shadow_frame, - const InstructionOperands* const operands, + ShadowFrame& caller_frame, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { // Compute method information. CodeItemDataAccessor accessor(called_method->DexInstructionData()); - - // Number of registers for the callee's call frame. Note that for non-exact - // invokes, we always derive this information from the callee method. We - // cannot guarantee during verification that the number of registers encoded - // in the invoke is equal to the number of ins for the callee. This is because - // some transformations (such as boxing a long -> Long or wideining an - // int -> long will change that number. - uint16_t num_regs; - size_t num_input_regs; - size_t first_dest_reg; + size_t first_dst_reg; if (LIKELY(accessor.HasCodeItem())) { - num_regs = accessor.RegistersSize(); - first_dest_reg = num_regs - accessor.InsSize(); - num_input_regs = accessor.InsSize(); + uint16_t num_regs = accessor.RegistersSize(); + first_dst_reg = num_regs - accessor.InsSize(); // Parameter registers go at the end of the shadow frame. - DCHECK_NE(first_dest_reg, (size_t)-1); + DCHECK_NE(first_dst_reg, (size_t)-1); } else { // No local regs for proxy and native methods. DCHECK(called_method->IsNative() || called_method->IsProxyMethod()); - num_regs = num_input_regs = GetInsForProxyOrNativeMethod(called_method); - first_dest_reg = 0; - } - - // Allocate shadow frame on the stack. - ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr = - CREATE_SHADOW_FRAME(num_regs, &shadow_frame, called_method, /* dex pc */ 0); - ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get(); - - // Whether this polymorphic invoke was issued by a transformer method. - bool is_caller_transformer = false; - // Thread might be suspended during PerformArgumentConversions due to the - // allocations performed during boxing. - { - ScopedStackedShadowFramePusher pusher( - self, new_shadow_frame, StackedShadowFrameType::kShadowFrameUnderConstruction); - if (callsite_type->IsExactMatch(target_type.Get())) { - // This is an exact invoke, we can take the fast path of just copying all - // registers without performing any argument conversions. - CopyArgumentsFromCallerFrame(shadow_frame, - new_shadow_frame, - operands, - first_dest_reg); - } else { - // This includes the case where we're entering this invoke-polymorphic - // from a transformer method. In that case, the callsite_type will contain - // a single argument of type dalvik.system.EmulatedStackFrame. In that - // case, we'll have to unmarshal the EmulatedStackFrame into the - // new_shadow_frame and perform argument conversions on it. - if (InvokedFromTransform(callsite_type)) { - is_caller_transformer = true; - // The emulated stack frame is the first and only argument when we're coming - // through from a transformer. - size_t first_arg_register = operands->GetOperand(0); - ObjPtr<mirror::EmulatedStackFrame> emulated_stack_frame( - ObjPtr<mirror::EmulatedStackFrame>::DownCast( - shadow_frame.GetVRegReference(first_arg_register))); - if (!emulated_stack_frame->WriteToShadowFrame(self, - target_type, - first_dest_reg, - new_shadow_frame)) { - DCHECK(self->IsExceptionPending()); - result->SetL(nullptr); - return false; - } - } else { - if (!callsite_type->IsConvertible(target_type.Get())) { - ThrowWrongMethodTypeException(target_type.Get(), callsite_type.Get()); - return false; - } - if (!ConvertAndCopyArgumentsFromCallerFrame(self, - callsite_type, - target_type, - shadow_frame, - first_dest_reg, - operands, - new_shadow_frame)) { - DCHECK(self->IsExceptionPending()); - result->SetL(nullptr); - return false; - } - } - } + first_dst_reg = 0; } PerformCall(self, accessor, - shadow_frame.GetMethod(), - first_dest_reg, - new_shadow_frame, + caller_frame.GetMethod(), + first_dst_reg, + &caller_frame, result, interpreter::ShouldStayInSwitchInterpreter(called_method)); - if (self->IsExceptionPending()) { - return false; - } - - // If the caller of this signature polymorphic method was a transformer, - // we need to copy the result back out to the emulated stack frame. - if (is_caller_transformer) { - StackHandleScope<2> hs(self); - size_t first_callee_register = operands->GetOperand(0); - Handle<mirror::EmulatedStackFrame> emulated_stack_frame( - hs.NewHandle(ObjPtr<mirror::EmulatedStackFrame>::DownCast( - shadow_frame.GetVRegReference(first_callee_register)))); - Handle<mirror::MethodType> emulated_stack_type(hs.NewHandle(emulated_stack_frame->GetType())); - JValue local_result; - local_result.SetJ(result->GetJ()); - - if (ConvertReturnValue(emulated_stack_type, target_type, &local_result)) { - emulated_stack_frame->SetReturnValue(self, local_result); - return true; - } - - DCHECK(self->IsExceptionPending()); - return false; - } - return ConvertReturnValue(callsite_type, target_type, result); + return !self->IsExceptionPending(); } static inline bool MethodHandleInvokeTransform(ArtMethod* called_method, @@ -737,33 +609,16 @@ bool DoInvokePolymorphicMethod(Thread* self, } if (IsInvokeTransform(handle_kind)) { - // There are two cases here - method handles representing regular - // transforms and those representing call site transforms. Method - // handles for call site transforms adapt their MethodType to match - // the call site. For these, the |callee_type| is the same as the - // |callsite_type|. The VarargsCollector is such a tranform, its - // method type depends on the call site, ie. x(a) or x(a, b), or - // x(a, b, c). The VarargsCollector invokes a variable arity method - // with the arity arguments in an array. - Handle<mirror::MethodType> callee_type = - (handle_kind == mirror::MethodHandle::Kind::kInvokeCallSiteTransform) ? callsite_type - : handle_type; return MethodHandleInvokeTransform(called_method, callsite_type, - callee_type, + handle_type, self, shadow_frame, /* receiver= */ method_handle, operands, result); } else { - return MethodHandleInvokeMethod(called_method, - callsite_type, - handle_type, - self, - shadow_frame, - operands, - result); + return MethodHandleInvokeMethod(called_method, self, shadow_frame, result); } } @@ -1112,18 +967,16 @@ static inline bool MethodHandleInvokeExactInternal( // Compute method information. CodeItemDataAccessor accessor(called_method->DexInstructionData()); uint16_t num_regs; - size_t num_input_regs; size_t first_dest_reg; if (LIKELY(accessor.HasCodeItem())) { num_regs = accessor.RegistersSize(); first_dest_reg = num_regs - accessor.InsSize(); - num_input_regs = accessor.InsSize(); // Parameter registers go at the end of the shadow frame. DCHECK_NE(first_dest_reg, (size_t)-1); } else { // No local regs for proxy and native methods. DCHECK(called_method->IsNative() || called_method->IsProxyMethod()); - num_regs = num_input_regs = GetInsForProxyOrNativeMethod(called_method); + num_regs = GetInsForProxyOrNativeMethod(called_method); first_dest_reg = 0; } diff --git a/runtime/method_handles.h b/runtime/method_handles.h index b6e31345e1..a098bc6783 100644 --- a/runtime/method_handles.h +++ b/runtime/method_handles.h @@ -127,6 +127,13 @@ bool PerformConversions(Thread* self, int32_t start_index, int32_t end_index) REQUIRES_SHARED(Locks::mutator_lock_); +template <typename G, typename S> +bool CopyArguments(Thread* self, + Handle<mirror::MethodType> method_type, + Handle<mirror::MethodType> callee_type, + G* getter, + S* setter) REQUIRES_SHARED(Locks::mutator_lock_); + bool MethodHandleInvoke(Thread* self, ShadowFrame& shadow_frame, Handle<mirror::MethodHandle> method_handle, diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc index 19e40dc148..933cd3632f 100644 --- a/runtime/mirror/emulated_stack_frame.cc +++ b/runtime/mirror/emulated_stack_frame.cc @@ -151,23 +151,15 @@ ObjPtr<mirror::EmulatedStackFrame> EmulatedStackFrame::CreateFromShadowFrameAndA const InstructionOperands* const operands) { StackHandleScope<6> hs(self); - // Step 1: We must throw a WrongMethodTypeException if there's a mismatch in the - // number of arguments between the caller and the callsite. - Handle<mirror::ObjectArray<mirror::Class>> from_types(hs.NewHandle(caller_type->GetPTypes())); - Handle<mirror::ObjectArray<mirror::Class>> to_types(hs.NewHandle(callee_type->GetPTypes())); - - const int32_t num_method_params = from_types->GetLength(); - if (to_types->GetLength() != num_method_params) { - ThrowWrongMethodTypeException(callee_type.Get(), caller_type.Get()); - return nullptr; - } + DCHECK(callee_type->IsExactMatch(caller_type.Get())); + Handle<mirror::ObjectArray<mirror::Class>> p_types(hs.NewHandle(callee_type->GetPTypes())); // Step 2: Calculate the size of the reference / byte arrays in the emulated // stack frame. size_t frame_size = 0; size_t refs_size = 0; Handle<mirror::Class> r_type(hs.NewHandle(callee_type->GetRType())); - CalculateFrameAndReferencesSize(to_types.Get(), r_type.Get(), &frame_size, &refs_size); + CalculateFrameAndReferencesSize(p_types.Get(), r_type.Get(), &frame_size, &refs_size); // Step 3 : Allocate the arrays. ObjPtr<mirror::Class> array_class(GetClassRoot<mirror::ObjectArray<mirror::Object>>()); @@ -185,18 +177,15 @@ ObjPtr<mirror::EmulatedStackFrame> EmulatedStackFrame::CreateFromShadowFrameAndA return nullptr; } - // Step 4 : Perform argument conversions (if required). + // Step 4 : Copy arguments. ShadowFrameGetter getter(caller_frame, operands); EmulatedStackFrameAccessor setter(references, stack_frame, stack_frame->GetLength()); - if (!PerformConversions<ShadowFrameGetter, EmulatedStackFrameAccessor>( - self, caller_type, callee_type, &getter, &setter, num_method_params)) { - return nullptr; - } + CopyArguments<ShadowFrameGetter, EmulatedStackFrameAccessor>( + self, caller_type, &getter, &setter); // Step 5: Construct the EmulatedStackFrame object. Handle<EmulatedStackFrame> sf(hs.NewHandle( ObjPtr<EmulatedStackFrame>::DownCast(GetClassRoot<EmulatedStackFrame>()->AllocObject(self)))); - sf->SetFieldObject<false>(CallsiteTypeOffset(), caller_type.Get()); sf->SetFieldObject<false>(TypeOffset(), callee_type.Get()); sf->SetFieldObject<false>(ReferencesOffset(), references.Get()); sf->SetFieldObject<false>(StackFrameOffset(), stack_frame.Get()); @@ -208,25 +197,17 @@ bool EmulatedStackFrame::WriteToShadowFrame(Thread* self, Handle<mirror::MethodType> callee_type, const uint32_t first_dest_reg, ShadowFrame* callee_frame) { - ObjPtr<mirror::ObjectArray<mirror::Class>> from_types(GetType()->GetPTypes()); - ObjPtr<mirror::ObjectArray<mirror::Class>> to_types(callee_type->GetPTypes()); - - const int32_t num_method_params = from_types->GetLength(); - if (to_types->GetLength() != num_method_params) { - ThrowWrongMethodTypeException(callee_type.Get(), GetType()); - return false; - } + DCHECK(callee_type->IsExactMatch(GetType())); StackHandleScope<3> hs(self); - Handle<mirror::MethodType> frame_callsite_type(hs.NewHandle(GetType())); Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(GetReferences())); Handle<ByteArray> stack_frame(hs.NewHandle(GetStackFrame())); EmulatedStackFrameAccessor getter(references, stack_frame, stack_frame->GetLength()); ShadowFrameSetter setter(callee_frame, first_dest_reg); - return PerformConversions<EmulatedStackFrameAccessor, ShadowFrameSetter>( - self, frame_callsite_type, callee_type, &getter, &setter, num_method_params); + CopyArguments<EmulatedStackFrameAccessor, ShadowFrameSetter>(self, callee_type, &getter, &setter); + return true; } void EmulatedStackFrame::GetReturnValue(Thread* self, JValue* value) { diff --git a/runtime/mirror/emulated_stack_frame.h b/runtime/mirror/emulated_stack_frame.h index b63ccaabf9..fef6e3fad9 100644 --- a/runtime/mirror/emulated_stack_frame.h +++ b/runtime/mirror/emulated_stack_frame.h @@ -68,10 +68,6 @@ class MANAGED EmulatedStackFrame : public Object { ObjPtr<mirror::ByteArray> GetStackFrame() REQUIRES_SHARED(Locks::mutator_lock_); - static MemberOffset CallsiteTypeOffset() { - return MemberOffset(OFFSETOF_MEMBER(EmulatedStackFrame, callsite_type_)); - } - static MemberOffset TypeOffset() { return MemberOffset(OFFSETOF_MEMBER(EmulatedStackFrame, type_)); } @@ -84,7 +80,6 @@ class MANAGED EmulatedStackFrame : public Object { return MemberOffset(OFFSETOF_MEMBER(EmulatedStackFrame, stack_frame_)); } - HeapReference<mirror::MethodType> callsite_type_; HeapReference<mirror::ObjectArray<mirror::Object>> references_; HeapReference<mirror::ByteArray> stack_frame_; HeapReference<mirror::MethodType> type_; diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h index 0a7042248d..ef354a9d0a 100644 --- a/runtime/mirror/method_handle_impl.h +++ b/runtime/mirror/method_handle_impl.h @@ -50,7 +50,6 @@ class MANAGED MethodHandle : public Object { kInvokeStatic, kInvokeInterface, kInvokeTransform, - kInvokeCallSiteTransform, kInvokeVarHandle, kInvokeVarHandleExact, kInstanceGet, |