Commit 5bf15c5d authored by verwaest@chromium.org's avatar verwaest@chromium.org

Preallocate space in descriptor arrays.

Review URL: https://chromiumcodereview.appspot.com/10916336

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12538 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4d485a43
...@@ -384,7 +384,7 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target, ...@@ -384,7 +384,7 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
void Genesis::SetFunctionInstanceDescriptor( void Genesis::SetFunctionInstanceDescriptor(
Handle<Map> map, PrototypePropertyMode prototypeMode) { Handle<Map> map, PrototypePropertyMode prototypeMode) {
int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5; int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
Handle<DescriptorArray> descriptors(factory()->NewDescriptorArray(size)); Handle<DescriptorArray> descriptors(factory()->NewDescriptorArray(0, size));
DescriptorArray::WhitenessWitness witness(*descriptors); DescriptorArray::WhitenessWitness witness(*descriptors);
Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength)); Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
...@@ -525,7 +525,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) { ...@@ -525,7 +525,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
void Genesis::SetStrictFunctionInstanceDescriptor( void Genesis::SetStrictFunctionInstanceDescriptor(
Handle<Map> map, PrototypePropertyMode prototypeMode) { Handle<Map> map, PrototypePropertyMode prototypeMode) {
int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5; int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
Handle<DescriptorArray> descriptors(factory()->NewDescriptorArray(size)); Handle<DescriptorArray> descriptors(factory()->NewDescriptorArray(0, size));
DescriptorArray::WhitenessWitness witness(*descriptors); DescriptorArray::WhitenessWitness witness(*descriptors);
Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength)); Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
...@@ -868,7 +868,8 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -868,7 +868,8 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
array_function->shared()->set_length(1); array_function->shared()->set_length(1);
Handle<Map> initial_map(array_function->initial_map()); Handle<Map> initial_map(array_function->initial_map());
Handle<DescriptorArray> array_descriptors(factory->NewDescriptorArray(1)); Handle<DescriptorArray> array_descriptors(
factory->NewDescriptorArray(0, 1));
DescriptorArray::WhitenessWitness witness(*array_descriptors); DescriptorArray::WhitenessWitness witness(*array_descriptors);
Handle<Foreign> array_length(factory->NewForeign(&Accessors::ArrayLength)); Handle<Foreign> array_length(factory->NewForeign(&Accessors::ArrayLength));
...@@ -915,7 +916,8 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -915,7 +916,8 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
Handle<Map> string_map = Handle<Map> string_map =
Handle<Map>(native_context()->string_function()->initial_map()); Handle<Map>(native_context()->string_function()->initial_map());
Handle<DescriptorArray> string_descriptors(factory->NewDescriptorArray(1)); Handle<DescriptorArray> string_descriptors(
factory->NewDescriptorArray(0, 1));
DescriptorArray::WhitenessWitness witness(*string_descriptors); DescriptorArray::WhitenessWitness witness(*string_descriptors);
Handle<Foreign> string_length( Handle<Foreign> string_length(
...@@ -956,7 +958,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -956,7 +958,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
PropertyAttributes final = PropertyAttributes final =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(5); Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(0, 5);
DescriptorArray::WhitenessWitness witness(*descriptors); DescriptorArray::WhitenessWitness witness(*descriptors);
Map::SetDescriptors(initial_map, descriptors); Map::SetDescriptors(initial_map, descriptors);
...@@ -1140,7 +1142,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, ...@@ -1140,7 +1142,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE,
Heap::kArgumentsObjectSizeStrict); Heap::kArgumentsObjectSizeStrict);
// 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(0, 3);
DescriptorArray::WhitenessWitness witness(*descriptors); DescriptorArray::WhitenessWitness witness(*descriptors);
Map::SetDescriptors(map, descriptors); Map::SetDescriptors(map, descriptors);
...@@ -1487,7 +1489,7 @@ bool Genesis::InstallNatives() { ...@@ -1487,7 +1489,7 @@ bool Genesis::InstallNatives() {
Handle<Map> script_map = Handle<Map>(script_fun->initial_map()); Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
Handle<DescriptorArray> script_descriptors( Handle<DescriptorArray> script_descriptors(
factory()->NewDescriptorArray(13)); factory()->NewDescriptorArray(0, 13));
DescriptorArray::WhitenessWitness witness(*script_descriptors); DescriptorArray::WhitenessWitness witness(*script_descriptors);
Handle<Foreign> script_source( Handle<Foreign> script_source(
...@@ -1665,7 +1667,8 @@ bool Genesis::InstallNatives() { ...@@ -1665,7 +1667,8 @@ bool Genesis::InstallNatives() {
// Make "length" magic on instances. // Make "length" magic on instances.
Handle<Map> initial_map(array_function->initial_map()); Handle<Map> initial_map(array_function->initial_map());
Handle<DescriptorArray> array_descriptors(factory()->NewDescriptorArray(1)); Handle<DescriptorArray> array_descriptors(
factory()->NewDescriptorArray(0, 1));
DescriptorArray::WhitenessWitness witness(*array_descriptors); DescriptorArray::WhitenessWitness witness(*array_descriptors);
Handle<Foreign> array_length(factory()->NewForeign( Handle<Foreign> array_length(factory()->NewForeign(
...@@ -1765,7 +1768,7 @@ bool Genesis::InstallNatives() { ...@@ -1765,7 +1768,7 @@ bool Genesis::InstallNatives() {
// Update map with length accessor from Array and add "index" and "input". // Update map with length accessor from Array and add "index" and "input".
Handle<DescriptorArray> reresult_descriptors = Handle<DescriptorArray> reresult_descriptors =
factory()->NewDescriptorArray(3); factory()->NewDescriptorArray(0, 3);
DescriptorArray::WhitenessWitness witness(*reresult_descriptors); DescriptorArray::WhitenessWitness witness(*reresult_descriptors);
Map::SetDescriptors(initial_map, reresult_descriptors); Map::SetDescriptors(initial_map, reresult_descriptors);
......
...@@ -112,10 +112,11 @@ Handle<ObjectHashTable> Factory::NewObjectHashTable(int at_least_space_for) { ...@@ -112,10 +112,11 @@ Handle<ObjectHashTable> Factory::NewObjectHashTable(int at_least_space_for) {
} }
Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors) { Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors,
int slack) {
ASSERT(0 <= number_of_descriptors); ASSERT(0 <= number_of_descriptors);
CALL_HEAP_FUNCTION(isolate(), CALL_HEAP_FUNCTION(isolate(),
DescriptorArray::Allocate(number_of_descriptors), DescriptorArray::Allocate(number_of_descriptors, slack),
DescriptorArray); DescriptorArray);
} }
...@@ -1284,10 +1285,26 @@ Handle<JSFunction> Factory::CreateApiFunction( ...@@ -1284,10 +1285,26 @@ Handle<JSFunction> Factory::CreateApiFunction(
result->shared()->DontAdaptArguments(); result->shared()->DontAdaptArguments();
// Recursively copy parent templates' accessors, 'data' may be modified. // Recursively copy parent templates' accessors, 'data' may be modified.
int max_number_of_additional_properties = 0;
FunctionTemplateInfo* info = *obj;
while (true) {
Object* props = info->property_accessors();
if (!props->IsUndefined()) {
Handle<Object> props_handle(props);
NeanderArray props_array(props_handle);
max_number_of_additional_properties += props_array.length();
}
Object* parent = info->parent_template();
if (parent->IsUndefined()) break;
info = FunctionTemplateInfo::cast(parent);
}
Map::EnsureDescriptorSlack(map, max_number_of_additional_properties);
while (true) { while (true) {
Handle<Object> props = Handle<Object>(obj->property_accessors()); Handle<Object> props = Handle<Object>(obj->property_accessors());
if (!props->IsUndefined()) { if (!props->IsUndefined()) {
Map::CopyAppendCallbackDescriptors(map, props); Map::AppendCallbackDescriptors(map, props);
} }
Handle<Object> parent = Handle<Object>(obj->parent_template()); Handle<Object> parent = Handle<Object>(obj->parent_template());
if (parent->IsUndefined()) break; if (parent->IsUndefined()) break;
......
...@@ -66,7 +66,8 @@ class Factory { ...@@ -66,7 +66,8 @@ class Factory {
Handle<ObjectHashTable> NewObjectHashTable(int at_least_space_for); Handle<ObjectHashTable> NewObjectHashTable(int at_least_space_for);
Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors); Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors,
int slack = 0);
Handle<DeoptimizationInputData> NewDeoptimizationInputData( Handle<DeoptimizationInputData> NewDeoptimizationInputData(
int deopt_entry_count, int deopt_entry_count,
PretenureFlag pretenure); PretenureFlag pretenure);
......
...@@ -905,7 +905,7 @@ bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) { ...@@ -905,7 +905,7 @@ bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) {
if (valid_entries == -1) valid_entries = number_of_descriptors(); if (valid_entries == -1) valid_entries = number_of_descriptors();
String* current_key = NULL; String* current_key = NULL;
uint32_t current = 0; uint32_t current = 0;
for (int i = 0; i < valid_entries; i++) { for (int i = 0; i < number_of_descriptors(); i++) {
String* key = GetSortedKey(i); String* key = GetSortedKey(i);
if (key == current_key) { if (key == current_key) {
PrintDescriptors(); PrintDescriptors();
......
...@@ -1906,6 +1906,12 @@ bool DescriptorArray::IsEmpty() { ...@@ -1906,6 +1906,12 @@ bool DescriptorArray::IsEmpty() {
} }
void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
WRITE_FIELD(
this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors));
}
// Perform a binary search in a fixed array. Low and high are entry indices. If // Perform a binary search in a fixed array. Low and high are entry indices. If
// there are three entries in this array it should be called with low=0 and // there are three entries in this array it should be called with low=0 and
// high=2. // high=2.
...@@ -2138,11 +2144,30 @@ void DescriptorArray::Set(int descriptor_number, ...@@ -2138,11 +2144,30 @@ void DescriptorArray::Set(int descriptor_number,
} }
void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
// Range check.
ASSERT(descriptor_number < number_of_descriptors());
ASSERT(desc->GetDetails().descriptor_index() <=
number_of_descriptors());
ASSERT(desc->GetDetails().descriptor_index() > 0);
set(ToKeyIndex(descriptor_number), desc->GetKey());
set(ToValueIndex(descriptor_number), desc->GetValue());
set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi());
}
void DescriptorArray::EraseDescriptor(Heap* heap, int descriptor_number) {
set_null_unchecked(heap, ToKeyIndex(descriptor_number));
set_null_unchecked(heap, ToValueIndex(descriptor_number));
}
void DescriptorArray::Append(Descriptor* desc, void DescriptorArray::Append(Descriptor* desc,
const WhitenessWitness& witness, const WhitenessWitness& witness) {
int number_of_set_descriptors) { int descriptor_number = number_of_descriptors();
int descriptor_number = number_of_set_descriptors;
int enumeration_index = descriptor_number + 1; int enumeration_index = descriptor_number + 1;
SetNumberOfDescriptors(descriptor_number + 1);
desc->SetEnumerationIndex(enumeration_index); desc->SetEnumerationIndex(enumeration_index);
Set(descriptor_number, desc, witness); Set(descriptor_number, desc, witness);
...@@ -2160,6 +2185,27 @@ void DescriptorArray::Append(Descriptor* desc, ...@@ -2160,6 +2185,27 @@ void DescriptorArray::Append(Descriptor* desc,
} }
void DescriptorArray::Append(Descriptor* desc) {
int descriptor_number = number_of_descriptors();
int enumeration_index = descriptor_number + 1;
SetNumberOfDescriptors(descriptor_number + 1);
desc->SetEnumerationIndex(enumeration_index);
Set(descriptor_number, desc);
uint32_t hash = desc->GetKey()->Hash();
int insertion;
for (insertion = descriptor_number; insertion > 0; --insertion) {
String* key = GetSortedKey(insertion - 1);
if (key->Hash() <= hash) break;
SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
}
SetSortedKey(insertion, descriptor_number);
}
void DescriptorArray::SwapSortedKeys(int first, int second) { void DescriptorArray::SwapSortedKeys(int first, int second) {
int first_key = GetSortedKeyIndex(first); int first_key = GetSortedKeyIndex(first);
SetSortedKey(first, GetSortedKeyIndex(second)); SetSortedKey(first, GetSortedKeyIndex(second));
...@@ -3591,8 +3637,8 @@ void Map::AppendDescriptor(Descriptor* desc, ...@@ -3591,8 +3637,8 @@ void Map::AppendDescriptor(Descriptor* desc,
const DescriptorArray::WhitenessWitness& witness) { const DescriptorArray::WhitenessWitness& witness) {
DescriptorArray* descriptors = instance_descriptors(); DescriptorArray* descriptors = instance_descriptors();
int number_of_own_descriptors = NumberOfOwnDescriptors(); int number_of_own_descriptors = NumberOfOwnDescriptors();
ASSERT(number_of_own_descriptors < descriptors->number_of_descriptors()); ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
descriptors->Append(desc, witness, number_of_own_descriptors); descriptors->Append(desc, witness);
SetNumberOfOwnDescriptors(number_of_own_descriptors + 1); SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
} }
......
...@@ -2218,14 +2218,31 @@ static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) { ...@@ -2218,14 +2218,31 @@ static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
} }
void Map::CopyAppendCallbackDescriptors(Handle<Map> map, void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
Handle<Object> descriptors) { Handle<DescriptorArray> descriptors(map->instance_descriptors());
if (slack <= descriptors->NumberOfSlackDescriptors()) return;
int number_of_descriptors = descriptors->number_of_descriptors();
Isolate* isolate = map->GetIsolate();
Handle<DescriptorArray> new_descriptors =
isolate->factory()->NewDescriptorArray(number_of_descriptors, slack);
DescriptorArray::WhitenessWitness witness(*new_descriptors);
for (int i = 0; i < number_of_descriptors; ++i) {
new_descriptors->CopyFrom(i, *descriptors, i, witness);
}
Map::SetDescriptors(map, new_descriptors);
}
void Map::AppendCallbackDescriptors(Handle<Map> map,
Handle<Object> descriptors) {
Isolate* isolate = map->GetIsolate(); Isolate* isolate = map->GetIsolate();
Handle<DescriptorArray> array(map->instance_descriptors()); Handle<DescriptorArray> array(map->instance_descriptors());
v8::NeanderArray callbacks(descriptors); NeanderArray callbacks(descriptors);
int nof_callbacks = callbacks.length(); int nof_callbacks = callbacks.length();
int descriptor_count = array->number_of_descriptors();
ASSERT(descriptor_count == map->NumberOfOwnDescriptors()); ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
// Ensure the keys are symbols before writing them into the instance // Ensure the keys are symbols before writing them into the instance
// descriptor. Since it may cause a GC, it has to be done before we // descriptor. Since it may cause a GC, it has to be done before we
...@@ -2238,51 +2255,23 @@ void Map::CopyAppendCallbackDescriptors(Handle<Map> map, ...@@ -2238,51 +2255,23 @@ void Map::CopyAppendCallbackDescriptors(Handle<Map> map,
entry->set_name(*key); entry->set_name(*key);
} }
Handle<DescriptorArray> result = int nof = map->NumberOfOwnDescriptors();
isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks);
// 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 < descriptor_count; i++) {
result->CopyFrom(i, *array, i, witness);
}
// After this point the GC is not allowed to run anymore until the map is in a
// consistent state again, i.e., all the descriptors are appended and the
// descriptor array is trimmed to the right size.
Map::SetDescriptors(map, result);
// Fill in new callback descriptors. Process the callbacks from // Fill in new callback descriptors. Process the callbacks from
// back to front so that the last callback with a given name takes // back to front so that the last callback with a given name takes
// precedence over previously added callbacks with that name. // precedence over previously added callbacks with that name.
int nof = descriptor_count;
for (int i = nof_callbacks - 1; i >= 0; i--) { for (int i = nof_callbacks - 1; i >= 0; i--) {
AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
String* key = String::cast(entry->name()); String* key = String::cast(entry->name());
// Check if a descriptor with this name already exists before writing. // Check if a descriptor with this name already exists before writing.
if (result->Search(key, nof) == DescriptorArray::kNotFound) { if (array->Search(key, nof) == DescriptorArray::kNotFound) {
CallbacksDescriptor desc(key, entry, entry->property_attributes()); CallbacksDescriptor desc(key, entry, entry->property_attributes());
map->AppendDescriptor(&desc, witness); array->Append(&desc);
nof += 1; nof += 1;
} }
} }
ASSERT(nof == map->NumberOfOwnDescriptors()); map->SetNumberOfOwnDescriptors(nof);
// Reinstall the original descriptor array if no new elements were added.
if (nof == descriptor_count) {
Map::SetDescriptors(map, array);
return;
}
// If duplicates were detected, trim the descriptor array to the right size.
int new_array_size = DescriptorArray::LengthFor(nof);
if (new_array_size < result->length()) {
RightTrimFixedArray<FROM_MUTATOR>(
isolate->heap(), *result, result->length() - new_array_size);
}
} }
...@@ -5018,25 +5007,37 @@ MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) { ...@@ -5018,25 +5007,37 @@ MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
int old_size = descriptors->number_of_descriptors(); int old_size = descriptors->number_of_descriptors();
DescriptorArray* new_descriptors; DescriptorArray* new_descriptors;
MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1);
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
DescriptorArray::WhitenessWitness witness(new_descriptors);
for (int i = 0; i < old_size; ++i) { if (descriptors->NumberOfSlackDescriptors() > 0) {
new_descriptors->CopyFrom(i, descriptors, i, witness); new_descriptors = descriptors;
} new_descriptors->Append(descriptor);
new_descriptors->Append(descriptor, witness, old_size); } else {
// Descriptor arrays grow by 50%.
MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
old_size, old_size < 4 ? 1 : old_size / 2);
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
DescriptorArray::WhitenessWitness witness(new_descriptors);
// Copy the descriptors, inserting a descriptor.
for (int i = 0; i < old_size; ++i) {
new_descriptors->CopyFrom(i, descriptors, i, witness);
}
new_descriptors->Append(descriptor, witness);
// If the source descriptors had an enum cache we copy it. This ensures that // If the source descriptors had an enum cache we copy it. This ensures that
// the maps to which we push the new descriptor array back can rely on a // the maps to which we push the new descriptor array back can rely on a
// cache always being available once it is set. If the map has more // cache always being available once it is set. If the map has more
// enumerated descriptors than available in the original cache, the cache // enumerated descriptors than available in the original cache, the cache
// will be lazily replaced by the extended cache when needed. // will be lazily replaced by the extended cache when needed.
if (descriptors->HasEnumCache()) { if (descriptors->HasEnumCache()) {
new_descriptors->CopyEnumCacheFrom(descriptors); new_descriptors->CopyEnumCacheFrom(descriptors);
}
} }
transitions->set_descriptors(new_descriptors); transitions->set_descriptors(new_descriptors);
set_transitions(transitions); set_transitions(transitions);
result->SetBackPointer(this); result->SetBackPointer(this);
set_owns_descriptors(false); set_owns_descriptors(false);
...@@ -5207,7 +5208,7 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, ...@@ -5207,7 +5208,7 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
} }
DescriptorArray* new_descriptors; DescriptorArray* new_descriptors;
MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1); MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1);
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
DescriptorArray::WhitenessWitness witness(new_descriptors); DescriptorArray::WhitenessWitness witness(new_descriptors);
...@@ -5217,10 +5218,17 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, ...@@ -5217,10 +5218,17 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
new_descriptors->CopyFrom(i, descriptors, i, witness); new_descriptors->CopyFrom(i, descriptors, i, witness);
} }
new_descriptors->Set(old_size, descriptor, witness); if (old_size != descriptors->number_of_descriptors()) {
new_descriptors->Sort(); new_descriptors->SetNumberOfDescriptors(new_size);
new_descriptors->Set(old_size, descriptor, witness);
new_descriptors->Sort();
} else {
new_descriptors->Append(descriptor, witness);
}
return CopyReplaceDescriptors(new_descriptors, descriptor->GetKey(), flag); String* key = descriptor->GetKey();
return CopyReplaceDescriptors(new_descriptors, key, flag);
} }
...@@ -6071,16 +6079,17 @@ bool FixedArray::IsEqualTo(FixedArray* other) { ...@@ -6071,16 +6079,17 @@ bool FixedArray::IsEqualTo(FixedArray* other) {
#endif #endif
MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, int slack) {
Heap* heap = Isolate::Current()->heap(); Heap* heap = Isolate::Current()->heap();
// Do not use DescriptorArray::cast on incomplete object. // Do not use DescriptorArray::cast on incomplete object.
int size = number_of_descriptors + slack;
if (size == 0) return heap->empty_descriptor_array();
FixedArray* result; FixedArray* result;
if (number_of_descriptors == 0) return heap->empty_descriptor_array();
// Allocate the array of keys. // Allocate the array of keys.
MaybeObject* maybe_array = MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size));
heap->AllocateFixedArray(LengthFor(number_of_descriptors));
if (!maybe_array->To(&result)) return maybe_array; if (!maybe_array->To(&result)) return maybe_array;
result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
result->set(kEnumCacheIndex, Smi::FromInt(0)); result->set(kEnumCacheIndex, Smi::FromInt(0));
return result; return result;
} }
...@@ -7495,8 +7504,17 @@ void Map::ClearNonLiveTransitions(Heap* heap) { ...@@ -7495,8 +7504,17 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
int number_of_descriptors = descriptors->number_of_descriptors(); int number_of_descriptors = descriptors->number_of_descriptors();
int to_trim = number_of_descriptors - number_of_own_descriptors; int to_trim = number_of_descriptors - number_of_own_descriptors;
if (to_trim > 0) { if (to_trim > 0) {
RightTrimFixedArray<FROM_GC>( // Maximally keep 50% of unused descriptors.
heap, descriptors, to_trim * DescriptorArray::kDescriptorSize); int keep = Min(to_trim, number_of_own_descriptors / 2);
for (int i = number_of_own_descriptors;
i < number_of_own_descriptors + keep;
++i) {
descriptors->EraseDescriptor(heap, i);
}
if (to_trim > keep) {
RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim - keep);
}
descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
if (descriptors->HasEnumCache()) { if (descriptors->HasEnumCache()) {
int live_enum = int live_enum =
NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
......
...@@ -2484,9 +2484,19 @@ class DescriptorArray: public FixedArray { ...@@ -2484,9 +2484,19 @@ class DescriptorArray: public FixedArray {
int number_of_descriptors() { int number_of_descriptors() {
ASSERT(length() >= kFirstIndex || IsEmpty()); ASSERT(length() >= kFirstIndex || IsEmpty());
int len = length(); int len = length();
return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kDescriptorSize; return len == 0 ? 0 : Smi::cast(get(kDescriptorLengthIndex))->value();
} }
int number_of_descriptors_storage() {
int len = length();
return len == 0 ? 0 : (len - kFirstIndex) / kDescriptorSize;
}
int NumberOfSlackDescriptors() {
return number_of_descriptors_storage() - number_of_descriptors();
}
inline void SetNumberOfDescriptors(int number_of_descriptors);
inline int number_of_entries() { return number_of_descriptors(); } inline int number_of_entries() { return number_of_descriptors(); }
bool HasEnumCache() { bool HasEnumCache() {
...@@ -2538,13 +2548,14 @@ class DescriptorArray: public FixedArray { ...@@ -2538,13 +2548,14 @@ class DescriptorArray: public FixedArray {
inline void Set(int descriptor_number, inline void Set(int descriptor_number,
Descriptor* desc, Descriptor* desc,
const WhitenessWitness&); const WhitenessWitness&);
inline void Set(int descriptor_number, Descriptor* desc);
inline void EraseDescriptor(Heap* heap, int descriptor_number);
// Append automatically sets the enumeration index. This should only be used // Append automatically sets the enumeration index. This should only be used
// to add descriptors in bulk at the end, followed by sorting the descriptor // to add descriptors in bulk at the end, followed by sorting the descriptor
// array. // array.
inline void Append(Descriptor* desc, inline void Append(Descriptor* desc, const WhitenessWitness&);
const WhitenessWitness&, inline void Append(Descriptor* desc);
int number_of_set_descriptors);
// Transfer a complete descriptor from the src descriptor array to this // Transfer a complete descriptor from the src descriptor array to this
// descriptor array. // descriptor array.
...@@ -2567,7 +2578,8 @@ class DescriptorArray: public FixedArray { ...@@ -2567,7 +2578,8 @@ class DescriptorArray: public FixedArray {
// Allocates a DescriptorArray, but returns the singleton // Allocates a DescriptorArray, but returns the singleton
// empty descriptor array object if number_of_descriptors is 0. // empty descriptor array object if number_of_descriptors is 0.
MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors); MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors,
int slack = 0);
// Casting. // Casting.
static inline DescriptorArray* cast(Object* obj); static inline DescriptorArray* cast(Object* obj);
...@@ -2575,8 +2587,9 @@ class DescriptorArray: public FixedArray { ...@@ -2575,8 +2587,9 @@ class DescriptorArray: public FixedArray {
// Constant for denoting key was not found. // Constant for denoting key was not found.
static const int kNotFound = -1; static const int kNotFound = -1;
static const int kEnumCacheIndex = 0; static const int kDescriptorLengthIndex = 0;
static const int kFirstIndex = 1; static const int kEnumCacheIndex = 1;
static const int kFirstIndex = 2;
// The length of the "bridge" to the enum cache. // The length of the "bridge" to the enum cache.
static const int kEnumCacheBridgeLength = 2; static const int kEnumCacheBridgeLength = 2;
...@@ -2584,7 +2597,8 @@ class DescriptorArray: public FixedArray { ...@@ -2584,7 +2597,8 @@ class DescriptorArray: public FixedArray {
static const int kEnumCacheBridgeIndicesCacheIndex = 1; static const int kEnumCacheBridgeIndicesCacheIndex = 1;
// Layout description. // Layout description.
static const int kEnumCacheOffset = FixedArray::kHeaderSize; static const int kDescriptorLengthOffset = FixedArray::kHeaderSize;
static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize;
static const int kFirstOffset = kEnumCacheOffset + kPointerSize; static const int kFirstOffset = kEnumCacheOffset + kPointerSize;
// Layout description for the bridge array. // Layout description for the bridge array.
...@@ -5011,8 +5025,10 @@ class Map: public HeapObject { ...@@ -5011,8 +5025,10 @@ class Map: public HeapObject {
// Extend the descriptor array of the map with the list of descriptors. // Extend the descriptor array of the map with the list of descriptors.
// In case of duplicates, the latest descriptor is used. // In case of duplicates, the latest descriptor is used.
static void CopyAppendCallbackDescriptors(Handle<Map> map, static void AppendCallbackDescriptors(Handle<Map> map,
Handle<Object> descriptors); Handle<Object> descriptors);
static void EnsureDescriptorSlack(Handle<Map> map, int slack);
// Returns the found code or undefined if absent. // Returns the found code or undefined if absent.
Object* FindInCodeCache(String* name, Code::Flags flags); Object* FindInCodeCache(String* name, Code::Flags flags);
......
...@@ -155,7 +155,7 @@ TEST(StressJS) { ...@@ -155,7 +155,7 @@ TEST(StressJS) {
FACTORY->NewStringFromAscii(Vector<const char>("get", 3)); FACTORY->NewStringFromAscii(Vector<const char>("get", 3));
ASSERT(instance_descriptors->IsEmpty()); ASSERT(instance_descriptors->IsEmpty());
Handle<DescriptorArray> new_descriptors = FACTORY->NewDescriptorArray(1); Handle<DescriptorArray> new_descriptors = FACTORY->NewDescriptorArray(0, 1);
v8::internal::DescriptorArray::WhitenessWitness witness(*new_descriptors); v8::internal::DescriptorArray::WhitenessWitness witness(*new_descriptors);
v8::internal::Map::SetDescriptors(map, new_descriptors); v8::internal::Map::SetDescriptors(map, new_descriptors);
......
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