From 75f35d3fe1be2cb42ed21f4af69cc384661b4438 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Wed, 30 May 2012 15:15:17 +0000 Subject: [PATCH] Decoupling MarkDescriptorArray as much as possible from the ContentArray. Review URL: https://chromiumcodereview.appspot.com/10417030 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11683 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mark-compact.cc | 13 ++++++------- src/objects-inl.h | 6 ++++++ src/objects.cc | 5 ++++- src/objects.h | 9 +++++++++ 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/mark-compact.cc b/src/mark-compact.cc index 69542685a2..d1be73561e 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -1872,17 +1872,16 @@ void Marker::MarkDescriptorArray(DescriptorArray* descriptors) { if (!base_marker()->MarkObjectAndPush(descriptors)) return; FixedArray* contents = FixedArray::cast( descriptors->get(DescriptorArray::kContentArrayIndex)); - ASSERT(contents->length() >= 2); ASSERT(Marking::IsWhite(Marking::MarkBitFrom(contents))); base_marker()->MarkObjectWithoutPush(contents); - // Contents contains (value, details) pairs. If the descriptor contains a - // transition (value is a Map), we don't mark the value as live. It might - // be set to the NULL_DESCRIPTOR in ClearNonLiveTransitions later. - for (int i = 0; i < contents->length(); i += 2) { - PropertyDetails details(Smi::cast(contents->get(i + 1))); + // If the descriptor contains a transition (value is a Map), we don't mark the + // value as live. It might be set to the NULL_DESCRIPTOR in + // ClearNonLiveTransitions later. + for (int i = 0; i < descriptors->number_of_descriptors(); ++i) { + PropertyDetails details(descriptors->GetDetails(i)); + Object** slot = descriptors->GetValueSlot(i); - Object** slot = contents->data_start() + i; if (!(*slot)->IsHeapObject()) continue; HeapObject* value = HeapObject::cast(*slot); diff --git a/src/objects-inl.h b/src/objects-inl.h index d87b3a0413..5ad67c98b3 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1939,6 +1939,12 @@ String* DescriptorArray::GetKey(int descriptor_number) { } +Object** DescriptorArray::GetValueSlot(int descriptor_number) { + ASSERT(descriptor_number < number_of_descriptors()); + return GetContentArray()->data_start() + ToValueIndex(descriptor_number); +} + + Object* DescriptorArray::GetValue(int descriptor_number) { ASSERT(descriptor_number < number_of_descriptors()); return GetContentArray()->get(ToValueIndex(descriptor_number)); diff --git a/src/objects.cc b/src/objects.cc index 250136761c..21784c0f0b 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -6069,7 +6069,10 @@ MaybeObject* DescriptorArray::RemoveTransitions() { return new_descriptors; } - +// We need the whiteness witness since sort will reshuffle the entries in the +// descriptor array. If the descriptor array were to be black, the shuffling +// would move a slot that was already recorded as pointing into an evacuation +// candidate. This would result in missing updates upon evacuation. void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) { // In-place heap sort. int len = number_of_descriptors(); diff --git a/src/objects.h b/src/objects.h index 95f633f544..076368830a 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2453,6 +2453,7 @@ class DescriptorArray: public FixedArray { // Accessors for fetching instance descriptor at descriptor number. inline String* GetKey(int descriptor_number); inline Object* GetValue(int descriptor_number); + inline Object** GetValueSlot(int descriptor_number); inline PropertyDetails GetDetails(int descriptor_number); inline PropertyType GetType(int descriptor_number); inline int GetFieldIndex(int descriptor_number); @@ -2463,6 +2464,14 @@ class DescriptorArray: public FixedArray { inline bool IsTransitionOnly(int descriptor_number); inline bool IsNullDescriptor(int descriptor_number); + // WhitenessWitness is used to prove that a specific descriptor array is white + // (unmarked), so incremental write barriers can be skipped because the + // marking invariant cannot be broken and slots pointing into evacuation + // candidates will be discovered when the object is scanned. A witness is + // always stack-allocated right after creating a descriptor array. By + // allocating a witness, incremental marking is globally disabled. The witness + // is then passed along wherever needed to statically prove that the + // descriptor array is known to be white. class WhitenessWitness { public: inline explicit WhitenessWitness(DescriptorArray* array);