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:
parent
666c4be29f
commit
af876ee474
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
10
src/heap.cc
10
src/heap.cc
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user