diff options
Diffstat (limited to 'runtime/stack.h')
-rw-r--r-- | runtime/stack.h | 99 |
1 files changed, 58 insertions, 41 deletions
diff --git a/runtime/stack.h b/runtime/stack.h index 0692390..8466069 100644 --- a/runtime/stack.h +++ b/runtime/stack.h @@ -19,8 +19,10 @@ #include "dex_file.h" #include "instrumentation.h" +#include "base/casts.h" #include "base/macros.h" #include "arch/context.h" +#include "mirror/object_reference.h" #include <stdint.h> #include <string> @@ -96,16 +98,33 @@ enum VRegBaseRegNum : int { kVRegNonSpecialTempBaseReg = -3, }; +// A reference from the shadow stack to a MirrorType object within the Java heap. +template<class MirrorType> +class MANAGED StackReference : public mirror::ObjectReference<false, MirrorType> { + public: + StackReference<MirrorType>() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + : mirror::ObjectReference<false, MirrorType>(nullptr) {} + + static StackReference<MirrorType> FromMirrorPtr(MirrorType* p) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return StackReference<MirrorType>(p); + } + + private: + StackReference<MirrorType>(MirrorType* p) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + : mirror::ObjectReference<false, MirrorType>(p) {} +}; + // ShadowFrame has 3 possible layouts: // - portable - a unified array of VRegs and references. Precise references need GC maps. // - interpreter - separate VRegs and reference arrays. References are in the reference array. // - JNI - just VRegs, but where every VReg holds a reference. class ShadowFrame { public: - // Compute size of ShadowFrame in bytes. + // Compute size of ShadowFrame in bytes assuming it has a reference array. static size_t ComputeSize(uint32_t num_vregs) { return sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) + - (sizeof(mirror::Object*) * num_vregs); + (sizeof(StackReference<mirror::Object>) * num_vregs); } // Create ShadowFrame in heap for deoptimization. @@ -195,22 +214,19 @@ class ShadowFrame { } template <bool kChecked = false> - mirror::Object* GetVRegReference(size_t i) const { + mirror::Object* GetVRegReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK_LT(i, NumberOfVRegs()); if (HasReferenceArray()) { - mirror::Object* ref = References()[i]; + mirror::Object* ref = References()[i].AsMirrorPtr(); if (kChecked) { CHECK(VerifyReference(ref)) << "VReg " << i << "(" << ref << ") is in protected space, reference array " << true; } - // If the vreg reference is not equal to the vreg then the vreg reference is stale. - if (UNLIKELY(reinterpret_cast<uint32_t>(ref) != vregs_[i])) { - return nullptr; - } return ref; } else { - const uint32_t* vreg = &vregs_[i]; - mirror::Object* ref = *reinterpret_cast<mirror::Object* const*>(vreg); + const uint32_t* vreg_ptr = &vregs_[i]; + mirror::Object* ref = + reinterpret_cast<const StackReference<mirror::Object>*>(vreg_ptr)->AsMirrorPtr(); if (kChecked) { CHECK(VerifyReference(ref)) << "VReg " << i << "(" << ref << ") is in protected space, reference array " << false; @@ -231,7 +247,7 @@ class ShadowFrame { // This is needed for moving collectors since these can update the vreg references if they // happen to agree with references in the reference array. if (kMovingCollector && HasReferenceArray()) { - References()[i] = nullptr; + References()[i].Clear(); } } @@ -242,7 +258,7 @@ class ShadowFrame { // This is needed for moving collectors since these can update the vreg references if they // happen to agree with references in the reference array. if (kMovingCollector && HasReferenceArray()) { - References()[i] = nullptr; + References()[i].Clear(); } } @@ -255,8 +271,8 @@ class ShadowFrame { // This is needed for moving collectors since these can update the vreg references if they // happen to agree with references in the reference array. if (kMovingCollector && HasReferenceArray()) { - References()[i] = nullptr; - References()[i + 1] = nullptr; + References()[i].Clear(); + References()[i + 1].Clear(); } } @@ -269,24 +285,24 @@ class ShadowFrame { // This is needed for moving collectors since these can update the vreg references if they // happen to agree with references in the reference array. if (kMovingCollector && HasReferenceArray()) { - References()[i] = nullptr; - References()[i + 1] = nullptr; + References()[i].Clear(); + References()[i + 1].Clear(); } } - void SetVRegReference(size_t i, mirror::Object* val) { + void SetVRegReference(size_t i, mirror::Object* val) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK_LT(i, NumberOfVRegs()); DCHECK(!kMovingCollector || VerifyReference(val)) << "VReg " << i << "(" << val << ") is in protected space"; uint32_t* vreg = &vregs_[i]; - *reinterpret_cast<mirror::Object**>(vreg) = val; + reinterpret_cast<StackReference<mirror::Object>*>(vreg)->Assign(val); if (HasReferenceArray()) { - References()[i] = val; + References()[i].Assign(val); } } - mirror::ArtMethod* GetMethod() const { - DCHECK_NE(method_, static_cast<void*>(NULL)); + mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(method_ != nullptr); return method_; } @@ -298,7 +314,7 @@ class ShadowFrame { void SetMethod(mirror::ArtMethod* method) { #if defined(ART_USE_PORTABLE_COMPILER) - DCHECK_NE(method, static_cast<void*>(NULL)); + DCHECK(method != nullptr); method_ = method; #else UNUSED(method); @@ -306,7 +322,7 @@ class ShadowFrame { #endif } - bool Contains(mirror::Object** shadow_frame_entry_obj) const { + bool Contains(StackReference<mirror::Object>* shadow_frame_entry_obj) const { if (HasReferenceArray()) { return ((&References()[0] <= shadow_frame_entry_obj) && (shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1]))); @@ -346,22 +362,22 @@ class ShadowFrame { CHECK_LT(num_vregs, static_cast<uint32_t>(kHasReferenceArray)); number_of_vregs_ |= kHasReferenceArray; #endif - memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(mirror::Object*))); + memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(StackReference<mirror::Object>))); } else { memset(vregs_, 0, num_vregs * sizeof(uint32_t)); } } - mirror::Object* const* References() const { + const StackReference<mirror::Object>* References() const { DCHECK(HasReferenceArray()); const uint32_t* vreg_end = &vregs_[NumberOfVRegs()]; - return reinterpret_cast<mirror::Object* const*>(vreg_end); + return reinterpret_cast<const StackReference<mirror::Object>*>(vreg_end); } bool VerifyReference(const mirror::Object* val) const; - mirror::Object** References() { - return const_cast<mirror::Object**>(const_cast<const ShadowFrame*>(this)->References()); + StackReference<mirror::Object>* References() { + return const_cast<StackReference<mirror::Object>*>(const_cast<const ShadowFrame*>(this)->References()); } #if defined(ART_USE_PORTABLE_COMPILER) @@ -470,9 +486,9 @@ class PACKED(4) ManagedStack { return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_); } - size_t NumJniShadowFrameReferences() const; + size_t NumJniShadowFrameReferences() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool ShadowFramesContain(mirror::Object** shadow_frame_entry) const; + bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const; private: ManagedStack* link_; @@ -494,18 +510,18 @@ class StackVisitor { void WalkStack(bool include_transitions = false) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ArtMethod* GetMethod() const { - if (cur_shadow_frame_ != NULL) { + mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (cur_shadow_frame_ != nullptr) { return cur_shadow_frame_->GetMethod(); - } else if (cur_quick_frame_ != NULL) { + } else if (cur_quick_frame_ != nullptr) { return *cur_quick_frame_; } else { - return NULL; + return nullptr; } } bool IsShadowFrame() const { - return cur_shadow_frame_ != NULL; + return cur_shadow_frame_ != nullptr; } uint32_t GetDexPc() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -514,9 +530,10 @@ class StackVisitor { size_t GetNativePcOffset() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - uintptr_t* CalleeSaveAddress(int num, size_t frame_size) const { + uintptr_t* CalleeSaveAddress(int num, size_t frame_size) const + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Callee saves are held at the top of the frame - DCHECK(GetMethod() != NULL); + DCHECK(GetMethod() != nullptr); byte* save_addr = reinterpret_cast<byte*>(cur_quick_frame_) + frame_size - ((num + 1) * kPointerSize); #if defined(__i386__) @@ -553,17 +570,17 @@ class StackVisitor { // This is a fast-path for getting/setting values in a quick frame. uint32_t* GetVRegAddr(mirror::ArtMethod** cur_quick_frame, const DexFile::CodeItem* code_item, - uint32_t core_spills, uint32_t fp_spills, size_t frame_size, - uint16_t vreg) const { + uint32_t core_spills, uint32_t fp_spills, size_t frame_size, + uint16_t vreg) const { int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg); DCHECK_EQ(cur_quick_frame, GetCurrentQuickFrame()); byte* vreg_addr = reinterpret_cast<byte*>(cur_quick_frame) + offset; return reinterpret_cast<uint32_t*>(vreg_addr); } - uintptr_t GetReturnPc() const; + uintptr_t GetReturnPc() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetReturnPc(uintptr_t new_ret_pc); + void SetReturnPc(uintptr_t new_ret_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); /* * Return sp-relative offset for a Dalvik virtual register, compiler |