summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/class_linker_test.cc1
-rw-r--r--runtime/method_handles-inl.h23
-rw-r--r--runtime/method_handles.cc175
-rw-r--r--runtime/method_handles.h7
-rw-r--r--runtime/mirror/emulated_stack_frame.cc37
-rw-r--r--runtime/mirror/emulated_stack_frame.h5
-rw-r--r--runtime/mirror/method_handle_impl.h1
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,