Commit af876ee4 authored by vegorov@chromium.org's avatar vegorov@chromium.org

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
parent 666c4be2
...@@ -376,26 +376,28 @@ Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor( ...@@ -376,26 +376,28 @@ Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
PropertyAttributes attributes = PropertyAttributes attributes =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
DescriptorArray::WhitenessWitness witness(*descriptors);
{ // Add length. { // Add length.
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionLength); Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionLength);
CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes); CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes);
descriptors->Set(0, &d); descriptors->Set(0, &d, witness);
} }
{ // Add name. { // Add name.
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionName); Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionName);
CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes); CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes);
descriptors->Set(1, &d); descriptors->Set(1, &d, witness);
} }
{ // Add arguments. { // Add arguments.
Handle<Foreign> foreign = Handle<Foreign> foreign =
factory()->NewForeign(&Accessors::FunctionArguments); factory()->NewForeign(&Accessors::FunctionArguments);
CallbacksDescriptor d(*factory()->arguments_symbol(), *foreign, attributes); CallbacksDescriptor d(*factory()->arguments_symbol(), *foreign, attributes);
descriptors->Set(2, &d); descriptors->Set(2, &d, witness);
} }
{ // Add caller. { // Add caller.
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionCaller); Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionCaller);
CallbacksDescriptor d(*factory()->caller_symbol(), *foreign, attributes); CallbacksDescriptor d(*factory()->caller_symbol(), *foreign, attributes);
descriptors->Set(3, &d); descriptors->Set(3, &d, witness);
} }
if (prototypeMode != DONT_ADD_PROTOTYPE) { if (prototypeMode != DONT_ADD_PROTOTYPE) {
// Add prototype. // Add prototype.
...@@ -405,9 +407,9 @@ Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor( ...@@ -405,9 +407,9 @@ Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
Handle<Foreign> foreign = Handle<Foreign> foreign =
factory()->NewForeign(&Accessors::FunctionPrototype); factory()->NewForeign(&Accessors::FunctionPrototype);
CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes); CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes);
descriptors->Set(4, &d); descriptors->Set(4, &d, witness);
} }
descriptors->Sort(); descriptors->Sort(witness);
return descriptors; return descriptors;
} }
...@@ -525,25 +527,27 @@ Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor( ...@@ -525,25 +527,27 @@ Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor(
PropertyAttributes attributes = static_cast<PropertyAttributes>( PropertyAttributes attributes = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE); DONT_ENUM | DONT_DELETE);
DescriptorArray::WhitenessWitness witness(*descriptors);
{ // length { // length
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionLength); Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionLength);
CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes); CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes);
descriptors->Set(0, &d); descriptors->Set(0, &d, witness);
} }
{ // name { // name
Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionName); Handle<Foreign> foreign = factory()->NewForeign(&Accessors::FunctionName);
CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes); CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes);
descriptors->Set(1, &d); descriptors->Set(1, &d, witness);
} }
{ // arguments { // arguments
CallbacksDescriptor d(*factory()->arguments_symbol(), CallbacksDescriptor d(*factory()->arguments_symbol(),
*arguments, *arguments,
attributes); attributes);
descriptors->Set(2, &d); descriptors->Set(2, &d, witness);
} }
{ // caller { // caller
CallbacksDescriptor d(*factory()->caller_symbol(), *caller, attributes); CallbacksDescriptor d(*factory()->caller_symbol(), *caller, attributes);
descriptors->Set(3, &d); descriptors->Set(3, &d, witness);
} }
// prototype // prototype
...@@ -554,10 +558,10 @@ Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor( ...@@ -554,10 +558,10 @@ Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor(
Handle<Foreign> foreign = Handle<Foreign> foreign =
factory()->NewForeign(&Accessors::FunctionPrototype); factory()->NewForeign(&Accessors::FunctionPrototype);
CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes); CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes);
descriptors->Set(4, &d); descriptors->Set(4, &d, witness);
} }
descriptors->Sort(); descriptors->Sort(witness);
return descriptors; return descriptors;
} }
...@@ -942,6 +946,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -942,6 +946,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
ASSERT_EQ(0, initial_map->inobject_properties()); ASSERT_EQ(0, initial_map->inobject_properties());
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(5); Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(5);
DescriptorArray::WhitenessWitness witness(*descriptors);
PropertyAttributes final = PropertyAttributes final =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
int enum_index = 0; int enum_index = 0;
...@@ -951,7 +956,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -951,7 +956,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kSourceFieldIndex, JSRegExp::kSourceFieldIndex,
final, final,
enum_index++); enum_index++);
descriptors->Set(0, &field); descriptors->Set(0, &field, witness);
} }
{ {
// ECMA-262, section 15.10.7.2. // ECMA-262, section 15.10.7.2.
...@@ -959,7 +964,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -959,7 +964,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kGlobalFieldIndex, JSRegExp::kGlobalFieldIndex,
final, final,
enum_index++); enum_index++);
descriptors->Set(1, &field); descriptors->Set(1, &field, witness);
} }
{ {
// ECMA-262, section 15.10.7.3. // ECMA-262, section 15.10.7.3.
...@@ -967,7 +972,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -967,7 +972,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kIgnoreCaseFieldIndex, JSRegExp::kIgnoreCaseFieldIndex,
final, final,
enum_index++); enum_index++);
descriptors->Set(2, &field); descriptors->Set(2, &field, witness);
} }
{ {
// ECMA-262, section 15.10.7.4. // ECMA-262, section 15.10.7.4.
...@@ -975,7 +980,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -975,7 +980,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kMultilineFieldIndex, JSRegExp::kMultilineFieldIndex,
final, final,
enum_index++); enum_index++);
descriptors->Set(3, &field); descriptors->Set(3, &field, witness);
} }
{ {
// ECMA-262, section 15.10.7.5. // ECMA-262, section 15.10.7.5.
...@@ -985,10 +990,10 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -985,10 +990,10 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
JSRegExp::kLastIndexFieldIndex, JSRegExp::kLastIndexFieldIndex,
writable, writable,
enum_index++); enum_index++);
descriptors->Set(4, &field); descriptors->Set(4, &field, witness);
} }
descriptors->SetNextEnumerationIndex(enum_index); descriptors->SetNextEnumerationIndex(enum_index);
descriptors->Sort(); descriptors->Sort(witness);
initial_map->set_inobject_properties(5); initial_map->set_inobject_properties(5);
initial_map->set_pre_allocated_property_fields(5); initial_map->set_pre_allocated_property_fields(5);
...@@ -1125,19 +1130,20 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -1125,19 +1130,20 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
// Create the descriptor array for the arguments object. // Create the descriptor array for the arguments object.
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3); Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3);
DescriptorArray::WhitenessWitness witness(*descriptors);
{ // length { // length
FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM); FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM);
descriptors->Set(0, &d); descriptors->Set(0, &d, witness);
} }
{ // callee { // callee
CallbacksDescriptor d(*factory->callee_symbol(), *callee, attributes); CallbacksDescriptor d(*factory->callee_symbol(), *callee, attributes);
descriptors->Set(1, &d); descriptors->Set(1, &d, witness);
} }
{ // caller { // caller
CallbacksDescriptor d(*factory->caller_symbol(), *caller, attributes); 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. // Create the map. Allocate one in-object field for length.
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE,
...@@ -1696,7 +1702,9 @@ bool Genesis::InstallNatives() { ...@@ -1696,7 +1702,9 @@ bool Genesis::InstallNatives() {
Handle<DescriptorArray> reresult_descriptors = Handle<DescriptorArray> reresult_descriptors =
factory()->NewDescriptorArray(3); 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; int enum_index = 0;
{ {
...@@ -1704,7 +1712,7 @@ bool Genesis::InstallNatives() { ...@@ -1704,7 +1712,7 @@ bool Genesis::InstallNatives() {
JSRegExpResult::kIndexIndex, JSRegExpResult::kIndexIndex,
NONE, NONE,
enum_index++); enum_index++);
reresult_descriptors->Set(1, &index_field); reresult_descriptors->Set(1, &index_field, witness);
} }
{ {
...@@ -1712,9 +1720,9 @@ bool Genesis::InstallNatives() { ...@@ -1712,9 +1720,9 @@ bool Genesis::InstallNatives() {
JSRegExpResult::kInputIndex, JSRegExpResult::kInputIndex,
NONE, NONE,
enum_index++); 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_inobject_properties(2);
initial_map->set_pre_allocated_property_fields(2); initial_map->set_pre_allocated_property_fields(2);
......
...@@ -831,10 +831,13 @@ Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors( ...@@ -831,10 +831,13 @@ Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
// Number of descriptors added to the result so far. // Number of descriptors added to the result so far.
int descriptor_count = 0; 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. // Copy the descriptors from the array.
for (int i = 0; i < array->number_of_descriptors(); i++) { for (int i = 0; i < array->number_of_descriptors(); i++) {
if (array->GetType(i) != NULL_DESCRIPTOR) { 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( ...@@ -854,7 +857,7 @@ Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
if (result->LinearSearch(*key, descriptor_count) == if (result->LinearSearch(*key, descriptor_count) ==
DescriptorArray::kNotFound) { DescriptorArray::kNotFound) {
CallbacksDescriptor desc(*key, *entry, entry->property_attributes()); CallbacksDescriptor desc(*key, *entry, entry->property_attributes());
result->Set(descriptor_count, &desc); result->Set(descriptor_count, &desc, witness);
descriptor_count++; descriptor_count++;
} else { } else {
duplicates++; duplicates++;
...@@ -868,13 +871,13 @@ Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors( ...@@ -868,13 +871,13 @@ Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
Handle<DescriptorArray> new_result = Handle<DescriptorArray> new_result =
NewDescriptorArray(number_of_descriptors); NewDescriptorArray(number_of_descriptors);
for (int i = 0; i < number_of_descriptors; i++) { 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; result = new_result;
} }
// Sort the result before returning. // Sort the result before returning.
result->Sort(); result->Sort(witness);
return result; return result;
} }
......
...@@ -3434,22 +3434,22 @@ MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) { ...@@ -3434,22 +3434,22 @@ MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) {
// Inline constructor can only handle inobject properties. // Inline constructor can only handle inobject properties.
fun->shared()->ForbidInlineConstructor(); fun->shared()->ForbidInlineConstructor();
} else { } else {
Object* descriptors_obj; DescriptorArray* descriptors;
{ MaybeObject* maybe_descriptors_obj = DescriptorArray::Allocate(count); { 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; return maybe_descriptors_obj;
} }
} }
DescriptorArray* descriptors = DescriptorArray::cast(descriptors_obj); DescriptorArray::WhitenessWitness witness(descriptors);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
String* name = fun->shared()->GetThisPropertyAssignmentName(i); String* name = fun->shared()->GetThisPropertyAssignmentName(i);
ASSERT(name->IsSymbol()); ASSERT(name->IsSymbol());
FieldDescriptor field(name, i, NONE); FieldDescriptor field(name, i, NONE);
field.SetEnumerationIndex(i); field.SetEnumerationIndex(i);
descriptors->Set(i, &field); descriptors->Set(i, &field, witness);
} }
descriptors->SetNextEnumerationIndex(count); descriptors->SetNextEnumerationIndex(count);
descriptors->SortUnchecked(); descriptors->SortUnchecked(witness);
// The descriptors may contain duplicates because the compiler does not // The descriptors may contain duplicates because the compiler does not
// guarantee the uniqueness of property names (it would have required // guarantee the uniqueness of property names (it would have required
......
...@@ -50,7 +50,8 @@ IncrementalMarking::IncrementalMarking(Heap* heap) ...@@ -50,7 +50,8 @@ IncrementalMarking::IncrementalMarking(Heap* heap)
steps_took_since_last_gc_(0), steps_took_since_last_gc_(0),
should_hurry_(false), should_hurry_(false),
allocation_marking_factor_(0), allocation_marking_factor_(0),
allocated_(0) { allocated_(0),
no_marking_scope_depth_(0) {
} }
...@@ -702,6 +703,8 @@ void IncrementalMarking::Step(intptr_t allocated_bytes) { ...@@ -702,6 +703,8 @@ void IncrementalMarking::Step(intptr_t allocated_bytes) {
if (allocated_ < kAllocatedThreshold) return; if (allocated_ < kAllocatedThreshold) return;
if (state_ == MARKING && no_marking_scope_depth_ > 0) return;
intptr_t bytes_to_process = allocated_ * allocation_marking_factor_; intptr_t bytes_to_process = allocated_ * allocation_marking_factor_;
double start = 0; double start = 0;
......
...@@ -198,6 +198,14 @@ class IncrementalMarking { ...@@ -198,6 +198,14 @@ class IncrementalMarking {
} }
} }
void EnterNoMarkingScope() {
no_marking_scope_depth_++;
}
void LeaveNoMarkingScope() {
no_marking_scope_depth_--;
}
private: private:
void set_should_hurry(bool val) { void set_should_hurry(bool val) {
should_hurry_ = val; should_hurry_ = val;
...@@ -249,6 +257,8 @@ class IncrementalMarking { ...@@ -249,6 +257,8 @@ class IncrementalMarking {
int allocation_marking_factor_; int allocation_marking_factor_;
intptr_t allocated_; intptr_t allocated_;
int no_marking_scope_depth_;
DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalMarking); DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalMarking);
}; };
......
...@@ -1813,15 +1813,13 @@ void FixedArray::set(int index, ...@@ -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(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
ASSERT(index >= 0 && index < array->length()); ASSERT(index >= 0 && index < array->length());
ASSERT(!HEAP->InNewSpace(value)); ASSERT(!HEAP->InNewSpace(value));
WRITE_FIELD(array, kHeaderSize + index * kPointerSize, 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) { ...@@ -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); Object* tmp = array->get(first);
fast_set(array, first, array->get(second)); NoWriteBarrierSet(array, first, array->get(second));
fast_set(array, second, tmp); NoWriteBarrierSet(array, second, tmp);
} }
...@@ -2020,7 +2020,9 @@ void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { ...@@ -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. // Range check.
ASSERT(descriptor_number < number_of_descriptors()); ASSERT(descriptor_number < number_of_descriptors());
...@@ -2028,26 +2030,53 @@ void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { ...@@ -2028,26 +2030,53 @@ void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
ASSERT(!HEAP->InNewSpace(desc->GetKey())); ASSERT(!HEAP->InNewSpace(desc->GetKey()));
ASSERT(!HEAP->InNewSpace(desc->GetValue())); ASSERT(!HEAP->InNewSpace(desc->GetValue()));
fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey()); NoWriteBarrierSet(this,
ToKeyIndex(descriptor_number),
desc->GetKey());
FixedArray* content_array = GetContentArray(); FixedArray* content_array = GetContentArray();
fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue()); NoWriteBarrierSet(content_array,
fast_set(content_array, ToDetailsIndex(descriptor_number), ToValueIndex(descriptor_number),
desc->GetDetails().AsSmi()); 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; Descriptor desc;
src->Get(src_index, &desc); src->Get(src_index, &desc);
Set(index, &desc); Set(index, &desc, witness);
} }
void DescriptorArray::Swap(int first, int second) { void DescriptorArray::NoWriteBarrierSwapDescriptors(int first, int second) {
fast_swap(this, ToKeyIndex(first), ToKeyIndex(second)); NoWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
FixedArray* content_array = GetContentArray(); FixedArray* content_array = GetContentArray();
fast_swap(content_array, ToValueIndex(first), ToValueIndex(second)); NoWriteBarrierSwap(content_array,
fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second)); 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, ...@@ -4461,7 +4490,7 @@ void Dictionary<Shape, Key>::SetEntry(int entry,
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc); WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
FixedArray::set(index, key, mode); FixedArray::set(index, key, mode);
FixedArray::set(index+1, value, mode); FixedArray::set(index+1, value, mode);
FixedArray::fast_set(this, index+2, details.AsSmi()); FixedArray::set(index+2, details.AsSmi());
} }
......
...@@ -5396,9 +5396,9 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, ...@@ -5396,9 +5396,9 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
if (IsEmpty()) return; // Do nothing for empty descriptor array. if (IsEmpty()) return; // Do nothing for empty descriptor array.
FixedArray::cast(bridge_storage)-> FixedArray::cast(bridge_storage)->
set(kEnumCacheBridgeCacheIndex, new_cache); set(kEnumCacheBridgeCacheIndex, new_cache);
fast_set(FixedArray::cast(bridge_storage), NoWriteBarrierSet(FixedArray::cast(bridge_storage),
kEnumCacheBridgeEnumIndex, kEnumCacheBridgeEnumIndex,
get(kEnumerationIndexIndex)); get(kEnumerationIndexIndex));
set(kEnumerationIndexIndex, bridge_storage); set(kEnumerationIndexIndex, bridge_storage);
} }
} }
...@@ -5459,10 +5459,16 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor, ...@@ -5459,10 +5459,16 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor,
++new_size; ++new_size;
} }
} }
DescriptorArray* new_descriptors;
{ MaybeObject* maybe_result = Allocate(new_size); { 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 // Set the enumeration index in the descriptors and set the enumeration index
// in the result. // in the result.
int enumeration_index = NextEnumerationIndex(); int enumeration_index = NextEnumerationIndex();
...@@ -5490,16 +5496,16 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor, ...@@ -5490,16 +5496,16 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor,
} }
if (IsNullDescriptor(from_index)) continue; if (IsNullDescriptor(from_index)) continue;
if (remove_transitions && IsTransition(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++; if (replacing) from_index++;
for (; from_index < number_of_descriptors(); from_index++) { for (; from_index < number_of_descriptors(); from_index++) {
if (IsNullDescriptor(from_index)) continue; if (IsNullDescriptor(from_index)) continue;
if (remove_transitions && IsTransition(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()); ASSERT(to_index == new_descriptors->number_of_descriptors());
...@@ -5521,16 +5527,21 @@ MaybeObject* DescriptorArray::RemoveTransitions() { ...@@ -5521,16 +5527,21 @@ MaybeObject* DescriptorArray::RemoveTransitions() {
} }
// Allocate the new descriptor array. // Allocate the new descriptor array.
Object* result; DescriptorArray* new_descriptors;
{ MaybeObject* maybe_result = Allocate(number_of_descriptors() - num_removed); { 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. // Copy the content.
int next_descriptor = 0; int next_descriptor = 0;
for (int i = 0; i < number_of_descriptors(); i++) { 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()); ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
...@@ -5538,7 +5549,7 @@ MaybeObject* DescriptorArray::RemoveTransitions() { ...@@ -5538,7 +5549,7 @@ MaybeObject* DescriptorArray::RemoveTransitions() {
} }
void DescriptorArray::SortUnchecked() { void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
// In-place heap sort. // In-place heap sort.
int len = number_of_descriptors(); int len = number_of_descriptors();
...@@ -5559,7 +5570,7 @@ void DescriptorArray::SortUnchecked() { ...@@ -5559,7 +5570,7 @@ void DescriptorArray::SortUnchecked() {
} }
} }
if (child_hash <= parent_hash) break; 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. // Now element at child_index could be < its children.
parent_index = child_index; // parent_hash remains correct. parent_index = child_index; // parent_hash remains correct.
} }
...@@ -5568,8 +5579,8 @@ void DescriptorArray::SortUnchecked() { ...@@ -5568,8 +5579,8 @@ void DescriptorArray::SortUnchecked() {
// Extract elements and create sorted array. // Extract elements and create sorted array.
for (int i = len - 1; i > 0; --i) { for (int i = len - 1; i > 0; --i) {
// Put max element at the back of the array. // Put max element at the back of the array.
Swap(0, i); NoWriteBarrierSwapDescriptors(0, i);
// Sift down the new top element. // Shift down the new top element.
int parent_index = 0; int parent_index = 0;
const uint32_t parent_hash = GetKey(parent_index)->Hash(); const uint32_t parent_hash = GetKey(parent_index)->Hash();
const int max_parent_index = (i / 2) - 1; const int max_parent_index = (i / 2) - 1;
...@@ -5584,15 +5595,15 @@ void DescriptorArray::SortUnchecked() { ...@@ -5584,15 +5595,15 @@ void DescriptorArray::SortUnchecked() {
} }
} }
if (child_hash <= parent_hash) break; if (child_hash <= parent_hash) break;
Swap(parent_index, child_index); NoWriteBarrierSwapDescriptors(parent_index, child_index);
parent_index = child_index; parent_index = child_index;
} }
} }
} }
void DescriptorArray::Sort() { void DescriptorArray::Sort(const WhitenessWitness& witness) {
SortUnchecked(); SortUnchecked(witness);
SLOW_ASSERT(IsSortedNoDuplicates()); SLOW_ASSERT(IsSortedNoDuplicates());
} }
...@@ -11709,8 +11720,8 @@ void CompilationCacheTable::Remove(Object* value) { ...@@ -11709,8 +11720,8 @@ void CompilationCacheTable::Remove(Object* value) {
int entry_index = EntryToIndex(entry); int entry_index = EntryToIndex(entry);
int value_index = entry_index + 1; int value_index = entry_index + 1;
if (get(value_index) == value) { if (get(value_index) == value) {
fast_set(this, entry_index, null_value); NoWriteBarrierSet(this, entry_index, null_value);
fast_set(this, value_index, null_value); NoWriteBarrierSet(this, value_index, null_value);
ElementRemoved(); ElementRemoved();
} }
} }
...@@ -12182,14 +12193,15 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( ...@@ -12182,14 +12193,15 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
} }
// Allocate the instance descriptor. // Allocate the instance descriptor.
Object* descriptors_unchecked; DescriptorArray* descriptors;
{ MaybeObject* maybe_descriptors_unchecked = { MaybeObject* maybe_descriptors =
DescriptorArray::Allocate(instance_descriptor_length); DescriptorArray::Allocate(instance_descriptor_length);
if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) {
return maybe_descriptors_unchecked; return maybe_descriptors;
} }
} }
DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked);
DescriptorArray::WhitenessWitness witness(descriptors);
int inobject_props = obj->map()->inobject_properties(); int inobject_props = obj->map()->inobject_properties();
int number_of_allocated_fields = int number_of_allocated_fields =
...@@ -12227,7 +12239,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( ...@@ -12227,7 +12239,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
JSFunction::cast(value), JSFunction::cast(value),
details.attributes(), details.attributes(),
details.index()); details.index());
descriptors->Set(next_descriptor++, &d); descriptors->Set(next_descriptor++, &d, witness);
} else if (type == NORMAL) { } else if (type == NORMAL) {
if (current_offset < inobject_props) { if (current_offset < inobject_props) {
obj->InObjectPropertyAtPut(current_offset, obj->InObjectPropertyAtPut(current_offset,
...@@ -12241,13 +12253,13 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( ...@@ -12241,13 +12253,13 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
current_offset++, current_offset++,
details.attributes(), details.attributes(),
details.index()); details.index());
descriptors->Set(next_descriptor++, &d); descriptors->Set(next_descriptor++, &d, witness);
} else if (type == CALLBACKS) { } else if (type == CALLBACKS) {
CallbacksDescriptor d(String::cast(key), CallbacksDescriptor d(String::cast(key),
value, value,
details.attributes(), details.attributes(),
details.index()); details.index());
descriptors->Set(next_descriptor++, &d); descriptors->Set(next_descriptor++, &d, witness);
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
...@@ -12255,7 +12267,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( ...@@ -12255,7 +12267,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
} }
ASSERT(current_offset == number_of_fields); ASSERT(current_offset == number_of_fields);
descriptors->Sort(); descriptors->Sort(witness);
// Allocate new map. // Allocate new map.
Object* new_map; Object* new_map;
{ MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors(); { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#endif #endif
#include "v8checks.h" #include "v8checks.h"
// //
// Most object types in the V8 JavaScript are described in this file. // Most object types in the V8 JavaScript are described in this file.
// //
...@@ -2185,7 +2186,9 @@ class FixedArray: public FixedArrayBase { ...@@ -2185,7 +2186,9 @@ class FixedArray: public FixedArrayBase {
protected: protected:
// Set operation on FixedArray without using write barriers. Can // Set operation on FixedArray without using write barriers. Can
// only be used for storing old space objects or smis. // 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: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray); DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
...@@ -2250,6 +2253,9 @@ class FixedDoubleArray: public FixedArrayBase { ...@@ -2250,6 +2253,9 @@ class FixedDoubleArray: public FixedArrayBase {
}; };
class IncrementalMarking;
// DescriptorArrays are fixed arrays used to hold instance descriptors. // DescriptorArrays are fixed arrays used to hold instance descriptors.
// The format of the these objects is: // The format of the these objects is:
// TODO(1399): It should be possible to make room for bit_field3 in the map // TODO(1399): It should be possible to make room for bit_field3 in the map
...@@ -2291,7 +2297,7 @@ class DescriptorArray: public FixedArray { ...@@ -2291,7 +2297,7 @@ class DescriptorArray: public FixedArray {
// Set next enumeration index and flush any enum cache. // Set next enumeration index and flush any enum cache.
void SetNextEnumerationIndex(int value) { void SetNextEnumerationIndex(int value) {
if (!IsEmpty()) { if (!IsEmpty()) {
fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value)); set(kEnumerationIndexIndex, Smi::FromInt(value));
} }
} }
bool HasEnumCache() { bool HasEnumCache() {
...@@ -2328,13 +2334,27 @@ class DescriptorArray: public FixedArray { ...@@ -2328,13 +2334,27 @@ class DescriptorArray: public FixedArray {
inline bool IsNullDescriptor(int descriptor_number); inline bool IsNullDescriptor(int descriptor_number);
inline bool IsDontEnum(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. // Accessor for complete descriptor.
inline void Get(int descriptor_number, Descriptor* desc); 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 // Transfer complete descriptor from another descriptor array to
// this one. // 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 // Copy the descriptor array, insert a new descriptor and optionally
// remove map transitions. If the descriptor is already present, it is // remove map transitions. If the descriptor is already present, it is
...@@ -2351,11 +2371,11 @@ class DescriptorArray: public FixedArray { ...@@ -2351,11 +2371,11 @@ class DescriptorArray: public FixedArray {
// Sort the instance descriptors by the hash codes of their keys. // Sort the instance descriptors by the hash codes of their keys.
// Does not check for duplicates. // Does not check for duplicates.
void SortUnchecked(); void SortUnchecked(const WhitenessWitness&);
// Sort the instance descriptors by the hash codes of their keys. // Sort the instance descriptors by the hash codes of their keys.
// Checks the result for duplicates. // Checks the result for duplicates.
void Sort(); void Sort(const WhitenessWitness&);
// Search the instance descriptors for given name. // Search the instance descriptors for given name.
inline int Search(String* name); inline int Search(String* name);
...@@ -2448,10 +2468,12 @@ class DescriptorArray: public FixedArray { ...@@ -2448,10 +2468,12 @@ class DescriptorArray: public FixedArray {
NULL_DESCRIPTOR; NULL_DESCRIPTOR;
} }
// Swap operation on FixedArray without using write barriers. // 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. // Swap descriptor first and second.
inline void Swap(int first, int second); inline void NoWriteBarrierSwapDescriptors(int first, int second);
FixedArray* GetContentArray() { FixedArray* GetContentArray() {
return FixedArray::cast(get(kContentArrayIndex)); return FixedArray::cast(get(kContentArrayIndex));
...@@ -2593,12 +2615,12 @@ class HashTable: public FixedArray { ...@@ -2593,12 +2615,12 @@ class HashTable: public FixedArray {
// Update the number of elements in the hash table. // Update the number of elements in the hash table.
void SetNumberOfElements(int nof) { 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. // Update the number of deleted elements in the hash table.
void SetNumberOfDeletedElements(int nod) { void SetNumberOfDeletedElements(int nod) {
fast_set(this, kNumberOfDeletedElementsIndex, Smi::FromInt(nod)); set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
} }
// Sets the capacity of the hash table. // Sets the capacity of the hash table.
...@@ -2608,7 +2630,7 @@ class HashTable: public FixedArray { ...@@ -2608,7 +2630,7 @@ class HashTable: public FixedArray {
// and non-zero. // and non-zero.
ASSERT(capacity > 0); ASSERT(capacity > 0);
ASSERT(capacity <= kMaxCapacity); 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> { ...@@ -2816,7 +2838,7 @@ class Dictionary: public HashTable<Shape, Key> {
// Accessors for next enumeration index. // Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) { void SetNextEnumerationIndex(int index) {
this->fast_set(this, kNextEnumerationIndexIndex, Smi::FromInt(index)); this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
} }
int NextEnumerationIndex() { int NextEnumerationIndex() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment