diff options
author | 2023-01-06 16:44:38 +0000 | |
---|---|---|
committer | 2023-01-17 09:20:34 +0000 | |
commit | 9e3761d6b98e090cff2e30e0f5e9714f434dd0f2 (patch) | |
tree | 9fba285742b0658a623dd42c14f9241cceb7ba18 | |
parent | 9ab12375de1b61ebfa924a6fbff7428e3b54d1f1 (diff) |
Remove one template argument to the switch interpreter.
Dynamically check for SkipAccessChecks instead.
arm64 apex goes from 49545216 bytes to 49324032, ~200KB savings.
Test: test.py
Change-Id: Iaa64f56485b15c0e3c0eaa31e469a2795035debe
-rw-r--r-- | runtime/Android.bp | 2 | ||||
-rw-r--r-- | runtime/art_method.h | 2 | ||||
-rw-r--r-- | runtime/common_dex_operations.h | 4 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils-inl.h | 8 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.h | 3 | ||||
-rw-r--r-- | runtime/interpreter/interpreter.cc | 34 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_common.cc | 89 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_common.h | 96 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl-inl.h | 123 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl.h | 12 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl0.cc | 2 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl1.cc | 2 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl2.cc | 30 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl3.cc | 30 | ||||
-rw-r--r-- | runtime/interpreter/unstarted_runtime_test.cc | 42 | ||||
-rw-r--r-- | runtime/method_handles.cc | 15 |
16 files changed, 212 insertions, 282 deletions
diff --git a/runtime/Android.bp b/runtime/Android.bp index f162807bf9..bfe04f3aff 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -183,8 +183,6 @@ libart_cc_defaults { "interpreter/interpreter_common.cc", "interpreter/interpreter_switch_impl0.cc", "interpreter/interpreter_switch_impl1.cc", - "interpreter/interpreter_switch_impl2.cc", - "interpreter/interpreter_switch_impl3.cc", "interpreter/lock_count_data.cc", "interpreter/shadow_frame.cc", "interpreter/unstarted_runtime.cc", diff --git a/runtime/art_method.h b/runtime/art_method.h index 7841e3a334..dce4066d0d 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -565,8 +565,8 @@ class ArtMethod final { } void SetMustCountLocks() REQUIRES_SHARED(Locks::mutator_lock_) { - AddAccessFlags(kAccMustCountLocks); ClearAccessFlags(kAccSkipAccessChecks); + AddAccessFlags(kAccMustCountLocks); } // Returns true if the method is using the nterp entrypoint fast path. diff --git a/runtime/common_dex_operations.h b/runtime/common_dex_operations.h index 0b9d3fbb53..ce2090c2a5 100644 --- a/runtime/common_dex_operations.h +++ b/runtime/common_dex_operations.h @@ -175,7 +175,7 @@ static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self, return true; } -template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active> +template<Primitive::Type field_type, bool transaction_active> ALWAYS_INLINE bool DoFieldPutCommon(Thread* self, const ShadowFrame& shadow_frame, ObjPtr<mirror::Object> obj, @@ -236,7 +236,7 @@ ALWAYS_INLINE bool DoFieldPutCommon(Thread* self, break; case Primitive::kPrimNot: { ObjPtr<mirror::Object> reg = value.GetL(); - if (do_assignability_check && reg != nullptr) { + if (reg != nullptr && !shadow_frame.GetMethod()->SkipAccessChecks()) { // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the // object in the destructor. ObjPtr<mirror::Class> field_class; diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index cbe754337c..4a1dfba786 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -289,7 +289,6 @@ inline ObjPtr<mirror::Object> AllocObjectFromCodeInitialized(ObjPtr<mirror::Clas } -template <bool kAccessCheck> ALWAYS_INLINE inline ObjPtr<mirror::Class> CheckArrayAlloc(dex::TypeIndex type_idx, int32_t component_count, @@ -311,7 +310,7 @@ inline ObjPtr<mirror::Class> CheckArrayAlloc(dex::TypeIndex type_idx, } CHECK(klass->IsArrayClass()) << klass->PrettyClass(); } - if (kAccessCheck) { + if (!method->SkipAccessChecks()) { ObjPtr<mirror::Class> referrer = method->GetDeclaringClass(); if (UNLIKELY(!referrer->CanAccess(klass))) { ThrowIllegalAccessErrorClass(referrer, klass); @@ -326,7 +325,7 @@ inline ObjPtr<mirror::Class> CheckArrayAlloc(dex::TypeIndex type_idx, // it cannot be resolved, throw an error. If it can, use it to create an array. // When verification/compiler hasn't been able to verify access, optionally perform an access // check. -template <bool kAccessCheck, bool kInstrumented> +template <bool kInstrumented> ALWAYS_INLINE inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx, int32_t component_count, @@ -334,8 +333,7 @@ inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx, Thread* self, gc::AllocatorType allocator_type) { bool slow_path = false; - ObjPtr<mirror::Class> klass = - CheckArrayAlloc<kAccessCheck>(type_idx, component_count, method, &slow_path); + ObjPtr<mirror::Class> klass = CheckArrayAlloc(type_idx, component_count, method, &slow_path); if (UNLIKELY(slow_path)) { if (klass == nullptr) { return nullptr; diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index a69b055c1f..ae80352f72 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -77,7 +77,6 @@ inline ObjPtr<mirror::Object> AllocObjectFromCodeInitialized(ObjPtr<mirror::Clas REQUIRES(!Roles::uninterruptible_); -template <bool kAccessCheck> ALWAYS_INLINE inline ObjPtr<mirror::Class> CheckArrayAlloc(dex::TypeIndex type_idx, int32_t component_count, ArtMethod* method, @@ -89,7 +88,7 @@ ALWAYS_INLINE inline ObjPtr<mirror::Class> CheckArrayAlloc(dex::TypeIndex type_i // it cannot be resolved, throw an error. If it can, use it to create an array. // When verification/compiler hasn't been able to verify access, optionally perform an access // check. -template <bool kAccessCheck, bool kInstrumented = true> +template <bool kInstrumented = true> ALWAYS_INLINE inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx, int32_t component_count, ArtMethod* method, diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index 42596d860e..0dc8d8bcb1 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -237,21 +237,11 @@ static JValue ExecuteSwitch(Thread* self, JValue result_register, bool interpret_one_instruction) REQUIRES_SHARED(Locks::mutator_lock_) { if (Runtime::Current()->IsActiveTransaction()) { - if (shadow_frame.GetMethod()->SkipAccessChecks()) { - return ExecuteSwitchImpl<false, true>( - self, accessor, shadow_frame, result_register, interpret_one_instruction); - } else { - return ExecuteSwitchImpl<true, true>( - self, accessor, shadow_frame, result_register, interpret_one_instruction); - } + return ExecuteSwitchImpl<true>( + self, accessor, shadow_frame, result_register, interpret_one_instruction); } else { - if (shadow_frame.GetMethod()->SkipAccessChecks()) { - return ExecuteSwitchImpl<false, false>( - self, accessor, shadow_frame, result_register, interpret_one_instruction); - } else { - return ExecuteSwitchImpl<true, false>( - self, accessor, shadow_frame, result_register, interpret_one_instruction); - } + return ExecuteSwitchImpl<false>( + self, accessor, shadow_frame, result_register, interpret_one_instruction); } } @@ -311,8 +301,12 @@ static inline JValue Execute( // any value. DCHECK(Runtime::Current()->AreNonStandardExitsEnabled()); JValue ret = JValue(); - PerformNonStandardReturn<MonitorState::kNoMonitorsLocked>( - self, shadow_frame, ret, instrumentation, accessor.InsSize()); + PerformNonStandardReturn(self, + shadow_frame, + ret, + instrumentation, + accessor.InsSize(), + /* unlock_monitors= */ false); return ret; } if (UNLIKELY(self->IsExceptionPending())) { @@ -322,8 +316,12 @@ static inline JValue Execute( JValue ret = JValue(); if (UNLIKELY(shadow_frame.GetForcePopFrame())) { DCHECK(Runtime::Current()->AreNonStandardExitsEnabled()); - PerformNonStandardReturn<MonitorState::kNoMonitorsLocked>( - self, shadow_frame, ret, instrumentation, accessor.InsSize()); + PerformNonStandardReturn(self, + shadow_frame, + ret, + instrumentation, + accessor.InsSize(), + /* unlock_monitors= */ false); } return ret; } diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 033b4da84a..7b4923b4ec 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -231,7 +231,7 @@ void AbortTransactionV(Thread* self, const char* fmt, va_list args) { // about ALWAYS_INLINE (-Werror, -Wgcc-compat) in definitions. // -template <bool is_range, bool do_assignability_check> +template <bool is_range> static ALWAYS_INLINE bool DoCallCommon(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, @@ -1181,8 +1181,7 @@ inline void CopyRegisters(ShadowFrame& caller_frame, } } -template <bool is_range, - bool do_assignability_check> +template <bool is_range> static inline bool DoCallCommon(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, @@ -1261,7 +1260,7 @@ static inline bool DoCallCommon(ArtMethod* called_method, ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get(); // Initialize new shadow frame by copying the registers from the callee shadow frame. - if (do_assignability_check) { + if (!shadow_frame.GetMethod()->SkipAccessChecks()) { // Slow path. // We might need to do class loading, which incurs a thread state change to kNative. So // register the shadow frame as under construction and allow suspension again. @@ -1304,7 +1303,7 @@ static inline bool DoCallCommon(ArtMethod* called_method, // Handle Object references. 1 virtual register slot. case 'L': { ObjPtr<mirror::Object> o = shadow_frame.GetVRegReference(src_reg); - if (do_assignability_check && o != nullptr) { + if (o != nullptr) { const dex::TypeIndex type_idx = params->GetTypeItem(shorty_pos).type_idx_; ObjPtr<mirror::Class> arg_type = method->GetDexCache()->GetResolvedType(type_idx); if (arg_type == nullptr) { @@ -1378,7 +1377,7 @@ static inline bool DoCallCommon(ArtMethod* called_method, return !self->IsExceptionPending(); } -template<bool is_range, bool do_assignability_check> +template<bool is_range> NO_STACK_PROTECTOR bool DoCall(ArtMethod* called_method, Thread* self, @@ -1402,7 +1401,7 @@ bool DoCall(ArtMethod* called_method, inst->GetVarArgs(arg, inst_data); } - return DoCallCommon<is_range, do_assignability_check>( + return DoCallCommon<is_range>( called_method, self, shadow_frame, @@ -1413,7 +1412,7 @@ bool DoCall(ArtMethod* called_method, is_string_init); } -template <bool is_range, bool do_access_check, bool transaction_active> +template <bool is_range, bool transaction_active> bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame, Thread* self, @@ -1430,6 +1429,7 @@ bool DoFilledNewArray(const Instruction* inst, return false; } uint16_t type_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c(); + bool do_access_check = !shadow_frame.GetMethod()->SkipAccessChecks(); ObjPtr<mirror::Class> array_class = ResolveVerifyAndClinit(dex::TypeIndex(type_idx), shadow_frame.GetMethod(), self, @@ -1534,20 +1534,50 @@ void RecordArrayElementsInTransaction(ObjPtr<mirror::Array> array, int32_t count } } +void UnlockHeldMonitors(Thread* self, ShadowFrame* shadow_frame) + REQUIRES_SHARED(Locks::mutator_lock_) { + DCHECK(shadow_frame->GetForcePopFrame() || Runtime::Current()->IsTransactionAborted()); + // Unlock all monitors. + if (shadow_frame->GetMethod()->MustCountLocks()) { + DCHECK(!shadow_frame->GetMethod()->SkipAccessChecks()); + // Get the monitors from the shadow-frame monitor-count data. + shadow_frame->GetLockCountData().VisitMonitors( + [&](mirror::Object** obj) REQUIRES_SHARED(Locks::mutator_lock_) { + // Since we don't use the 'obj' pointer after the DoMonitorExit everything should be fine + // WRT suspension. + DoMonitorExit(self, shadow_frame, *obj); + }); + } else { + std::vector<verifier::MethodVerifier::DexLockInfo> locks; + verifier::MethodVerifier::FindLocksAtDexPc(shadow_frame->GetMethod(), + shadow_frame->GetDexPC(), + &locks, + Runtime::Current()->GetTargetSdkVersion()); + for (const auto& reg : locks) { + if (UNLIKELY(reg.dex_registers.empty())) { + LOG(ERROR) << "Unable to determine reference locked by " + << shadow_frame->GetMethod()->PrettyMethod() << " at pc " + << shadow_frame->GetDexPC(); + } else { + DoMonitorExit( + self, shadow_frame, shadow_frame->GetVRegReference(*reg.dex_registers.begin())); + } + } + } +} + // Explicit DoCall template function declarations. -#define EXPLICIT_DO_CALL_TEMPLATE_DECL(_is_range, _do_assignability_check) \ - template REQUIRES_SHARED(Locks::mutator_lock_) \ - bool DoCall<_is_range, _do_assignability_check>(ArtMethod* method, \ - Thread* self, \ - ShadowFrame& shadow_frame, \ - const Instruction* inst, \ - uint16_t inst_data, \ - bool string_init, \ - JValue* result) -EXPLICIT_DO_CALL_TEMPLATE_DECL(false, false); -EXPLICIT_DO_CALL_TEMPLATE_DECL(false, true); -EXPLICIT_DO_CALL_TEMPLATE_DECL(true, false); -EXPLICIT_DO_CALL_TEMPLATE_DECL(true, true); +#define EXPLICIT_DO_CALL_TEMPLATE_DECL(_is_range) \ + template REQUIRES_SHARED(Locks::mutator_lock_) \ + bool DoCall<_is_range>(ArtMethod* method, \ + Thread* self, \ + ShadowFrame& shadow_frame, \ + const Instruction* inst, \ + uint16_t inst_data, \ + bool string_init, \ + JValue* result) +EXPLICIT_DO_CALL_TEMPLATE_DECL(false); +EXPLICIT_DO_CALL_TEMPLATE_DECL(true); #undef EXPLICIT_DO_CALL_TEMPLATE_DECL // Explicit DoInvokePolymorphic template function declarations. @@ -1561,16 +1591,15 @@ EXPLICIT_DO_INVOKE_POLYMORPHIC_TEMPLATE_DECL(true); #undef EXPLICIT_DO_INVOKE_POLYMORPHIC_TEMPLATE_DECL // Explicit DoFilledNewArray template function declarations. -#define EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(_is_range_, _check, _transaction_active) \ +#define EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(_is_range_, _transaction_active) \ template REQUIRES_SHARED(Locks::mutator_lock_) \ - bool DoFilledNewArray<_is_range_, _check, _transaction_active>(const Instruction* inst, \ - const ShadowFrame& shadow_frame, \ - Thread* self, JValue* result) -#define EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(_transaction_active) \ - EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, false, _transaction_active); \ - EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, true, _transaction_active); \ - EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, false, _transaction_active); \ - EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, true, _transaction_active) + bool DoFilledNewArray<_is_range_, _transaction_active>(const Instruction* inst, \ + const ShadowFrame& shadow_frame, \ + Thread* self, \ + JValue* result) +#define EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(_transaction_active) \ + EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, _transaction_active); \ + EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, _transaction_active) EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(false); EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(true); #undef EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index 35e329c7e9..b8d6817904 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -70,7 +70,6 @@ namespace interpreter { void ThrowNullPointerExceptionFromInterpreter() REQUIRES_SHARED(Locks::mutator_lock_); -template <bool kMonitorCounting> static inline void DoMonitorEnter(Thread* self, ShadowFrame* frame, ObjPtr<mirror::Object> ref) NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_) { @@ -84,28 +83,29 @@ static inline void DoMonitorEnter(Thread* self, ShadowFrame* frame, ObjPtr<mirro DCHECK(unlocked); return; } - if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) { + if (frame->GetMethod()->MustCountLocks()) { + DCHECK(!frame->GetMethod()->SkipAccessChecks()); frame->GetLockCountData().AddMonitor(self, h_ref.Get()); } } -template <bool kMonitorCounting> static inline void DoMonitorExit(Thread* self, ShadowFrame* frame, ObjPtr<mirror::Object> ref) NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_) { StackHandleScope<1> hs(self); Handle<mirror::Object> h_ref(hs.NewHandle(ref)); h_ref->MonitorExit(self); - if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) { + if (frame->GetMethod()->MustCountLocks()) { + DCHECK(!frame->GetMethod()->SkipAccessChecks()); frame->GetLockCountData().RemoveMonitorOrThrow(self, h_ref.Get()); } } -template <bool kMonitorCounting> static inline bool DoMonitorCheckOnExit(Thread* self, ShadowFrame* frame) NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_) { - if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) { + if (frame->GetMethod()->MustCountLocks()) { + DCHECK(!frame->GetMethod()->SkipAccessChecks()); return frame->GetLockCountData().CheckAllMonitorsReleasedOrThrow(self); } return true; @@ -124,7 +124,7 @@ void RecordArrayElementsInTransaction(ObjPtr<mirror::Array> array, int32_t count // Invokes the given method. This is part of the invocation support and is used by DoInvoke, // DoFastInvoke and DoInvokeVirtualQuick functions. // Returns true on success, otherwise throws an exception and returns false. -template<bool is_range, bool do_assignability_check> +template<bool is_range> bool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, @@ -157,54 +157,16 @@ NeedsMethodExitEvent(const instrumentation::Instrumentation* ins) return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners(); } -// NO_INLINE so we won't bloat the interpreter with this very cold lock-release code. -template <bool kMonitorCounting> -static NO_INLINE void UnlockHeldMonitors(Thread* self, ShadowFrame* shadow_frame) - REQUIRES_SHARED(Locks::mutator_lock_) { - DCHECK(shadow_frame->GetForcePopFrame() || - Runtime::Current()->IsTransactionAborted()); - // Unlock all monitors. - if (kMonitorCounting && shadow_frame->GetMethod()->MustCountLocks()) { - // Get the monitors from the shadow-frame monitor-count data. - shadow_frame->GetLockCountData().VisitMonitors( - [&](mirror::Object** obj) REQUIRES_SHARED(Locks::mutator_lock_) { - // Since we don't use the 'obj' pointer after the DoMonitorExit everything should be fine - // WRT suspension. - DoMonitorExit<kMonitorCounting>(self, shadow_frame, *obj); - }); - } else { - std::vector<verifier::MethodVerifier::DexLockInfo> locks; - verifier::MethodVerifier::FindLocksAtDexPc(shadow_frame->GetMethod(), - shadow_frame->GetDexPC(), - &locks, - Runtime::Current()->GetTargetSdkVersion()); - for (const auto& reg : locks) { - if (UNLIKELY(reg.dex_registers.empty())) { - LOG(ERROR) << "Unable to determine reference locked by " - << shadow_frame->GetMethod()->PrettyMethod() << " at pc " - << shadow_frame->GetDexPC(); - } else { - DoMonitorExit<kMonitorCounting>( - self, shadow_frame, shadow_frame->GetVRegReference(*reg.dex_registers.begin())); - } - } - } -} - -enum class MonitorState { - kNoMonitorsLocked, - kCountingMonitors, - kNormalMonitors, -}; +COLD_ATTR void UnlockHeldMonitors(Thread* self, ShadowFrame* shadow_frame) + REQUIRES_SHARED(Locks::mutator_lock_); -template<MonitorState kMonitorState> static inline ALWAYS_INLINE void PerformNonStandardReturn( Thread* self, ShadowFrame& frame, JValue& result, const instrumentation::Instrumentation* instrumentation, - uint16_t num_dex_inst) REQUIRES_SHARED(Locks::mutator_lock_) { - static constexpr bool kMonitorCounting = (kMonitorState == MonitorState::kCountingMonitors); + uint16_t num_dex_inst, + bool unlock_monitors = true) REQUIRES_SHARED(Locks::mutator_lock_) { ObjPtr<mirror::Object> thiz(frame.GetThisObject(num_dex_inst)); StackHandleScope<1u> hs(self); if (UNLIKELY(self->IsExceptionPending())) { @@ -212,10 +174,10 @@ static inline ALWAYS_INLINE void PerformNonStandardReturn( << self->GetException()->Dump(); self->ClearException(); } - if (kMonitorState != MonitorState::kNoMonitorsLocked) { - UnlockHeldMonitors<kMonitorCounting>(self, &frame); + if (unlock_monitors) { + UnlockHeldMonitors(self, &frame); + DoMonitorCheckOnExit(self, &frame); } - DoMonitorCheckOnExit<kMonitorCounting>(self, &frame); result = JValue(); if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) { SendMethodExitEvents(self, instrumentation, frame, frame.GetMethod(), result); @@ -224,7 +186,7 @@ static inline ALWAYS_INLINE void PerformNonStandardReturn( // Handles all invoke-XXX/range instructions except for invoke-polymorphic[/range]. // Returns true on success, otherwise throws an exception and returns false. -template<InvokeType type, bool is_range, bool do_access_check> +template<InvokeType type, bool is_range> static ALWAYS_INLINE bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, @@ -247,7 +209,7 @@ static ALWAYS_INLINE bool DoInvoke(Thread* self, return false; } - return DoCall<is_range, do_access_check>( + return DoCall<is_range>( called_method, self, shadow_frame, inst, inst_data, string_init, result); } @@ -393,7 +355,6 @@ static inline void GetFieldInfo(Thread* self, // Returns true on success, otherwise throws an exception and returns false. template<FindFieldType find_type, Primitive::Type field_type, - bool do_access_check, bool transaction_active = false> ALWAYS_INLINE bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, @@ -517,15 +478,13 @@ static inline bool CheckWriteValueConstraint(Thread* self, ObjPtr<mirror::Object // Handles iput-XXX and sput-XXX instructions. // Returns true on success, otherwise throws an exception and returns false. -template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check, - bool transaction_active> +template<FindFieldType find_type, Primitive::Type field_type, bool transaction_active> ALWAYS_INLINE bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) REQUIRES_SHARED(Locks::mutator_lock_) { bool should_report = Runtime::Current()->GetInstrumentation()->HasFieldWriteListeners(); - const bool do_assignability_check = do_access_check; bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite); uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data); bool resolve_field_type = (shadow_frame.GetVRegReference(vregA) != nullptr); @@ -578,11 +537,11 @@ ALWAYS_INLINE bool DoFieldPut(Thread* self, return false; } if (should_report) { - return DoFieldPutCommon<field_type, do_assignability_check, transaction_active>(self, - shadow_frame, - obj, - field, - value); + return DoFieldPutCommon<field_type, transaction_active>(self, + shadow_frame, + obj, + field, + value); } #define FIELD_SET(prim, type, jtype) \ case Primitive::kPrim ## prim: \ @@ -717,13 +676,16 @@ static inline bool DoLongRemainder(ShadowFrame& shadow_frame, // Handles filled-new-array and filled-new-array-range instructions. // Returns true on success, otherwise throws an exception and returns false. -template <bool is_range, bool do_access_check, bool transaction_active> -bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame, - Thread* self, JValue* result); +template <bool is_range, bool transaction_active> +bool DoFilledNewArray(const Instruction* inst, + const ShadowFrame& shadow_frame, + Thread* self, + JValue* result); // Handles packed-switch instruction. // Returns the branch offset to the next instruction to execute. -static inline int32_t DoPackedSwitch(const Instruction* inst, const ShadowFrame& shadow_frame, +static inline int32_t DoPackedSwitch(const Instruction* inst, + const ShadowFrame& shadow_frame, uint16_t inst_data) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(inst->Opcode() == Instruction::PACKED_SWITCH); diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h index 215194ed21..ddde26d0cf 100644 --- a/runtime/interpreter/interpreter_switch_impl-inl.h +++ b/runtime/interpreter/interpreter_switch_impl-inl.h @@ -50,7 +50,7 @@ namespace interpreter { // The function names must match the names from dex_instruction_list.h and have no arguments. // Return value: The handlers must return false if the instruction throws or returns (exits). // -template<bool do_access_check, bool transaction_active, Instruction::Format kFormat> +template<bool transaction_active, Instruction::Format kFormat> class InstructionHandler { public: #define HANDLER_ATTRIBUTES ALWAYS_INLINE FLATTEN WARN_UNUSED REQUIRES_SHARED(Locks::mutator_lock_) @@ -64,7 +64,7 @@ class InstructionHandler { DCHECK(abort_exception != nullptr); DCHECK(abort_exception->GetClass()->DescriptorEquals(Transaction::kAbortExceptionDescriptor)); Self()->ClearException(); - PerformNonStandardReturn<kMonitorState>( + PerformNonStandardReturn( Self(), shadow_frame_, ctx_->result, Instrumentation(), Accessor().InsSize()); Self()->SetException(abort_exception.Get()); ExitInterpreterLoop(); @@ -76,7 +76,7 @@ class InstructionHandler { HANDLER_ATTRIBUTES bool CheckForceReturn() { if (shadow_frame_.GetForcePopFrame()) { DCHECK(Runtime::Current()->AreNonStandardExitsEnabled()); - PerformNonStandardReturn<kMonitorState>( + PerformNonStandardReturn( Self(), shadow_frame_, ctx_->result, Instrumentation(), Accessor().InsSize()); ExitInterpreterLoop(); return false; @@ -100,7 +100,7 @@ class InstructionHandler { /* skip_listeners= */ skip_event, /* skip_throw_listener= */ skip_event)) { // Structured locking is to be enforced for abnormal termination, too. - DoMonitorCheckOnExit<do_assignability_check>(Self(), &shadow_frame_); + DoMonitorCheckOnExit(Self(), &shadow_frame_); ctx_->result = JValue(); /* Handled in caller. */ ExitInterpreterLoop(); return false; // Return to caller. @@ -204,7 +204,7 @@ class InstructionHandler { HANDLER_ATTRIBUTES bool HandleReturn(JValue result) { Self()->AllowThreadSuspension(); - if (!DoMonitorCheckOnExit<do_assignability_check>(Self(), &shadow_frame_)) { + if (!DoMonitorCheckOnExit(Self(), &shadow_frame_)) { return false; } if (UNLIKELY(NeedsMethodExitEvent(Instrumentation()) && @@ -341,19 +341,19 @@ class InstructionHandler { template<FindFieldType find_type, Primitive::Type field_type> HANDLER_ATTRIBUTES bool HandleGet() { - return DoFieldGet<find_type, field_type, do_access_check, transaction_active>( + return DoFieldGet<find_type, field_type, transaction_active>( Self(), shadow_frame_, inst_, inst_data_); } template<FindFieldType find_type, Primitive::Type field_type> HANDLER_ATTRIBUTES bool HandlePut() { - return DoFieldPut<find_type, field_type, do_access_check, transaction_active>( + return DoFieldPut<find_type, field_type, transaction_active>( Self(), shadow_frame_, inst_, inst_data_); } template<InvokeType type, bool is_range> HANDLER_ATTRIBUTES bool HandleInvoke() { - bool success = DoInvoke<type, is_range, do_access_check>( + bool success = DoInvoke<type, is_range>( Self(), shadow_frame_, inst_, inst_data_, ResultRegister()); return PossiblyHandlePendingExceptionOnInvoke(!success); } @@ -457,12 +457,12 @@ class InstructionHandler { HANDLER_ATTRIBUTES bool RETURN_OBJECT() { JValue result; Self()->AllowThreadSuspension(); - if (!DoMonitorCheckOnExit<do_assignability_check>(Self(), &shadow_frame_)) { + if (!DoMonitorCheckOnExit(Self(), &shadow_frame_)) { return false; } const size_t ref_idx = A(); ObjPtr<mirror::Object> obj_result = GetVRegReference(ref_idx); - if (do_assignability_check && obj_result != nullptr) { + if (obj_result != nullptr && UNLIKELY(DoAssignabilityChecks())) { ObjPtr<mirror::Class> return_type = shadow_frame_.GetMethod()->ResolveReturnType(); // Re-load since it might have moved. obj_result = GetVRegReference(ref_idx); @@ -481,22 +481,23 @@ class InstructionHandler { return false; // Pending exception. } } - StackHandleScope<1> hs(Self()); - MutableHandle<mirror::Object> h_result(hs.NewHandle(obj_result)); result.SetL(obj_result); - if (UNLIKELY(NeedsMethodExitEvent(Instrumentation()) && - !SendMethodExitEvents(Self(), - Instrumentation(), - shadow_frame_, - shadow_frame_.GetMethod(), - h_result))) { - DCHECK(Self()->IsExceptionPending()); - // Do not raise exception event if it is caused by other instrumentation event. - shadow_frame_.SetSkipNextExceptionEvent(true); - return false; // Pending exception. + if (UNLIKELY(NeedsMethodExitEvent(Instrumentation()))) { + StackHandleScope<1> hs(Self()); + MutableHandle<mirror::Object> h_result(hs.NewHandle(obj_result)); + if (!SendMethodExitEvents(Self(), + Instrumentation(), + shadow_frame_, + shadow_frame_.GetMethod(), + h_result)) { + DCHECK(Self()->IsExceptionPending()); + // Do not raise exception event if it is caused by other instrumentation event. + shadow_frame_.SetSkipNextExceptionEvent(true); + return false; // Pending exception. + } + // Re-load since it might have moved or been replaced during the MethodExitEvent. + result.SetL(h_result.Get()); } - // Re-load since it might have moved or been replaced during the MethodExitEvent. - result.SetL(h_result.Get()); ctx_->result = result; ExitInterpreterLoop(); return false; @@ -551,11 +552,12 @@ class InstructionHandler { } HANDLER_ATTRIBUTES bool CONST_CLASS() { - ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()), - shadow_frame_.GetMethod(), - Self(), - false, - do_access_check); + ObjPtr<mirror::Class> c = + ResolveVerifyAndClinit(dex::TypeIndex(B()), + shadow_frame_.GetMethod(), + Self(), + false, + !shadow_frame_.GetMethod()->SkipAccessChecks()); if (UNLIKELY(c == nullptr)) { return false; // Pending exception. } @@ -596,7 +598,7 @@ class InstructionHandler { ThrowNullPointerExceptionFromInterpreter(); return false; // Pending exception. } - DoMonitorEnter<do_assignability_check>(Self(), &shadow_frame_, obj); + DoMonitorEnter(Self(), &shadow_frame_, obj); return !Self()->IsExceptionPending(); } @@ -609,16 +611,17 @@ class InstructionHandler { ThrowNullPointerExceptionFromInterpreter(); return false; // Pending exception. } - DoMonitorExit<do_assignability_check>(Self(), &shadow_frame_, obj); + DoMonitorExit(Self(), &shadow_frame_, obj); return !Self()->IsExceptionPending(); } HANDLER_ATTRIBUTES bool CHECK_CAST() { - ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()), - shadow_frame_.GetMethod(), - Self(), - false, - do_access_check); + ObjPtr<mirror::Class> c = + ResolveVerifyAndClinit(dex::TypeIndex(B()), + shadow_frame_.GetMethod(), + Self(), + false, + !shadow_frame_.GetMethod()->SkipAccessChecks()); if (UNLIKELY(c == nullptr)) { return false; // Pending exception. } @@ -631,11 +634,12 @@ class InstructionHandler { } HANDLER_ATTRIBUTES bool INSTANCE_OF() { - ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(C()), - shadow_frame_.GetMethod(), - Self(), - false, - do_access_check); + ObjPtr<mirror::Class> c = + ResolveVerifyAndClinit(dex::TypeIndex(C()), + shadow_frame_.GetMethod(), + Self(), + false, + !shadow_frame_.GetMethod()->SkipAccessChecks()); if (UNLIKELY(c == nullptr)) { return false; // Pending exception. } @@ -656,11 +660,12 @@ class InstructionHandler { HANDLER_ATTRIBUTES bool NEW_INSTANCE() { ObjPtr<mirror::Object> obj = nullptr; - ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()), - shadow_frame_.GetMethod(), - Self(), - false, - do_access_check); + ObjPtr<mirror::Class> c = + ResolveVerifyAndClinit(dex::TypeIndex(B()), + shadow_frame_.GetMethod(), + Self(), + false, + !shadow_frame_.GetMethod()->SkipAccessChecks()); if (LIKELY(c != nullptr)) { // Don't allow finalizable objects to be allocated during a transaction since these can't // be finalized without a started runtime. @@ -687,7 +692,7 @@ class InstructionHandler { HANDLER_ATTRIBUTES bool NEW_ARRAY() { int32_t length = GetVReg(B()); - ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>( + ObjPtr<mirror::Object> obj = AllocArrayFromCode( dex::TypeIndex(C()), length, shadow_frame_.GetMethod(), @@ -701,12 +706,12 @@ class InstructionHandler { } HANDLER_ATTRIBUTES bool FILLED_NEW_ARRAY() { - return DoFilledNewArray<false, do_access_check, transaction_active>( + return DoFilledNewArray<false, transaction_active>( inst_, shadow_frame_, Self(), ResultRegister()); } HANDLER_ATTRIBUTES bool FILLED_NEW_ARRAY_RANGE() { - return DoFilledNewArray<true, do_access_check, transaction_active>( + return DoFilledNewArray<true, transaction_active>( inst_, shadow_frame_, Self(), ResultRegister()); } @@ -731,7 +736,7 @@ class InstructionHandler { ObjPtr<mirror::Object> exception = GetVRegReference(A()); if (UNLIKELY(exception == nullptr)) { ThrowNullPointerException(); - } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) { + } else if (DoAssignabilityChecks() && !exception->GetClass()->IsThrowableClass()) { // This should never happen. std::string temp; Self()->ThrowNewExceptionF("Ljava/lang/InternalError;", @@ -1741,9 +1746,9 @@ class InstructionHandler { } private: - static constexpr bool do_assignability_check = do_access_check; - static constexpr MonitorState kMonitorState = - do_assignability_check ? MonitorState::kCountingMonitors : MonitorState::kNormalMonitors; + bool DoAssignabilityChecks() const REQUIRES_SHARED(Locks::mutator_lock_) { + return !shadow_frame_.GetMethod()->SkipAccessChecks(); + } ALWAYS_INLINE const CodeItemDataAccessor& Accessor() { return ctx_->accessor; } ALWAYS_INLINE const uint16_t* Insns() { return ctx_->accessor.Insns(); } @@ -1815,7 +1820,7 @@ class InstructionHandler { #endif #define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v) \ -template<bool do_access_check, bool transaction_active> \ +template<bool transaction_active> \ ASAN_NO_INLINE NO_STACK_PROTECTOR static bool OP_##OPCODE_NAME( \ SwitchImplContext* ctx, \ const instrumentation::Instrumentation* instrumentation, \ @@ -1826,14 +1831,14 @@ ASAN_NO_INLINE NO_STACK_PROTECTOR static bool OP_##OPCODE_NAME( uint16_t inst_data, \ const Instruction*& next, \ bool& exit) REQUIRES_SHARED(Locks::mutator_lock_) { \ - InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \ + InstructionHandler<transaction_active, Instruction::FORMAT> handler( \ ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit); \ return LIKELY(handler.OPCODE_NAME()); \ } DEX_INSTRUCTION_LIST(OPCODE_CASE) #undef OPCODE_CASE -template<bool do_access_check, bool transaction_active> +template<bool transaction_active> NO_STACK_PROTECTOR void ExecuteSwitchImplCpp(SwitchImplContext* ctx) { Thread* self = ctx->self; @@ -1858,7 +1863,7 @@ void ExecuteSwitchImplCpp(SwitchImplContext* ctx) { uint16_t inst_data = inst->Fetch16(0); bool exit = false; bool success; // Moved outside to keep frames small under asan. - if (InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat>( + if (InstructionHandler<transaction_active, Instruction::kInvalidFormat>( ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit). Preamble()) { DCHECK_EQ(self->IsExceptionPending(), inst->Opcode(inst_data) == Instruction::MOVE_EXCEPTION); @@ -1866,7 +1871,7 @@ void ExecuteSwitchImplCpp(SwitchImplContext* ctx) { #define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v) \ case OPCODE: { \ next = inst->RelativeAt(Instruction::SizeInCodeUnits(Instruction::FORMAT)); \ - success = OP_##OPCODE_NAME<do_access_check, transaction_active>( \ + success = OP_##OPCODE_NAME<transaction_active>( \ ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit); \ if (success && LIKELY(!interpret_one_instruction)) { \ continue; \ @@ -1882,7 +1887,7 @@ void ExecuteSwitchImplCpp(SwitchImplContext* ctx) { return; // Return statement or debugger forced exit. } if (self->IsExceptionPending()) { - if (!InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat>( + if (!InstructionHandler<transaction_active, Instruction::kInvalidFormat>( ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit). HandlePendingException()) { shadow_frame.SetDexPC(dex::kDexNoIndex); diff --git a/runtime/interpreter/interpreter_switch_impl.h b/runtime/interpreter/interpreter_switch_impl.h index d4dca11c60..3a42c217a9 100644 --- a/runtime/interpreter/interpreter_switch_impl.h +++ b/runtime/interpreter/interpreter_switch_impl.h @@ -45,7 +45,7 @@ struct SwitchImplContext { }; // The actual internal implementation of the switch interpreter. -template<bool do_access_check, bool transaction_active> +template<bool transaction_active> void ExecuteSwitchImplCpp(SwitchImplContext* ctx) REQUIRES_SHARED(Locks::mutator_lock_); @@ -55,9 +55,11 @@ extern "C" void ExecuteSwitchImplAsm(SwitchImplContext* ctx, void* impl, const u REQUIRES_SHARED(Locks::mutator_lock_); // Wrapper around the switch interpreter which ensures we can unwind through it. -template<bool do_access_check, bool transaction_active> -ALWAYS_INLINE JValue ExecuteSwitchImpl(Thread* self, const CodeItemDataAccessor& accessor, - ShadowFrame& shadow_frame, JValue result_register, +template<bool transaction_active> +ALWAYS_INLINE JValue ExecuteSwitchImpl(Thread* self, + const CodeItemDataAccessor& accessor, + ShadowFrame& shadow_frame, + JValue result_register, bool interpret_one_instruction) REQUIRES_SHARED(Locks::mutator_lock_) { SwitchImplContext ctx { @@ -68,7 +70,7 @@ ALWAYS_INLINE JValue ExecuteSwitchImpl(Thread* self, const CodeItemDataAccessor& .interpret_one_instruction = interpret_one_instruction, .result = JValue(), }; - void* impl = reinterpret_cast<void*>(&ExecuteSwitchImplCpp<do_access_check, transaction_active>); + void* impl = reinterpret_cast<void*>(&ExecuteSwitchImplCpp<transaction_active>); const uint16_t* dex_pc = ctx.accessor.Insns(); ExecuteSwitchImplAsm(&ctx, impl, dex_pc); return ctx.result; diff --git a/runtime/interpreter/interpreter_switch_impl0.cc b/runtime/interpreter/interpreter_switch_impl0.cc index 00159ecd3f..b4e5f5061d 100644 --- a/runtime/interpreter/interpreter_switch_impl0.cc +++ b/runtime/interpreter/interpreter_switch_impl0.cc @@ -24,7 +24,7 @@ namespace interpreter { // Explicit definition of ExecuteSwitchImplCpp. template HOT_ATTR -void ExecuteSwitchImplCpp<false, false>(SwitchImplContext* ctx); +void ExecuteSwitchImplCpp<false>(SwitchImplContext* ctx); } // namespace interpreter } // namespace art diff --git a/runtime/interpreter/interpreter_switch_impl1.cc b/runtime/interpreter/interpreter_switch_impl1.cc index 3a86765c68..f8f9fcc81a 100644 --- a/runtime/interpreter/interpreter_switch_impl1.cc +++ b/runtime/interpreter/interpreter_switch_impl1.cc @@ -24,7 +24,7 @@ namespace interpreter { // Explicit definition of ExecuteSwitchImplCpp. template -void ExecuteSwitchImplCpp<false, true>(SwitchImplContext* ctx); +void ExecuteSwitchImplCpp<true>(SwitchImplContext* ctx); } // namespace interpreter } // namespace art diff --git a/runtime/interpreter/interpreter_switch_impl2.cc b/runtime/interpreter/interpreter_switch_impl2.cc deleted file mode 100644 index c2739c13ae..0000000000 --- a/runtime/interpreter/interpreter_switch_impl2.cc +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// The interpreter function takes considerable time to compile and link. -// We compile the explicit definitions separately to speed up the build. - -#include "interpreter_switch_impl-inl.h" - -namespace art { -namespace interpreter { - -// Explicit definition of ExecuteSwitchImplCpp. -template HOT_ATTR -void ExecuteSwitchImplCpp<true, false>(SwitchImplContext* ctx); - -} // namespace interpreter -} // namespace art diff --git a/runtime/interpreter/interpreter_switch_impl3.cc b/runtime/interpreter/interpreter_switch_impl3.cc deleted file mode 100644 index 808e4bc9c5..0000000000 --- a/runtime/interpreter/interpreter_switch_impl3.cc +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// The interpreter function takes considerable time to compile and link. -// We compile the explicit definitions separately to speed up the build. - -#include "interpreter_switch_impl-inl.h" - -namespace art { -namespace interpreter { - -// Explicit definition of ExecuteSwitchImplCpp. -template -void ExecuteSwitchImplCpp<true, true>(SwitchImplContext* ctx); - -} // namespace interpreter -} // namespace art diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc index dfda20a818..3227ef7d76 100644 --- a/runtime/interpreter/unstarted_runtime_test.cc +++ b/runtime/interpreter/unstarted_runtime_test.cc @@ -415,13 +415,13 @@ TEST_F(UnstartedRuntimeTest, StringInit) { shadow_frame->SetVRegReference(1, string_arg.Get()); ArtMethod* factory = WellKnownClasses::StringInitToStringFactory(method); - interpreter::DoCall<false, false>(factory, - self, - *shadow_frame, - Instruction::At(inst_data), - inst_data[0], - /* string_init= */ true, - &result); + interpreter::DoCall<false>(factory, + self, + *shadow_frame, + Instruction::At(inst_data), + inst_data[0], + /* string_init= */ true, + &result); ObjPtr<mirror::String> string_result = down_cast<mirror::String*>(result.GetL()); EXPECT_EQ(string_arg->GetLength(), string_result->GetLength()); @@ -1015,13 +1015,13 @@ TEST_F(UnstartedRuntimeTest, FloatConversion) { UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, method, 0); shadow_frame->SetVRegDouble(0, 1.23); - interpreter::DoCall<false, false>(method, - self, - *shadow_frame, - Instruction::At(inst_data), - inst_data[0], - /* string_init= */ false, - &result); + interpreter::DoCall<false>(method, + self, + *shadow_frame, + Instruction::At(inst_data), + inst_data[0], + /* string_init= */ false, + &result); ObjPtr<mirror::String> string_result = down_cast<mirror::String*>(result.GetL()); ASSERT_TRUE(string_result != nullptr); @@ -1173,13 +1173,13 @@ class UnstartedClassForNameTest : public UnstartedRuntimeTest { // create instruction data for invoke-direct {v0} of method with fake index uint16_t inst_data[3] = { 0x1070, 0x0000, 0x0010 }; - interpreter::DoCall<false, false>(boot_cp_init, - self, - *shadow_frame, - Instruction::At(inst_data), - inst_data[0], - /* string_init= */ false, - &result); + interpreter::DoCall<false>(boot_cp_init, + self, + *shadow_frame, + Instruction::At(inst_data), + inst_data[0], + /* string_init= */ false, + &result); CHECK(!self->IsExceptionPending()); } diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc index 059a33f079..c8c6ef9a73 100644 --- a/runtime/method_handles.cc +++ b/runtime/method_handles.cc @@ -551,31 +551,30 @@ inline bool MethodHandleFieldPut(Thread* self, JValue& value) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(!Runtime::Current()->IsActiveTransaction()); static const bool kTransaction = false; // Not in a transaction. - static const bool kAssignabilityCheck = false; // No access check. switch (field_type) { case Primitive::kPrimBoolean: return - DoFieldPutCommon<Primitive::kPrimBoolean, kAssignabilityCheck, kTransaction>( + DoFieldPutCommon<Primitive::kPrimBoolean, kTransaction>( self, shadow_frame, obj, field, value); case Primitive::kPrimByte: - return DoFieldPutCommon<Primitive::kPrimByte, kAssignabilityCheck, kTransaction>( + return DoFieldPutCommon<Primitive::kPrimByte, kTransaction>( self, shadow_frame, obj, field, value); case Primitive::kPrimChar: - return DoFieldPutCommon<Primitive::kPrimChar, kAssignabilityCheck, kTransaction>( + return DoFieldPutCommon<Primitive::kPrimChar, kTransaction>( self, shadow_frame, obj, field, value); case Primitive::kPrimShort: - return DoFieldPutCommon<Primitive::kPrimShort, kAssignabilityCheck, kTransaction>( + return DoFieldPutCommon<Primitive::kPrimShort, kTransaction>( self, shadow_frame, obj, field, value); case Primitive::kPrimInt: case Primitive::kPrimFloat: - return DoFieldPutCommon<Primitive::kPrimInt, kAssignabilityCheck, kTransaction>( + return DoFieldPutCommon<Primitive::kPrimInt, kTransaction>( self, shadow_frame, obj, field, value); case Primitive::kPrimLong: case Primitive::kPrimDouble: - return DoFieldPutCommon<Primitive::kPrimLong, kAssignabilityCheck, kTransaction>( + return DoFieldPutCommon<Primitive::kPrimLong, kTransaction>( self, shadow_frame, obj, field, value); case Primitive::kPrimNot: - return DoFieldPutCommon<Primitive::kPrimNot, kAssignabilityCheck, kTransaction>( + return DoFieldPutCommon<Primitive::kPrimNot, kTransaction>( self, shadow_frame, obj, field, value); case Primitive::kPrimVoid: LOG(FATAL) << "Unreachable: " << field_type; |