diff options
Diffstat (limited to 'runtime/stack.h')
-rw-r--r-- | runtime/stack.h | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/runtime/stack.h b/runtime/stack.h index a4b93bc..3d6b06a 100644 --- a/runtime/stack.h +++ b/runtime/stack.h @@ -150,10 +150,15 @@ class ShadowFrame { return *reinterpret_cast<unaligned_double*>(vreg); } + template <bool kChecked = false> mirror::Object* GetVRegReference(size_t i) const { DCHECK_LT(i, NumberOfVRegs()); if (HasReferenceArray()) { mirror::Object* ref = References()[i]; + 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 (reinterpret_cast<uint32_t>(ref) != vregs_[i]) { return nullptr; @@ -161,7 +166,12 @@ class ShadowFrame { return ref; } else { const uint32_t* vreg = &vregs_[i]; - return *reinterpret_cast<mirror::Object* const*>(vreg); + mirror::Object* ref = *reinterpret_cast<mirror::Object* const*>(vreg); + if (kChecked) { + CHECK(VerifyReference(ref)) << "VReg " << i + << "(" << ref << ") is in protected space, reference array " << false; + } + return ref; } } @@ -174,12 +184,22 @@ class ShadowFrame { DCHECK_LT(i, NumberOfVRegs()); uint32_t* vreg = &vregs_[i]; *reinterpret_cast<int32_t*>(vreg) = val; + // 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; + } } void SetVRegFloat(size_t i, float val) { DCHECK_LT(i, NumberOfVRegs()); uint32_t* vreg = &vregs_[i]; *reinterpret_cast<float*>(vreg) = val; + // 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; + } } void SetVRegLong(size_t i, int64_t val) { @@ -188,6 +208,12 @@ class ShadowFrame { // Alignment attribute required for GCC 4.8 typedef int64_t unaligned_int64 __attribute__ ((aligned (4))); *reinterpret_cast<unaligned_int64*>(vreg) = val; + // 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; + } } void SetVRegDouble(size_t i, double val) { @@ -196,10 +222,18 @@ class ShadowFrame { // Alignment attribute required for GCC 4.8 typedef double unaligned_double __attribute__ ((aligned (4))); *reinterpret_cast<unaligned_double*>(vreg) = val; + // 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; + } } void SetVRegReference(size_t i, mirror::Object* val) { 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; if (HasReferenceArray()) { @@ -280,6 +314,8 @@ class ShadowFrame { return reinterpret_cast<mirror::Object* const*>(vreg_end); } + bool VerifyReference(const mirror::Object* val) const; + mirror::Object** References() { return const_cast<mirror::Object**>(const_cast<const ShadowFrame*>(this)->References()); } |