Avoid incremental marking write-barrier when constructing descriptor arrays.

R=erik.corry@gmail.com

Review URL: http://codereview.chromium.org/8360004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9735 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vegorov@chromium.org 2011-10-21 10:32:38 +00:00
parent 666c4be29f
commit af876ee474
8 changed files with 185 additions and 98 deletions

View File

@ -376,26 +376,28 @@ Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
PropertyAttributes attributes =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
DescriptorArray::WhitenessWitness witness(*descriptors);
{ // Add length.
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionLength);
CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes);
descriptors->Set(0, &d);
descriptors->Set(0, &d, witness);
}
{ // Add name.
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionName);
CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes);
descriptors->Set(1, &d);
descriptors->Set(1, &d, witness);
}
{ // Add arguments.
Handle<Foreign> foreign =
factory()->NewForeign(&Accessors::FunctionArguments);
CallbacksDescriptor d(*factory()->arguments_symbol(), *foreign, attributes);
descriptors->Set(2, &d);
descriptors->Set(2, &d, witness);
}
{ // Add caller.
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionCaller);
CallbacksDescriptor d(*factory()->caller_symbol(), *foreign, attributes);
descriptors->Set(3, &d);
descriptors->Set(3, &d, witness);
}
if (prototypeMode != DONT_ADD_PROTOTYPE) {
// Add prototype.
@ -405,9 +407,9 @@ Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
Handle<Foreign> foreign =
factory()->NewForeign(&Accessors::FunctionPrototype);
CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes);
descriptors->Set(4, &d);
descriptors->Set(4, &d, witness);
}
descriptors->Sort();
descriptors->Sort(witness);
return descriptors;
}
@ -525,25 +527,27 @@ Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor(
PropertyAttributes attributes = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE);
DescriptorArray::WhitenessWitness witness(*descriptors);
{ // length
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionLength);
CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes);
descriptors->Set(0, &d);
descriptors->Set(0, &d, witness);
}
{ // name
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionName);
CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes);
descriptors->Set(1, &d);
descriptors->Set(1, &d, witness);
}
{ // arguments
CallbacksDescriptor d(*factory()->arguments_symbol(),
*arguments,
attributes);
descriptors->Set(2, &d);
descriptors->Set(2, &d, witness);
}
{ // caller
CallbacksDescriptor d(*factory()->caller_symbol(), *caller, attributes);
descriptors->Set(3, &d);
descriptors->Set(3, &d, witness);
}
// prototype
@ -554,10 +558,10 @@ Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor(
Handle<Foreign> foreign =
factory()->NewForeign(&Accessors::FunctionPrototype);
CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes);
descriptors->Set(4, &d);
descriptors->Set(4, &d, witness);
}
descriptors->Sort();
descriptors->Sort(witness);
return descriptors;
}
@ -942,6 +946,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
ASSERT_EQ(0, initial_map->inobject_properties());
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(5);
DescriptorArray::WhitenessWitness witness(*descriptors);
PropertyAttributes final =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
int enum_index = 0;
@ -951,7 +956,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kSourceFieldIndex,
final,
enum_index++);
descriptors->Set(0, &field);
descriptors->Set(0, &field, witness);
}
{
// ECMA-262, section 15.10.7.2.
@ -959,7 +964,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kGlobalFieldIndex,
final,
enum_index++);
descriptors->Set(1, &field);
descriptors->Set(1, &field, witness);
}
{
// ECMA-262, section 15.10.7.3.
@ -967,7 +972,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kIgnoreCaseFieldIndex,
final,
enum_index++);
descriptors->Set(2, &field);
descriptors->Set(2, &field, witness);
}
{
// ECMA-262, section 15.10.7.4.
@ -975,7 +980,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kMultilineFieldIndex,
final,
enum_index++);
descriptors->Set(3, &field);
descriptors->Set(3, &field, witness);
}
{
// ECMA-262, section 15.10.7.5.
@ -985,10 +990,10 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kLastIndexFieldIndex,
writable,
enum_index++);
descriptors->Set(4, &field);
descriptors->Set(4, &field, witness);
}
descriptors->SetNextEnumerationIndex(enum_index);
descriptors->Sort();
descriptors->Sort(witness);
initial_map->set_inobject_properties(5);
initial_map->set_pre_allocated_property_fields(5);
@ -1125,19 +1130,20 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
// Create the descriptor array for the arguments object.
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3);
DescriptorArray::WhitenessWitness witness(*descriptors);
{ // length
FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM);
descriptors->Set(0, &d);
descriptors->Set(0, &d, witness);
}
{ // callee
CallbacksDescriptor d(*factory->callee_symbol(), *callee, attributes);
descriptors->Set(1, &d);
descriptors->Set(1, &d, witness);
}
{ // caller
CallbacksDescriptor d(*factory->caller_symbol(), *caller, attributes);
descriptors->Set(2, &d);
descriptors->Set(2, &d, witness);
}
descriptors->Sort();
descriptors->Sort(witness);
// Create the map. Allocate one in-object field for length.
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE,
@ -1696,7 +1702,9 @@ bool Genesis::InstallNatives() {
Handle<DescriptorArray> reresult_descriptors =
factory()->NewDescriptorArray(3);
reresult_descriptors->CopyFrom(0, *array_descriptors, 0);
DescriptorArray::WhitenessWitness witness(*reresult_descriptors);
reresult_descriptors->CopyFrom(0, *array_descriptors, 0, witness);
int enum_index = 0;
{
@ -1704,7 +1712,7 @@ bool Genesis::InstallNatives() {
JSRegExpResult::kIndexIndex,
NONE,
enum_index++);
reresult_descriptors->Set(1, &index_field);
reresult_descriptors->Set(1, &index_field, witness);
}
{
@ -1712,9 +1720,9 @@ bool Genesis::InstallNatives() {
JSRegExpResult::kInputIndex,
NONE,
enum_index++);
reresult_descriptors->Set(2, &input_field);
reresult_descriptors->Set(2, &input_field, witness);
}
reresult_descriptors->Sort();
reresult_descriptors->Sort(witness);
initial_map->set_inobject_properties(2);
initial_map->set_pre_allocated_property_fields(2);

View File

@ -831,10 +831,13 @@ Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
// Number of descriptors added to the result so far.
int descriptor_count = 0;
// Ensure that marking will not progress and change color of objects.
DescriptorArray::WhitenessWitness witness(*result);
// Copy the descriptors from the array.
for (int i = 0; i < array->number_of_descriptors(); i++) {
if (array->GetType(i) != NULL_DESCRIPTOR) {
result->CopyFrom(descriptor_count++, *array, i);
result->CopyFrom(descriptor_count++, *array, i, witness);
}
}
@ -854,7 +857,7 @@ Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
if (result->LinearSearch(*key, descriptor_count) ==
DescriptorArray::kNotFound) {
CallbacksDescriptor desc(*key, *entry, entry->property_attributes());
result->Set(descriptor_count, &desc);
result->Set(descriptor_count, &desc, witness);
descriptor_count++;
} else {
duplicates++;
@ -868,13 +871,13 @@ Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
Handle<DescriptorArray> new_result =
NewDescriptorArray(number_of_descriptors);
for (int i = 0; i < number_of_descriptors; i++) {
new_result->CopyFrom(i, *result, i);
new_result->CopyFrom(i, *result, i, witness);
}
result = new_result;
}
// Sort the result before returning.
result->Sort();
result->Sort(witness);
return result;
}

View File

@ -3434,22 +3434,22 @@ MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) {
// Inline constructor can only handle inobject properties.
fun->shared()->ForbidInlineConstructor();
} else {
Object* descriptors_obj;
DescriptorArray* descriptors;
{ MaybeObject* maybe_descriptors_obj = DescriptorArray::Allocate(count);
if (!maybe_descriptors_obj->ToObject(&descriptors_obj)) {
if (!maybe_descriptors_obj->To<DescriptorArray>(&descriptors)) {
return maybe_descriptors_obj;
}
}
DescriptorArray* descriptors = DescriptorArray::cast(descriptors_obj);
DescriptorArray::WhitenessWitness witness(descriptors);
for (int i = 0; i < count; i++) {
String* name = fun->shared()->GetThisPropertyAssignmentName(i);
ASSERT(name->IsSymbol());
FieldDescriptor field(name, i, NONE);
field.SetEnumerationIndex(i);
descriptors->Set(i, &field);
descriptors->Set(i, &field, witness);
}
descriptors->SetNextEnumerationIndex(count);
descriptors->SortUnchecked();
descriptors->SortUnchecked(witness);
// The descriptors may contain duplicates because the compiler does not
// guarantee the uniqueness of property names (it would have required

View File

@ -50,7 +50,8 @@ IncrementalMarking::IncrementalMarking(Heap* heap)
steps_took_since_last_gc_(0),
should_hurry_(false),
allocation_marking_factor_(0),
allocated_(0) {
allocated_(0),
no_marking_scope_depth_(0) {
}
@ -702,6 +703,8 @@ void IncrementalMarking::Step(intptr_t allocated_bytes) {
if (allocated_ < kAllocatedThreshold) return;
if (state_ == MARKING && no_marking_scope_depth_ > 0) return;
intptr_t bytes_to_process = allocated_ * allocation_marking_factor_;
double start = 0;

View File

@ -198,6 +198,14 @@ class IncrementalMarking {
}
}
void EnterNoMarkingScope() {
no_marking_scope_depth_++;
}
void LeaveNoMarkingScope() {
no_marking_scope_depth_--;
}
private:
void set_should_hurry(bool val) {
should_hurry_ = val;
@ -249,6 +257,8 @@ class IncrementalMarking {
int allocation_marking_factor_;
intptr_t allocated_;
int no_marking_scope_depth_;
DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalMarking);
};

View File

@ -1813,15 +1813,13 @@ void FixedArray::set(int index,
}
void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
void FixedArray::NoWriteBarrierSet(FixedArray* array,
int index,
Object* value) {
ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
ASSERT(index >= 0 && index < array->length());
ASSERT(!HEAP->InNewSpace(value));
WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
array->GetHeap()->incremental_marking()->RecordWrite(
array,
HeapObject::RawField(array, kHeaderSize + index * kPointerSize),
value);
}
@ -1909,10 +1907,12 @@ void DescriptorArray::set_bit_field3_storage(int value) {
}
void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
void DescriptorArray::NoWriteBarrierSwap(FixedArray* array,
int first,
int second) {
Object* tmp = array->get(first);
fast_set(array, first, array->get(second));
fast_set(array, second, tmp);
NoWriteBarrierSet(array, first, array->get(second));
NoWriteBarrierSet(array, second, tmp);
}
@ -2020,7 +2020,9 @@ void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
}
void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
void DescriptorArray::Set(int descriptor_number,
Descriptor* desc,
const WhitenessWitness&) {
// Range check.
ASSERT(descriptor_number < number_of_descriptors());
@ -2028,26 +2030,53 @@ void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
ASSERT(!HEAP->InNewSpace(desc->GetKey()));
ASSERT(!HEAP->InNewSpace(desc->GetValue()));
fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
NoWriteBarrierSet(this,
ToKeyIndex(descriptor_number),
desc->GetKey());
FixedArray* content_array = GetContentArray();
fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
fast_set(content_array, ToDetailsIndex(descriptor_number),
desc->GetDetails().AsSmi());
NoWriteBarrierSet(content_array,
ToValueIndex(descriptor_number),
desc->GetValue());
NoWriteBarrierSet(content_array,
ToDetailsIndex(descriptor_number),
desc->GetDetails().AsSmi());
}
void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
void DescriptorArray::CopyFrom(int index,
DescriptorArray* src,
int src_index,
const WhitenessWitness& witness) {
Descriptor desc;
src->Get(src_index, &desc);
Set(index, &desc);
Set(index, &desc, witness);
}
void DescriptorArray::Swap(int first, int second) {
fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
void DescriptorArray::NoWriteBarrierSwapDescriptors(int first, int second) {
NoWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
FixedArray* content_array = GetContentArray();
fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
NoWriteBarrierSwap(content_array,
ToValueIndex(first),
ToValueIndex(second));
NoWriteBarrierSwap(content_array,
ToDetailsIndex(first),
ToDetailsIndex(second));
}
DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
: marking_(array->GetHeap()->incremental_marking()) {
marking_->EnterNoMarkingScope();
if (array->number_of_descriptors() > 0) {
ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
ASSERT(Marking::Color(array->GetContentArray()) == Marking::WHITE_OBJECT);
}
}
DescriptorArray::WhitenessWitness::~WhitenessWitness() {
marking_->LeaveNoMarkingScope();
}
@ -4461,7 +4490,7 @@ void Dictionary<Shape, Key>::SetEntry(int entry,
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
FixedArray::set(index, key, mode);
FixedArray::set(index+1, value, mode);
FixedArray::fast_set(this, index+2, details.AsSmi());
FixedArray::set(index+2, details.AsSmi());
}

View File

@ -5396,9 +5396,9 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
if (IsEmpty()) return; // Do nothing for empty descriptor array.
FixedArray::cast(bridge_storage)->
set(kEnumCacheBridgeCacheIndex, new_cache);
fast_set(FixedArray::cast(bridge_storage),
kEnumCacheBridgeEnumIndex,
get(kEnumerationIndexIndex));
NoWriteBarrierSet(FixedArray::cast(bridge_storage),
kEnumCacheBridgeEnumIndex,
get(kEnumerationIndexIndex));
set(kEnumerationIndexIndex, bridge_storage);
}
}
@ -5459,10 +5459,16 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor,
++new_size;
}
}
DescriptorArray* new_descriptors;
{ MaybeObject* maybe_result = Allocate(new_size);
if (!maybe_result->ToObject(&result)) return maybe_result;
if (!maybe_result->To<DescriptorArray>(&new_descriptors)) {
return maybe_result;
}
}
DescriptorArray* new_descriptors = DescriptorArray::cast(result);
DescriptorArray::WhitenessWitness witness(new_descriptors);
// Set the enumeration index in the descriptors and set the enumeration index
// in the result.
int enumeration_index = NextEnumerationIndex();
@ -5490,16 +5496,16 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor,
}
if (IsNullDescriptor(from_index)) continue;
if (remove_transitions && IsTransition(from_index)) continue;
new_descriptors->CopyFrom(to_index++, this, from_index);
new_descriptors->CopyFrom(to_index++, this, from_index, witness);
}
new_descriptors->Set(to_index++, descriptor);
new_descriptors->Set(to_index++, descriptor, witness);
if (replacing) from_index++;
for (; from_index < number_of_descriptors(); from_index++) {
if (IsNullDescriptor(from_index)) continue;
if (remove_transitions && IsTransition(from_index)) continue;
new_descriptors->CopyFrom(to_index++, this, from_index);
new_descriptors->CopyFrom(to_index++, this, from_index, witness);
}
ASSERT(to_index == new_descriptors->number_of_descriptors());
@ -5521,16 +5527,21 @@ MaybeObject* DescriptorArray::RemoveTransitions() {
}
// Allocate the new descriptor array.
Object* result;
DescriptorArray* new_descriptors;
{ MaybeObject* maybe_result = Allocate(number_of_descriptors() - num_removed);
if (!maybe_result->ToObject(&result)) return maybe_result;
if (!maybe_result->To<DescriptorArray>(&new_descriptors)) {
return maybe_result;
}
}
DescriptorArray* new_descriptors = DescriptorArray::cast(result);
DescriptorArray::WhitenessWitness witness(new_descriptors);
// Copy the content.
int next_descriptor = 0;
for (int i = 0; i < number_of_descriptors(); i++) {
if (IsProperty(i)) new_descriptors->CopyFrom(next_descriptor++, this, i);
if (IsProperty(i)) {
new_descriptors->CopyFrom(next_descriptor++, this, i, witness);
}
}
ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
@ -5538,7 +5549,7 @@ MaybeObject* DescriptorArray::RemoveTransitions() {
}
void DescriptorArray::SortUnchecked() {
void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
// In-place heap sort.
int len = number_of_descriptors();
@ -5559,7 +5570,7 @@ void DescriptorArray::SortUnchecked() {
}
}
if (child_hash <= parent_hash) break;
Swap(parent_index, child_index);
NoWriteBarrierSwapDescriptors(parent_index, child_index);
// Now element at child_index could be < its children.
parent_index = child_index; // parent_hash remains correct.
}
@ -5568,8 +5579,8 @@ void DescriptorArray::SortUnchecked() {
// Extract elements and create sorted array.
for (int i = len - 1; i > 0; --i) {
// Put max element at the back of the array.
Swap(0, i);
// Sift down the new top element.
NoWriteBarrierSwapDescriptors(0, i);
// Shift down the new top element.
int parent_index = 0;
const uint32_t parent_hash = GetKey(parent_index)->Hash();
const int max_parent_index = (i / 2) - 1;
@ -5584,15 +5595,15 @@ void DescriptorArray::SortUnchecked() {
}
}
if (child_hash <= parent_hash) break;
Swap(parent_index, child_index);
NoWriteBarrierSwapDescriptors(parent_index, child_index);
parent_index = child_index;
}
}
}
void DescriptorArray::Sort() {
SortUnchecked();
void DescriptorArray::Sort(const WhitenessWitness& witness) {
SortUnchecked(witness);
SLOW_ASSERT(IsSortedNoDuplicates());
}
@ -11709,8 +11720,8 @@ void CompilationCacheTable::Remove(Object* value) {
int entry_index = EntryToIndex(entry);
int value_index = entry_index + 1;
if (get(value_index) == value) {
fast_set(this, entry_index, null_value);
fast_set(this, value_index, null_value);
NoWriteBarrierSet(this, entry_index, null_value);
NoWriteBarrierSet(this, value_index, null_value);
ElementRemoved();
}
}
@ -12182,14 +12193,15 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
}
// Allocate the instance descriptor.
Object* descriptors_unchecked;
{ MaybeObject* maybe_descriptors_unchecked =
DescriptorArray* descriptors;
{ MaybeObject* maybe_descriptors =
DescriptorArray::Allocate(instance_descriptor_length);
if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
return maybe_descriptors_unchecked;
if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) {
return maybe_descriptors;
}
}
DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked);
DescriptorArray::WhitenessWitness witness(descriptors);
int inobject_props = obj->map()->inobject_properties();
int number_of_allocated_fields =
@ -12227,7 +12239,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
JSFunction::cast(value),
details.attributes(),
details.index());
descriptors->Set(next_descriptor++, &d);
descriptors->Set(next_descriptor++, &d, witness);
} else if (type == NORMAL) {
if (current_offset < inobject_props) {
obj->InObjectPropertyAtPut(current_offset,
@ -12241,13 +12253,13 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
current_offset++,
details.attributes(),
details.index());
descriptors->Set(next_descriptor++, &d);
descriptors->Set(next_descriptor++, &d, witness);
} else if (type == CALLBACKS) {
CallbacksDescriptor d(String::cast(key),
value,
details.attributes(),
details.index());
descriptors->Set(next_descriptor++, &d);
descriptors->Set(next_descriptor++, &d, witness);
} else {
UNREACHABLE();
}
@ -12255,7 +12267,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
}
ASSERT(current_offset == number_of_fields);
descriptors->Sort();
descriptors->Sort(witness);
// Allocate new map.
Object* new_map;
{ MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();

View File

@ -40,6 +40,7 @@
#endif
#include "v8checks.h"
//
// Most object types in the V8 JavaScript are described in this file.
//
@ -2185,7 +2186,9 @@ class FixedArray: public FixedArrayBase {
protected:
// Set operation on FixedArray without using write barriers. Can
// only be used for storing old space objects or smis.
static inline void fast_set(FixedArray* array, int index, Object* value);
static inline void NoWriteBarrierSet(FixedArray* array,
int index,
Object* value);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
@ -2250,6 +2253,9 @@ class FixedDoubleArray: public FixedArrayBase {
};
class IncrementalMarking;
// DescriptorArrays are fixed arrays used to hold instance descriptors.
// The format of the these objects is:
// TODO(1399): It should be possible to make room for bit_field3 in the map
@ -2291,7 +2297,7 @@ class DescriptorArray: public FixedArray {
// Set next enumeration index and flush any enum cache.
void SetNextEnumerationIndex(int value) {
if (!IsEmpty()) {
fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value));
set(kEnumerationIndexIndex, Smi::FromInt(value));
}
}
bool HasEnumCache() {
@ -2328,13 +2334,27 @@ class DescriptorArray: public FixedArray {
inline bool IsNullDescriptor(int descriptor_number);
inline bool IsDontEnum(int descriptor_number);
class WhitenessWitness {
public:
inline explicit WhitenessWitness(DescriptorArray* array);
inline ~WhitenessWitness();
private:
IncrementalMarking* marking_;
};
// Accessor for complete descriptor.
inline void Get(int descriptor_number, Descriptor* desc);
inline void Set(int descriptor_number, Descriptor* desc);
inline void Set(int descriptor_number,
Descriptor* desc,
const WhitenessWitness&);
// Transfer complete descriptor from another descriptor array to
// this one.
inline void CopyFrom(int index, DescriptorArray* src, int src_index);
inline void CopyFrom(int index,
DescriptorArray* src,
int src_index,
const WhitenessWitness&);
// Copy the descriptor array, insert a new descriptor and optionally
// remove map transitions. If the descriptor is already present, it is
@ -2351,11 +2371,11 @@ class DescriptorArray: public FixedArray {
// Sort the instance descriptors by the hash codes of their keys.
// Does not check for duplicates.
void SortUnchecked();
void SortUnchecked(const WhitenessWitness&);
// Sort the instance descriptors by the hash codes of their keys.
// Checks the result for duplicates.
void Sort();
void Sort(const WhitenessWitness&);
// Search the instance descriptors for given name.
inline int Search(String* name);
@ -2448,10 +2468,12 @@ class DescriptorArray: public FixedArray {
NULL_DESCRIPTOR;
}
// Swap operation on FixedArray without using write barriers.
static inline void fast_swap(FixedArray* array, int first, int second);
static inline void NoWriteBarrierSwap(FixedArray* array,
int first,
int second);
// Swap descriptor first and second.
inline void Swap(int first, int second);
inline void NoWriteBarrierSwapDescriptors(int first, int second);
FixedArray* GetContentArray() {
return FixedArray::cast(get(kContentArrayIndex));
@ -2593,12 +2615,12 @@ class HashTable: public FixedArray {
// Update the number of elements in the hash table.
void SetNumberOfElements(int nof) {
fast_set(this, kNumberOfElementsIndex, Smi::FromInt(nof));
set(kNumberOfElementsIndex, Smi::FromInt(nof));
}
// Update the number of deleted elements in the hash table.
void SetNumberOfDeletedElements(int nod) {
fast_set(this, kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
}
// Sets the capacity of the hash table.
@ -2608,7 +2630,7 @@ class HashTable: public FixedArray {
// and non-zero.
ASSERT(capacity > 0);
ASSERT(capacity <= kMaxCapacity);
fast_set(this, kCapacityIndex, Smi::FromInt(capacity));
set(kCapacityIndex, Smi::FromInt(capacity));
}
@ -2816,7 +2838,7 @@ class Dictionary: public HashTable<Shape, Key> {
// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
this->fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index));
this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
}
int NextEnumerationIndex() {