From 590fee9e8972f872301c2d16a575d579ee564bee Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Fri, 13 Sep 2013 13:46:47 -0700 Subject: Compacting collector. The compacting collector is currently similar to semispace. It works by copying objects back and forth between two bump pointer spaces. There are types of objects which are "non-movable" due to current runtime limitations. These are Classes, Methods, and Fields. Bump pointer spaces are a new type of continuous alloc space which have no lock in the allocation code path. When you allocate from these it uses atomic operations to increase an index. Traversing the objects in the bump pointer space relies on Object::SizeOf matching the allocated size exactly. Runtime changes: JNI::GetArrayElements returns copies objects if you attempt to get the backing data of a movable array. For GetArrayElementsCritical, we return direct backing storage for any types of arrays, but temporarily disable the GC until the critical region is completed. Added a new runtime call called VisitObjects, this is used in place of the old pattern which was flushing the allocation stack and walking the bitmaps. Changed image writer to be compaction safe and use object monitor word for forwarding addresses. Added a bunch of added SIRTs to ClassLinker, MethodLinker, etc.. TODO: Enable switching allocators, compacting on background, etc.. Bug: 8981901 Change-Id: I3c886fd322a6eef2b99388d19a765042ec26ab99 --- runtime/stack.h | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'runtime/stack.h') 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(vreg); } + template 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(ref) != vregs_[i]) { return nullptr; @@ -161,7 +166,12 @@ class ShadowFrame { return ref; } else { const uint32_t* vreg = &vregs_[i]; - return *reinterpret_cast(vreg); + mirror::Object* ref = *reinterpret_cast(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(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(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(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(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(vreg) = val; if (HasReferenceArray()) { @@ -280,6 +314,8 @@ class ShadowFrame { return reinterpret_cast(vreg_end); } + bool VerifyReference(const mirror::Object* val) const; + mirror::Object** References() { return const_cast(const_cast(this)->References()); } -- cgit v1.1