diff options
author | 2017-11-10 15:32:38 +0000 | |
---|---|---|
committer | 2017-11-13 10:13:13 +0000 | |
commit | 960d4f7c5f6a464aa00b8f393cc88996c55464f3 (patch) | |
tree | dcc69d9ab9b36afd5b22a0dbbf0e6279f8a26cf6 | |
parent | e983b1658589e2a3d12620846b7e2351af26afa6 (diff) |
ART: Simplify MethodHandle invocations
Use an operand iterator rather than passing arguments for both
range and varargs operands.
Test: art/test.py --host -j32
Change-Id: Ia42398773bd3732d917e19c25aa431b1e1369320
-rw-r--r-- | runtime/dex_instruction.cc | 10 | ||||
-rw-r--r-- | runtime/dex_instruction.h | 47 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 30 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_common.cc | 103 | ||||
-rw-r--r-- | runtime/method_handles.cc | 295 | ||||
-rw-r--r-- | runtime/method_handles.h | 58 | ||||
-rw-r--r-- | runtime/mirror/emulated_stack_frame.cc | 24 | ||||
-rw-r--r-- | runtime/mirror/emulated_stack_frame.h | 4 |
8 files changed, 265 insertions, 306 deletions
diff --git a/runtime/dex_instruction.cc b/runtime/dex_instruction.cc index e64c0f62c2..6ebe2286e8 100644 --- a/runtime/dex_instruction.cc +++ b/runtime/dex_instruction.cc @@ -548,4 +548,14 @@ std::ostream& operator<<(std::ostream& os, const Instruction::Code& code) { return os << Instruction::Name(code); } +uint32_t RangeInstructionOperands::GetOperand(size_t operand_index) const { + DCHECK_LT(operand_index, GetNumberOfOperands()); + return first_operand_ + operand_index; +} + +uint32_t VarArgsInstructionOperands::GetOperand(size_t operand_index) const { + DCHECK_LT(operand_index, GetNumberOfOperands()); + return operands_[operand_index]; +} + } // namespace art diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h index 09c78b2428..4041820616 100644 --- a/runtime/dex_instruction.h +++ b/runtime/dex_instruction.h @@ -689,6 +689,53 @@ std::ostream& operator<<(std::ostream& os, const Instruction::Format& format); std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags); std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags); +// Base class for accessing instruction operands. Unifies operand +// access for instructions that have range and varargs forms +// (e.g. invoke-polymoprhic/range and invoke-polymorphic). +class InstructionOperands { + public: + explicit InstructionOperands(size_t num_operands) : num_operands_(num_operands) {} + virtual ~InstructionOperands() {} + virtual uint32_t GetOperand(size_t index) const = 0; + size_t GetNumberOfOperands() const { return num_operands_; } + + private: + size_t num_operands_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(InstructionOperands); +}; + +// Class for accessing operands for instructions with a range format +// (e.g. 3rc and 4rcc). +class RangeInstructionOperands FINAL : public InstructionOperands { + public: + RangeInstructionOperands(uint32_t first_operand, size_t num_operands) + : InstructionOperands(num_operands), first_operand_(first_operand) {} + ~RangeInstructionOperands() {} + uint32_t GetOperand(size_t operand_index) const OVERRIDE; + + private: + const uint32_t first_operand_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(RangeInstructionOperands); +}; + +// Class for accessing operands for instructions with a variable +// number of arguments format (e.g. 35c and 45cc). +class VarArgsInstructionOperands FINAL : public InstructionOperands { + public: + VarArgsInstructionOperands(const uint32_t (&operands)[Instruction::kMaxVarArgRegs], + size_t num_operands) + : InstructionOperands(num_operands), operands_(operands) {} + ~VarArgsInstructionOperands() {} + uint32_t GetOperand(size_t operand_index) const OVERRIDE; + + private: + const uint32_t (&operands_)[Instruction::kMaxVarArgRegs]; + + DISALLOW_IMPLICIT_CONSTRUCTORS(VarArgsInstructionOperands); +}; + } // namespace art #endif // ART_RUNTIME_DEX_INSTRUCTION_H_ diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 127b5d7028..22c9a1d31a 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -2649,28 +2649,24 @@ extern "C" uintptr_t artInvokePolymorphic( // Call DoInvokePolymorphic with |is_range| = true, as shadow frame has argument registers in // consecutive order. - uint32_t unused_args[Instruction::kMaxVarArgRegs] = {}; - uint32_t first_callee_arg = first_arg + 1; - + RangeInstructionOperands operands(first_arg + 1, num_vregs - 1); bool isExact = (jni::EncodeArtMethod(resolved_method) == WellKnownClasses::java_lang_invoke_MethodHandle_invokeExact); bool success = false; if (isExact) { - success = MethodHandleInvokeExact<true/*is_range*/>(self, - *shadow_frame, - method_handle, - method_type, - unused_args, - first_callee_arg, - result); + success = MethodHandleInvokeExact(self, + *shadow_frame, + method_handle, + method_type, + &operands, + result); } else { - success = MethodHandleInvoke<true/*is_range*/>(self, - *shadow_frame, - method_handle, - method_type, - unused_args, - first_callee_arg, - result); + success = MethodHandleInvoke(self, + *shadow_frame, + method_handle, + method_type, + &operands, + result); } DCHECK(success || self->IsExceptionPending()); diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 0a1ae36167..d2d017e118 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -644,52 +644,47 @@ static bool DoMethodHandleInvokeCommon(Thread* self, // arguments either from a range or an array of arguments depending // on whether the DEX instruction is invoke-polymorphic/range or // invoke-polymorphic. The array here is for the latter. - uint32_t args[Instruction::kMaxVarArgRegs] = {}; if (UNLIKELY(is_range)) { // VRegC is the register holding the method handle. Arguments passed // to the method handle's target do not include the method handle. - uint32_t first_arg = inst->VRegC_4rcc() + 1; - static const bool kIsRange = true; + RangeInstructionOperands operands(inst->VRegC_4rcc() + 1, inst->VRegA_4rcc() - 1); if (invoke_exact) { - return art::MethodHandleInvokeExact<kIsRange>(self, - shadow_frame, - method_handle, - callsite_type, - args /* unused */, - first_arg, - result); + return MethodHandleInvokeExact(self, + shadow_frame, + method_handle, + callsite_type, + &operands, + result); } else { - return art::MethodHandleInvoke<kIsRange>(self, - shadow_frame, - method_handle, - callsite_type, - args /* unused */, - first_arg, - result); + return MethodHandleInvoke(self, + shadow_frame, + method_handle, + callsite_type, + &operands, + result); } } else { // Get the register arguments for the invoke. + uint32_t args[Instruction::kMaxVarArgRegs] = {}; inst->GetVarArgs(args, inst_data); // Drop the first register which is the method handle performing the invoke. memmove(args, args + 1, sizeof(args[0]) * (Instruction::kMaxVarArgRegs - 1)); args[Instruction::kMaxVarArgRegs - 1] = 0; - static const bool kIsRange = false; + VarArgsInstructionOperands operands(args, inst->VRegA_45cc() - 1); if (invoke_exact) { - return art::MethodHandleInvokeExact<kIsRange>(self, - shadow_frame, - method_handle, - callsite_type, - args, - args[0], - result); + return MethodHandleInvokeExact(self, + shadow_frame, + method_handle, + callsite_type, + &operands, + result); } else { - return art::MethodHandleInvoke<kIsRange>(self, - shadow_frame, - method_handle, - callsite_type, - args, - args[0], - result); + return MethodHandleInvoke(self, + shadow_frame, + method_handle, + callsite_type, + &operands, + result); } } } @@ -1180,17 +1175,13 @@ static ObjPtr<mirror::CallSite> InvokeBootstrapMethod(Thread* self, // Invoke the bootstrap method handle. JValue result; - - // This array of arguments is unused. DoMethodHandleInvokeExact() operates on either a - // an argument array or a range, but always takes an array argument. - uint32_t args_unused[Instruction::kMaxVarArgRegs]; - bool invoke_success = art::MethodHandleInvokeExact<true /* is_range */>(self, - *bootstrap_frame, - bootstrap, - bootstrap_method_type, - args_unused, - 0, - &result); + RangeInstructionOperands operands(0, vreg); + bool invoke_success = MethodHandleInvokeExact(self, + *bootstrap_frame, + bootstrap, + bootstrap_method_type, + &operands, + &result); if (!invoke_success) { DCHECK(self->IsExceptionPending()); return nullptr; @@ -1273,21 +1264,25 @@ bool DoInvokeCustom(Thread* self, Handle<mirror::MethodHandle> target = hs.NewHandle(call_site->GetTarget()); Handle<mirror::MethodType> target_method_type = hs.NewHandle(target->GetMethodType()); DCHECK_EQ(static_cast<size_t>(inst->VRegA()), target_method_type->NumberOfVRegs()); - - uint32_t args[Instruction::kMaxVarArgRegs]; if (is_range) { - args[0] = inst->VRegC_3rc(); + RangeInstructionOperands operands(inst->VRegC_3rc(), inst->VRegA_3rc()); + return MethodHandleInvokeExact(self, + shadow_frame, + target, + target_method_type, + &operands, + result); } else { + uint32_t args[Instruction::kMaxVarArgRegs]; inst->GetVarArgs(args, inst_data); + VarArgsInstructionOperands operands(args, inst->VRegA_35c()); + return MethodHandleInvokeExact(self, + shadow_frame, + target, + target_method_type, + &operands, + result); } - - return art::MethodHandleInvokeExact<is_range>(self, - shadow_frame, - target, - target_method_type, - args, - args[0], - result); } template <bool is_range> diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc index 5a5d5713a8..8eb31c1ef8 100644 --- a/runtime/method_handles.cc +++ b/runtime/method_handles.cc @@ -299,17 +299,14 @@ bool ConvertJValueCommon( namespace { -template <bool is_range> inline void CopyArgumentsFromCallerFrame(const ShadowFrame& caller_frame, ShadowFrame* callee_frame, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, - const size_t first_dst_reg, - const size_t num_regs) + const InstructionOperands* const operands, + const size_t first_dst_reg) REQUIRES_SHARED(Locks::mutator_lock_) { - for (size_t i = 0; i < num_regs; ++i) { + for (size_t i = 0; i < operands->GetNumberOfOperands(); ++i) { size_t dst_reg = first_dst_reg + i; - size_t src_reg = is_range ? (first_arg + i) : args[i]; + size_t src_reg = operands->GetOperand(i); // Uint required, so that sign extension does not make this wrong on 64-bit systems uint32_t src_value = caller_frame.GetVReg(src_reg); ObjPtr<mirror::Object> o = caller_frame.GetVRegReference<kVerifyNone>(src_reg); @@ -324,15 +321,13 @@ inline void CopyArgumentsFromCallerFrame(const ShadowFrame& caller_frame, } } -template <bool is_range> inline bool ConvertAndCopyArgumentsFromCallerFrame( Thread* self, Handle<mirror::MethodType> callsite_type, Handle<mirror::MethodType> callee_type, const ShadowFrame& caller_frame, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, - uint32_t first_dst_reg, + 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()); @@ -344,15 +339,14 @@ inline bool ConvertAndCopyArgumentsFromCallerFrame( return false; } - ShadowFrameGetter<is_range> getter(first_arg, args, caller_frame); - ShadowFrameSetter setter(callee_frame, first_dst_reg); - - return PerformConversions<ShadowFrameGetter<is_range>, ShadowFrameSetter>(self, - callsite_type, - callee_type, - &getter, - &setter, - num_method_params); + ShadowFrameGetter getter(operands, caller_frame); + 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) { @@ -406,14 +400,12 @@ static inline bool IsCallerTransformer(Handle<mirror::MethodType> callsite_type) return false; } -template <bool is_range> static inline bool MethodHandleInvokeMethod(ArtMethod* called_method, Handle<mirror::MethodType> callsite_type, Handle<mirror::MethodType> target_type, Thread* self, ShadowFrame& shadow_frame, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, + const InstructionOperands* const operands, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { // Compute method information. const DexFile::CodeItem* code_item = called_method->GetCodeItem(); @@ -455,12 +447,10 @@ static inline bool MethodHandleInvokeMethod(ArtMethod* called_method, 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<is_range>(shadow_frame, - new_shadow_frame, - args, - first_arg, - first_dest_reg, - num_input_regs); + 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 @@ -471,7 +461,7 @@ static inline bool MethodHandleInvokeMethod(ArtMethod* called_method, 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 = (is_range) ? first_arg : args[0]; + size_t first_arg_register = operands->GetOperand(0); ObjPtr<mirror::EmulatedStackFrame> emulated_stack_frame( reinterpret_cast<mirror::EmulatedStackFrame*>( shadow_frame.GetVRegReference(first_arg_register))); @@ -488,14 +478,13 @@ static inline bool MethodHandleInvokeMethod(ArtMethod* called_method, ThrowWrongMethodTypeException(target_type.Get(), callsite_type.Get()); return false; } - if (!ConvertAndCopyArgumentsFromCallerFrame<is_range>(self, - callsite_type, - target_type, - shadow_frame, - args, - first_arg, - first_dest_reg, - new_shadow_frame)) { + if (!ConvertAndCopyArgumentsFromCallerFrame(self, + callsite_type, + target_type, + shadow_frame, + first_dest_reg, + operands, + new_shadow_frame)) { DCHECK(self->IsExceptionPending()); result->SetL(0); return false; @@ -521,7 +510,7 @@ static inline bool MethodHandleInvokeMethod(ArtMethod* called_method, // 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 = is_range ? (first_arg) : args[0]; + size_t first_callee_register = operands->GetOperand(0); Handle<mirror::EmulatedStackFrame> emulated_stack_frame( hs.NewHandle(reinterpret_cast<mirror::EmulatedStackFrame*>( shadow_frame.GetVRegReference(first_callee_register)))); @@ -541,15 +530,13 @@ static inline bool MethodHandleInvokeMethod(ArtMethod* called_method, return ConvertReturnValue(callsite_type, target_type, result); } -template <bool is_range> static inline bool MethodHandleInvokeTransform(ArtMethod* called_method, Handle<mirror::MethodType> callsite_type, Handle<mirror::MethodType> callee_type, Thread* self, ShadowFrame& shadow_frame, Handle<mirror::MethodHandle> receiver, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, + const InstructionOperands* const operands, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { // This can be fixed to two, because the method we're calling here @@ -578,16 +565,15 @@ static inline bool MethodHandleInvokeTransform(ArtMethod* called_method, // If we're entering this transformer from another transformer, we can pass // through the handle directly to the callee, instead of having to // instantiate a new stack frame based on the shadow frame. - size_t first_callee_register = is_range ? first_arg : args[0]; + size_t first_callee_register = operands->GetOperand(0); sf.Assign(reinterpret_cast<mirror::EmulatedStackFrame*>( shadow_frame.GetVRegReference(first_callee_register))); } else { - sf.Assign(mirror::EmulatedStackFrame::CreateFromShadowFrameAndArgs<is_range>(self, - callsite_type, - callee_type, - shadow_frame, - first_arg, - args)); + sf.Assign(mirror::EmulatedStackFrame::CreateFromShadowFrameAndArgs(self, + callsite_type, + callee_type, + shadow_frame, + operands)); // Something went wrong while creating the emulated stack frame, we should // throw the pending exception. @@ -699,13 +685,11 @@ ArtMethod* RefineTargetMethod(Thread* self, return target_method; } -template <bool is_range> bool DoInvokePolymorphicMethod(Thread* self, ShadowFrame& shadow_frame, Handle<mirror::MethodHandle> method_handle, Handle<mirror::MethodType> callsite_type, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, + const InstructionOperands* const operands, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { StackHandleScope<1> hs(self); @@ -718,7 +702,7 @@ bool DoInvokePolymorphicMethod(Thread* self, // point because they would have been performed on our behalf at the point // of creation of the method handle. ArtMethod* target_method = method_handle->GetTargetMethod(); - uint32_t receiver_reg = is_range ? first_arg: args[0]; + uint32_t receiver_reg = (operands->GetNumberOfOperands() > 0) ? operands->GetOperand(0) : 0u; ArtMethod* called_method = RefineTargetMethod(self, shadow_frame, handle_kind, @@ -743,24 +727,22 @@ bool DoInvokePolymorphicMethod(Thread* self, Handle<mirror::MethodType> callee_type = (handle_kind == mirror::MethodHandle::Kind::kInvokeCallSiteTransform) ? callsite_type : handle_type; - return MethodHandleInvokeTransform<is_range>(called_method, - callsite_type, - callee_type, - self, - shadow_frame, - method_handle /* receiver */, - args, - first_arg, - result); + return MethodHandleInvokeTransform(called_method, + callsite_type, + callee_type, + self, + shadow_frame, + method_handle /* receiver */, + operands, + result); } else { - return MethodHandleInvokeMethod<is_range>(called_method, - callsite_type, - handle_type, - self, - shadow_frame, - args, - first_arg, - result); + return MethodHandleInvokeMethod(called_method, + callsite_type, + handle_type, + self, + shadow_frame, + operands, + result); } } @@ -884,23 +866,21 @@ static JValue GetValueFromShadowFrame(const ShadowFrame& shadow_frame, return field_value; } -template <bool is_range, bool do_conversions> +template <bool do_conversions> bool MethodHandleFieldAccess(Thread* self, ShadowFrame& shadow_frame, Handle<mirror::MethodHandle> method_handle, Handle<mirror::MethodType> callsite_type, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, + const InstructionOperands* const operands, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { StackHandleScope<1> hs(self); Handle<mirror::MethodType> handle_type(hs.NewHandle(method_handle->GetMethodType())); const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind(); ArtField* field = method_handle->GetTargetField(); Primitive::Type field_type = field->GetTypeAsPrimitiveType(); - switch (handle_kind) { case mirror::MethodHandle::kInstanceGet: { - size_t obj_reg = is_range ? first_arg : args[0]; + size_t obj_reg = operands->GetOperand(0); ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(obj_reg); MethodHandleFieldGet(self, shadow_frame, obj, field, field_type, result); if (do_conversions && !ConvertReturnValue(callsite_type, handle_type, result)) { @@ -923,8 +903,8 @@ bool MethodHandleFieldAccess(Thread* self, return true; } case mirror::MethodHandle::kInstancePut: { - size_t obj_reg = is_range ? first_arg : args[0]; - size_t value_reg = is_range ? (first_arg + 1) : args[1]; + size_t obj_reg = operands->GetOperand(0); + size_t value_reg = operands->GetOperand(1); const size_t kPTypeIndex = 1; // Use ptypes instead of field type since we may be unboxing a reference for a primitive // field. The field type is incorrect for this case. @@ -948,7 +928,7 @@ bool MethodHandleFieldAccess(Thread* self, DCHECK(self->IsExceptionPending()); return false; } - size_t value_reg = is_range ? first_arg : args[0]; + size_t value_reg = operands->GetOperand(0); const size_t kPTypeIndex = 0; // Use ptypes instead of field type since we may be unboxing a reference for a primitive // field. The field type is incorrect for this case. @@ -971,13 +951,11 @@ bool MethodHandleFieldAccess(Thread* self, } } -template <bool is_range> static inline bool MethodHandleInvokeInternal(Thread* self, ShadowFrame& shadow_frame, Handle<mirror::MethodHandle> method_handle, Handle<mirror::MethodType> callsite_type, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, + const InstructionOperands* const operands, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind(); @@ -989,32 +967,28 @@ static inline bool MethodHandleInvokeInternal(Thread* self, return false; } const bool do_convert = true; - return MethodHandleFieldAccess<is_range, do_convert>( + return MethodHandleFieldAccess<do_convert>( self, shadow_frame, method_handle, callsite_type, - args, - first_arg, + operands, result); } - return DoInvokePolymorphicMethod<is_range>(self, - shadow_frame, - method_handle, - callsite_type, - args, - first_arg, - result); + return DoInvokePolymorphicMethod(self, + shadow_frame, + method_handle, + callsite_type, + operands, + result); } -template <bool is_range> static inline bool MethodHandleInvokeExactInternal( Thread* self, ShadowFrame& shadow_frame, Handle<mirror::MethodHandle> method_handle, Handle<mirror::MethodType> callsite_type, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, + const InstructionOperands* const operands, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { StackHandleScope<1> hs(self); @@ -1027,29 +1001,27 @@ static inline bool MethodHandleInvokeExactInternal( const mirror::MethodHandle::Kind handle_kind = method_handle->GetHandleKind(); if (IsFieldAccess(handle_kind)) { const bool do_convert = false; - return MethodHandleFieldAccess<is_range, do_convert>(self, - shadow_frame, - method_handle, - callsite_type, - args, - first_arg, - result); - } - - // Slow-path check. - if (IsInvokeTransform(handle_kind) || IsCallerTransformer(callsite_type)) { - return DoInvokePolymorphicMethod<is_range>(self, + return MethodHandleFieldAccess<do_convert>(self, shadow_frame, method_handle, callsite_type, - args, - first_arg, + operands, result); } + // Slow-path check. + if (IsInvokeTransform(handle_kind) || IsCallerTransformer(callsite_type)) { + return DoInvokePolymorphicMethod(self, + shadow_frame, + method_handle, + callsite_type, + operands, + result); + } + // On the fast-path. This is equivalent to DoCallPolymoprhic without the conversion paths. ArtMethod* target_method = method_handle->GetTargetMethod(); - uint32_t receiver_reg = is_range ? first_arg : args[0]; + uint32_t receiver_reg = (operands->GetNumberOfOperands() > 0) ? operands->GetOperand(0) : 0u; ArtMethod* called_method = RefineTargetMethod(self, shadow_frame, handle_kind, @@ -1085,12 +1057,10 @@ static inline bool MethodHandleInvokeExactInternal( 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(); - CopyArgumentsFromCallerFrame<is_range>(shadow_frame, - new_shadow_frame, - args, - first_arg, - first_dest_reg, - num_input_regs); + CopyArgumentsFromCallerFrame(shadow_frame, + new_shadow_frame, + operands, + first_dest_reg); self->EndAssertNoThreadSuspension(old_cause); bool use_interpreter_entrypoint = ClassLinker::ShouldUseInterpreterEntrypoint( @@ -1110,43 +1080,37 @@ static inline bool MethodHandleInvokeExactInternal( } // namespace -template <bool is_range> -inline bool MethodHandleInvoke(Thread* self, - ShadowFrame& shadow_frame, - Handle<mirror::MethodHandle> method_handle, - Handle<mirror::MethodType> callsite_type, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, - JValue* result) +bool MethodHandleInvoke(Thread* self, + ShadowFrame& shadow_frame, + Handle<mirror::MethodHandle> method_handle, + Handle<mirror::MethodType> callsite_type, + const InstructionOperands* const operands, + JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { if (UNLIKELY(callsite_type->IsExactMatch(method_handle->GetMethodType()))) { // A non-exact invoke that can be invoked exactly. - return MethodHandleInvokeExactInternal<is_range>(self, - shadow_frame, - method_handle, - callsite_type, - args, - first_arg, - result); + return MethodHandleInvokeExactInternal(self, + shadow_frame, + method_handle, + callsite_type, + operands, + result); } else { - return MethodHandleInvokeInternal<is_range>(self, - shadow_frame, - method_handle, - callsite_type, - args, - first_arg, - result); + return MethodHandleInvokeInternal(self, + shadow_frame, + method_handle, + callsite_type, + operands, + result); } } -template <bool is_range> bool MethodHandleInvokeExact(Thread* self, - ShadowFrame& shadow_frame, - Handle<mirror::MethodHandle> method_handle, - Handle<mirror::MethodType> callsite_type, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, - JValue* result) + ShadowFrame& shadow_frame, + Handle<mirror::MethodHandle> method_handle, + Handle<mirror::MethodType> callsite_type, + const InstructionOperands* const operands, + JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { // We need to check the nominal type of the handle in addition to the // real type. The "nominal" type is present when MethodHandle.asType is @@ -1160,39 +1124,20 @@ bool MethodHandleInvokeExact(Thread* self, } if (LIKELY(!nominal_type->IsExactMatch(method_handle->GetMethodType()))) { // Different nominal type means we have to treat as non-exact. - return MethodHandleInvokeInternal<is_range>(self, - shadow_frame, - method_handle, - callsite_type, - args, - first_arg, - result); + return MethodHandleInvokeInternal(self, + shadow_frame, + method_handle, + callsite_type, + operands, + result); } } - return MethodHandleInvokeExactInternal<is_range>(self, - shadow_frame, - method_handle, - callsite_type, - args, - first_arg, - result); + return MethodHandleInvokeExactInternal(self, + shadow_frame, + method_handle, + callsite_type, + operands, + result); } -#define EXPLICIT_DO_METHOD_HANDLE_METHOD(_name, _is_range) \ - template REQUIRES_SHARED(Locks::mutator_lock_) \ - bool MethodHandle##_name<_is_range>( \ - Thread* self, \ - ShadowFrame& shadow_frame, \ - Handle<mirror::MethodHandle> method_handle, \ - Handle<mirror::MethodType> callsite_type, \ - const uint32_t (&args)[Instruction::kMaxVarArgRegs], \ - uint32_t first_arg, \ - JValue* result) - -EXPLICIT_DO_METHOD_HANDLE_METHOD(Invoke, true); -EXPLICIT_DO_METHOD_HANDLE_METHOD(Invoke, false); -EXPLICIT_DO_METHOD_HANDLE_METHOD(InvokeExact, true); -EXPLICIT_DO_METHOD_HANDLE_METHOD(InvokeExact, false); -#undef EXPLICIT_DO_METHOD_HANDLE_METHOD - } // namespace art diff --git a/runtime/method_handles.h b/runtime/method_handles.h index 930b8db63e..bc74bf23d2 100644 --- a/runtime/method_handles.h +++ b/runtime/method_handles.h @@ -126,50 +126,40 @@ bool PerformConversions(Thread* self, int32_t num_conversions) REQUIRES_SHARED(Locks::mutator_lock_); // A convenience class that allows for iteration through a list of -// input argument registers |arg| for non-range invokes or a list of -// consecutive registers starting with a given based for range -// invokes. -// -// This is used to iterate over input arguments while performing standard -// argument conversions. -template <bool is_range> +// input argument registers. This is used to iterate over input +// arguments while performing standard argument conversions. class ShadowFrameGetter { public: - ShadowFrameGetter(size_t first_src_reg, - const uint32_t (&arg)[Instruction::kMaxVarArgRegs], - const ShadowFrame& shadow_frame) : - first_src_reg_(first_src_reg), - arg_(arg), - shadow_frame_(shadow_frame), - arg_index_(0) { - } + ShadowFrameGetter(const InstructionOperands* const operands, const ShadowFrame& shadow_frame) + : operands_(operands), operand_index_(0), shadow_frame_(shadow_frame) {} ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) { - const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]); - ++arg_index_; - - return shadow_frame_.GetVReg(next); + return shadow_frame_.GetVReg(Next()); } ALWAYS_INLINE int64_t GetLong() REQUIRES_SHARED(Locks::mutator_lock_) { - const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]); - arg_index_ += 2; - - return shadow_frame_.GetVRegLong(next); + return shadow_frame_.GetVRegLong(NextLong()); } ALWAYS_INLINE ObjPtr<mirror::Object> GetReference() REQUIRES_SHARED(Locks::mutator_lock_) { - const uint32_t next = (is_range ? first_src_reg_ + arg_index_ : arg_[arg_index_]); - ++arg_index_; - - return shadow_frame_.GetVRegReference(next); + return shadow_frame_.GetVRegReference(Next()); } private: - const size_t first_src_reg_; - const uint32_t (&arg_)[Instruction::kMaxVarArgRegs]; + uint32_t Next() { + const uint32_t next = operands_->GetOperand(operand_index_); + operand_index_ += 1; + return next; + } + uint32_t NextLong() { + const uint32_t next = operands_->GetOperand(operand_index_); + operand_index_ += 2; + return next; + } + + const InstructionOperands* const operands_; + size_t operand_index_; // the next register operand to read from frame const ShadowFrame& shadow_frame_; - size_t arg_index_; }; // A convenience class that allows values to be written to a given shadow frame, @@ -201,23 +191,19 @@ class ShadowFrameSetter { size_t arg_index_; }; -template <bool is_range> bool MethodHandleInvoke(Thread* self, ShadowFrame& shadow_frame, Handle<mirror::MethodHandle> method_handle, Handle<mirror::MethodType> callsite_type, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, + const InstructionOperands* const args, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_); -template <bool is_range> bool MethodHandleInvokeExact(Thread* self, ShadowFrame& shadow_frame, Handle<mirror::MethodHandle> method_handle, Handle<mirror::MethodType> callsite_type, - const uint32_t (&args)[Instruction::kMaxVarArgRegs], - uint32_t first_arg, + const InstructionOperands* const args, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc index f82bfbfaef..5757992167 100644 --- a/runtime/mirror/emulated_stack_frame.cc +++ b/runtime/mirror/emulated_stack_frame.cc @@ -139,14 +139,12 @@ class EmulatedStackFrameAccessor { DISALLOW_COPY_AND_ASSIGN(EmulatedStackFrameAccessor); }; -template <bool is_range> mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs( Thread* self, Handle<mirror::MethodType> caller_type, Handle<mirror::MethodType> callee_type, const ShadowFrame& caller_frame, - const uint32_t first_src_reg, - const uint32_t (&arg)[Instruction::kMaxVarArgRegs]) { + const InstructionOperands* const operands) { StackHandleScope<6> hs(self); // Step 1: We must throw a WrongMethodTypeException if there's a mismatch in the @@ -185,9 +183,9 @@ mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs( } // Step 4 : Perform argument conversions (if required). - ShadowFrameGetter<is_range> getter(first_src_reg, arg, caller_frame); + ShadowFrameGetter getter(operands, caller_frame); EmulatedStackFrameAccessor setter(references, stack_frame, stack_frame->GetLength()); - if (!PerformConversions<ShadowFrameGetter<is_range>, EmulatedStackFrameAccessor>( + if (!PerformConversions<ShadowFrameGetter, EmulatedStackFrameAccessor>( self, caller_type, callee_type, &getter, &setter, num_method_params)) { return nullptr; } @@ -289,21 +287,5 @@ void EmulatedStackFrame::VisitRoots(RootVisitor* visitor) { static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass)); } -// Explicit CreateFromShadowFrameAndArgs template function declarations. -#define EXPLICIT_CREATE_FROM_SHADOW_FRAME_AND_ARGS_DECL(_is_range) \ - template REQUIRES_SHARED(Locks::mutator_lock_) \ - mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs<_is_range>( \ - Thread* self, \ - Handle<mirror::MethodType> caller_type, \ - Handle<mirror::MethodType> callee_type, \ - const ShadowFrame& caller_frame, \ - const uint32_t first_src_reg, \ - const uint32_t (&arg)[Instruction::kMaxVarArgRegs]) \ - -EXPLICIT_CREATE_FROM_SHADOW_FRAME_AND_ARGS_DECL(true); -EXPLICIT_CREATE_FROM_SHADOW_FRAME_AND_ARGS_DECL(false); -#undef EXPLICIT_CREATE_FROM_SHADOW_FRAME_AND_ARGS_DECL - - } // namespace mirror } // namespace art diff --git a/runtime/mirror/emulated_stack_frame.h b/runtime/mirror/emulated_stack_frame.h index 76859ef1c8..b6aa949ec3 100644 --- a/runtime/mirror/emulated_stack_frame.h +++ b/runtime/mirror/emulated_stack_frame.h @@ -35,14 +35,12 @@ class MANAGED EmulatedStackFrame : public Object { public: // Creates an emulated stack frame whose type is |frame_type| from // a shadow frame. - template <bool is_range> static mirror::EmulatedStackFrame* CreateFromShadowFrameAndArgs( Thread* self, Handle<mirror::MethodType> args_type, Handle<mirror::MethodType> frame_type, const ShadowFrame& caller_frame, - const uint32_t first_src_reg, - const uint32_t (&arg)[Instruction::kMaxVarArgRegs]) REQUIRES_SHARED(Locks::mutator_lock_); + const InstructionOperands* const operands) REQUIRES_SHARED(Locks::mutator_lock_); // Writes the contents of this emulated stack frame to the |callee_frame| // whose type is |callee_type|, starting at |first_dest_reg|. |