| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index c37a4a8b2086be48e881634f36f36acf034cc56c..57882a4d20a0f8f3a64c9919c39d94c86f64df30 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -487,20 +487,11 @@ MaybeObject* JSObject::SetNormalizedProperty(String* name,
|
| set_properties(StringDictionary::cast(dict));
|
| return value;
|
| }
|
| -
|
| - PropertyDetails original_details = property_dictionary()->DetailsAt(entry);
|
| - int enumeration_index;
|
| - // Preserve the enumeration index unless the property was deleted.
|
| - if (original_details.IsDeleted()) {
|
| - enumeration_index = property_dictionary()->NextEnumerationIndex();
|
| - property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1);
|
| - } else {
|
| - enumeration_index = original_details.dictionary_index();
|
| - ASSERT(enumeration_index > 0);
|
| - }
|
| -
|
| + // Preserve enumeration index.
|
| details = PropertyDetails(
|
| - details.attributes(), details.type(), enumeration_index);
|
| + details.attributes(),
|
| + details.type(),
|
| + property_dictionary()->DetailsAt(entry).dictionary_index());
|
|
|
| if (IsGlobalObject()) {
|
| JSGlobalPropertyCell* cell =
|
| @@ -651,9 +642,11 @@ MaybeObject* Object::GetProperty(Object* receiver,
|
| receiver, result->GetCallbackObject(), name);
|
| case HANDLER:
|
| return result->proxy()->GetPropertyWithHandler(receiver, name);
|
| - case INTERCEPTOR:
|
| + case INTERCEPTOR: {
|
| + JSObject* recvr = JSObject::cast(receiver);
|
| return result->holder()->GetPropertyWithInterceptor(
|
| - receiver, name, attributes);
|
| + recvr, name, attributes);
|
| + }
|
| case TRANSITION:
|
| case NONEXISTENT:
|
| UNREACHABLE();
|
| @@ -1539,9 +1532,8 @@ MaybeObject* JSObject::AddFastProperty(String* name,
|
| PropertyAttributes attributes,
|
| StoreFromKeyed store_mode) {
|
| ASSERT(!IsJSGlobalProxy());
|
| - ASSERT(DescriptorArray::kNotFound ==
|
| - map()->instance_descriptors()->Search(
|
| - name, map()->NumberOfOwnDescriptors()));
|
| + ASSERT(map()->instance_descriptors()->Search(name) ==
|
| + DescriptorArray::kNotFound);
|
|
|
| // Normalize the object if the name is an actual string (not the
|
| // hidden symbols) and is not a real identifier.
|
| @@ -1690,7 +1682,7 @@ MaybeObject* JSObject::AddProperty(String* name,
|
| }
|
| if (HasFastProperties()) {
|
| // Ensure the descriptor array does not get too big.
|
| - if (map_of_this->NumberOfOwnDescriptors() <
|
| + if (map_of_this->instance_descriptors()->number_of_descriptors() <
|
| DescriptorArray::kMaxNumberOfDescriptors) {
|
| if (value->IsJSFunction()) {
|
| return AddConstantFunctionProperty(name,
|
| @@ -1761,36 +1753,8 @@ MaybeObject* JSObject::ConvertTransitionToMapTransition(
|
| Object* new_value,
|
| PropertyAttributes attributes) {
|
| Map* old_map = map();
|
| - Map* old_target = old_map->GetTransition(transition_index);
|
| Object* result;
|
|
|
| - // To sever a transition to a map with which the descriptors are shared, the
|
| - // larger map (more descriptors) needs to store its own descriptors array.
|
| - // Both sides of the severed chain need to have their own descriptors pointer
|
| - // to store distinct descriptor arrays.
|
| -
|
| - // If the old_target did not yet store its own descriptors, the new
|
| - // descriptors pointer is created for the old_target by temporarily clearing
|
| - // the back pointer and setting its descriptor array. The ownership of the
|
| - // descriptor array is returned to the smaller maps by installing a reduced
|
| - // copy of the descriptor array in the old_map.
|
| -
|
| - // This phase is executed before creating the new map since it requires
|
| - // allocation that may fail.
|
| - if (!old_target->StoresOwnDescriptors()) {
|
| - DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
| -
|
| - old_target->SetBackPointer(GetHeap()->undefined_value());
|
| - MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors);
|
| - // Reset the backpointer before returning failure, otherwise the map ends up
|
| - // with an undefined backpointer and no descriptors, losing its own
|
| - // descriptors. Setting the backpointer always succeeds.
|
| - old_target->SetBackPointer(old_map);
|
| - if (maybe_failure->IsFailure()) return maybe_failure;
|
| -
|
| - old_map->set_owns_descriptors(true);
|
| - }
|
| -
|
| MaybeObject* maybe_result =
|
| ConvertDescriptorToField(name, new_value, attributes);
|
| if (!maybe_result->To(&result)) return maybe_result;
|
| @@ -1799,60 +1763,13 @@ MaybeObject* JSObject::ConvertTransitionToMapTransition(
|
|
|
| // This method should only be used to convert existing transitions. Objects
|
| // with the map of "new Object()" cannot have transitions in the first place.
|
| - Map* new_map = map();
|
| - ASSERT(new_map != GetIsolate()->empty_object_map());
|
| + ASSERT(map() != GetIsolate()->empty_object_map());
|
|
|
| // TODO(verwaest): From here on we lose existing map transitions, causing
|
| // invalid back pointers. This will change once we can store multiple
|
| // transitions with the same key.
|
| -
|
| - if (old_map->owns_descriptors()) {
|
| - // If the old map owns its own descriptors, transfer ownership to the
|
| - // new_map and install its descriptors in the old_map. Since the old_map
|
| - // stores the descriptors for the new_map, remove the transition array of
|
| - // the new_map that is only in place to store the descriptors.
|
| - old_map->transitions()->descriptors_pointer()->set_value(
|
| - new_map->instance_descriptors());
|
| - new_map->ClearTransitions(GetHeap());
|
| - old_map->set_owns_descriptors(false);
|
| - Map* map;
|
| - JSGlobalPropertyCell* pointer =
|
| - old_map->transitions()->descriptors_pointer();
|
| - for (Object* current = old_map;
|
| - !current->IsUndefined();
|
| - current = map->GetBackPointer()) {
|
| - map = Map::cast(current);
|
| - if (!map->HasTransitionArray()) break;
|
| - TransitionArray* transitions = map->transitions();
|
| - if (transitions->descriptors_pointer() != pointer) break;
|
| - map->SetEnumLength(Map::kInvalidEnumCache);
|
| - }
|
| - } else if (old_target->instance_descriptors() ==
|
| - old_map->instance_descriptors()) {
|
| - // Since the conversion above generated a new fast map with an additional
|
| - // property which can be shared as well, install this descriptor pointer
|
| - // along the entire chain of smaller maps; and remove the transition array
|
| - // that is only in place to hold the descriptor array in the new map.
|
| - Map* map;
|
| - JSGlobalPropertyCell* new_pointer =
|
| - new_map->transitions()->descriptors_pointer();
|
| - JSGlobalPropertyCell* old_pointer =
|
| - old_map->transitions()->descriptors_pointer();
|
| - for (Object* current = old_map;
|
| - !current->IsUndefined();
|
| - current = map->GetBackPointer()) {
|
| - map = Map::cast(current);
|
| - if (!map->HasTransitionArray()) break;
|
| - TransitionArray* transitions = map->transitions();
|
| - if (transitions->descriptors_pointer() != old_pointer) break;
|
| - map->SetEnumLength(Map::kInvalidEnumCache);
|
| - transitions->set_descriptors_pointer(new_pointer);
|
| - }
|
| - new_map->ClearTransitions(GetHeap());
|
| - }
|
| -
|
| - old_map->SetTransition(transition_index, new_map);
|
| - new_map->SetBackPointer(old_map);
|
| + old_map->SetTransition(transition_index, map());
|
| + map()->SetBackPointer(old_map);
|
| return result;
|
| }
|
|
|
| @@ -2176,13 +2093,11 @@ enum RightTrimMode { FROM_GC, FROM_MUTATOR };
|
| static void ZapEndOfFixedArray(Address new_end, int to_trim) {
|
| // If we are doing a big trim in old space then we zap the space.
|
| Object** zap = reinterpret_cast<Object**>(new_end);
|
| - zap++; // Header of filler must be at least one word so skip that.
|
| for (int i = 1; i < to_trim; i++) {
|
| *zap++ = Smi::FromInt(0);
|
| }
|
| }
|
|
|
| -
|
| template<RightTrimMode trim_mode>
|
| static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
|
| ASSERT(elms->map() != HEAP->fixed_cow_array_map());
|
| @@ -2223,31 +2138,13 @@ static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
|
| }
|
|
|
|
|
| -void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
|
| - 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) {
|
| +void Map::CopyAppendCallbackDescriptors(Handle<Map> map,
|
| + Handle<Object> descriptors) {
|
| Isolate* isolate = map->GetIsolate();
|
| Handle<DescriptorArray> array(map->instance_descriptors());
|
| - NeanderArray callbacks(descriptors);
|
| + v8::NeanderArray callbacks(descriptors);
|
| int nof_callbacks = callbacks.length();
|
| -
|
| - ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
|
| + int descriptor_count = array->number_of_descriptors();
|
|
|
| // 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
|
| @@ -2260,7 +2157,23 @@ void Map::AppendCallbackDescriptors(Handle<Map> map,
|
| entry->set_name(*key);
|
| }
|
|
|
| - int nof = map->NumberOfOwnDescriptors();
|
| + Handle<DescriptorArray> result =
|
| + 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.
|
| + if (0 < descriptor_count) {
|
| + 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
|
| // back to front so that the last callback with a given name takes
|
| @@ -2269,14 +2182,26 @@ void Map::AppendCallbackDescriptors(Handle<Map> map,
|
| AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
|
| String* key = String::cast(entry->name());
|
| // Check if a descriptor with this name already exists before writing.
|
| - if (array->Search(key, nof) == DescriptorArray::kNotFound) {
|
| + if (LinearSearch(*result, key, map->NumberOfOwnDescriptors()) ==
|
| + DescriptorArray::kNotFound) {
|
| CallbacksDescriptor desc(key, entry, entry->property_attributes());
|
| - array->Append(&desc);
|
| - nof += 1;
|
| + map->AppendDescriptor(&desc, witness);
|
| }
|
| }
|
|
|
| - map->SetNumberOfOwnDescriptors(nof);
|
| + int new_number_of_descriptors = map->NumberOfOwnDescriptors();
|
| + // Reinstall the original descriptor array if no new elements were added.
|
| + if (new_number_of_descriptors == 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(new_number_of_descriptors);
|
| + if (new_array_size < result->length()) {
|
| + RightTrimFixedArray<FROM_MUTATOR>(
|
| + isolate->heap(), *result, result->length() - new_array_size);
|
| + }
|
| }
|
|
|
|
|
| @@ -3339,19 +3264,19 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
|
| Map* map_of_this = map();
|
|
|
| // Allocate new content.
|
| - int real_size = map_of_this->NumberOfOwnDescriptors();
|
| - int property_count = real_size;
|
| + int property_count = map_of_this->NumberOfDescribedProperties();
|
| if (expected_additional_properties > 0) {
|
| property_count += expected_additional_properties;
|
| } else {
|
| property_count += 2; // Make space for two more properties.
|
| }
|
| StringDictionary* dictionary;
|
| - MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
|
| - if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
|
| + { MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
|
| + if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
|
| + }
|
|
|
| DescriptorArray* descs = map_of_this->instance_descriptors();
|
| - for (int i = 0; i < real_size; i++) {
|
| + for (int i = 0; i < descs->number_of_descriptors(); i++) {
|
| PropertyDetails details = descs->GetDetails(i);
|
| switch (details.type()) {
|
| case CONSTANT_FUNCTION: {
|
| @@ -3396,7 +3321,8 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
|
| Heap* current_heap = GetHeap();
|
|
|
| // Copy the next enumeration index from instance descriptor.
|
| - dictionary->SetNextEnumerationIndex(real_size + 1);
|
| + int index = map_of_this->instance_descriptors()->NextEnumerationIndex();
|
| + dictionary->SetNextEnumerationIndex(index);
|
|
|
| Map* new_map;
|
| MaybeObject* maybe_map =
|
| @@ -3742,11 +3668,10 @@ MaybeObject* JSObject::GetHiddenPropertiesHashTable(
|
| DescriptorArray* descriptors = this->map()->instance_descriptors();
|
| if (descriptors->number_of_descriptors() > 0) {
|
| int sorted_index = descriptors->GetSortedKeyIndex(0);
|
| - if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() &&
|
| - sorted_index < map()->NumberOfOwnDescriptors()) {
|
| + if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) {
|
| ASSERT(descriptors->GetType(sorted_index) == FIELD);
|
| - inline_value =
|
| - this->FastPropertyAt(descriptors->GetFieldIndex(sorted_index));
|
| + inline_value = this->FastPropertyAt(
|
| + descriptors->GetFieldIndex(sorted_index));
|
| } else {
|
| inline_value = GetHeap()->undefined_value();
|
| }
|
| @@ -3811,8 +3736,7 @@ MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) {
|
| DescriptorArray* descriptors = this->map()->instance_descriptors();
|
| if (descriptors->number_of_descriptors() > 0) {
|
| int sorted_index = descriptors->GetSortedKeyIndex(0);
|
| - if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol() &&
|
| - sorted_index < map()->NumberOfOwnDescriptors()) {
|
| + if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) {
|
| ASSERT(descriptors->GetType(sorted_index) == FIELD);
|
| this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
|
| value);
|
| @@ -4254,15 +4178,14 @@ void Map::SetDescriptors(Handle<Map> map,
|
| }
|
|
|
|
|
| -int Map::NumberOfDescribedProperties(DescriptorFlag which,
|
| - PropertyAttributes filter) {
|
| +int Map::NumberOfDescribedProperties(PropertyAttributes filter) {
|
| int result = 0;
|
| DescriptorArray* descs = instance_descriptors();
|
| - int limit = which == ALL_DESCRIPTORS
|
| - ? descs->number_of_descriptors()
|
| - : NumberOfOwnDescriptors();
|
| - for (int i = 0; i < limit; i++) {
|
| - if ((descs->GetDetails(i).attributes() & filter) == 0) result++;
|
| + for (int i = 0; i < descs->number_of_descriptors(); i++) {
|
| + PropertyDetails details = descs->GetDetails(i);
|
| + if ((details.attributes() & filter) == 0) {
|
| + result++;
|
| + }
|
| }
|
| return result;
|
| }
|
| @@ -4270,8 +4193,7 @@ int Map::NumberOfDescribedProperties(DescriptorFlag which,
|
|
|
| int Map::PropertyIndexFor(String* name) {
|
| DescriptorArray* descs = instance_descriptors();
|
| - int limit = NumberOfOwnDescriptors();
|
| - for (int i = 0; i < limit; i++) {
|
| + for (int i = 0; i < descs->number_of_descriptors(); i++) {
|
| if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i);
|
| }
|
| return -1;
|
| @@ -4280,9 +4202,8 @@ int Map::PropertyIndexFor(String* name) {
|
|
|
| int Map::NextFreePropertyIndex() {
|
| int max_index = -1;
|
| - int number_of_own_descriptors = NumberOfOwnDescriptors();
|
| DescriptorArray* descs = instance_descriptors();
|
| - for (int i = 0; i < number_of_own_descriptors; i++) {
|
| + for (int i = 0; i < descs->number_of_descriptors(); i++) {
|
| if (descs->GetType(i) == FIELD) {
|
| int current_index = descs->GetFieldIndex(i);
|
| if (current_index > max_index) max_index = current_index;
|
| @@ -4294,9 +4215,8 @@ int Map::NextFreePropertyIndex() {
|
|
|
| AccessorDescriptor* Map::FindAccessor(String* name) {
|
| DescriptorArray* descs = instance_descriptors();
|
| - int number_of_own_descriptors = NumberOfOwnDescriptors();
|
| - for (int i = 0; i < number_of_own_descriptors; i++) {
|
| - if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
|
| + for (int i = 0; i < descs->number_of_descriptors(); i++) {
|
| + if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
|
| return descs->GetCallbacks(i);
|
| }
|
| }
|
| @@ -4720,10 +4640,9 @@ MaybeObject* JSObject::DefineFastAccessor(String* name,
|
|
|
| if (result.IsFound()) {
|
| Map* target = result.GetTransitionTarget();
|
| - ASSERT(target->NumberOfOwnDescriptors() ==
|
| - map()->NumberOfOwnDescriptors());
|
| - // This works since descriptors are sorted in order of addition.
|
| - ASSERT(map()->instance_descriptors()->GetKey(descriptor_number) == name);
|
| + ASSERT(target->instance_descriptors()->number_of_descriptors() ==
|
| + map()->instance_descriptors()->number_of_descriptors());
|
| + ASSERT(target->instance_descriptors()->GetKey(descriptor_number) == name);
|
| return TryAccessorTransition(
|
| this, target, descriptor_number, component, accessor, attributes);
|
| }
|
| @@ -4906,9 +4825,8 @@ Object* JSObject::LookupAccessor(String* name, AccessorComponent component) {
|
|
|
| Object* JSObject::SlowReverseLookup(Object* value) {
|
| if (HasFastProperties()) {
|
| - int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
|
| DescriptorArray* descs = map()->instance_descriptors();
|
| - for (int i = 0; i < number_of_own_descriptors; i++) {
|
| + for (int i = 0; i < descs->number_of_descriptors(); i++) {
|
| if (descs->GetType(i) == FIELD) {
|
| if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
|
| return descs->GetKey(i);
|
| @@ -4937,11 +4855,8 @@ MaybeObject* Map::RawCopy(int instance_size) {
|
| result->set_bit_field(bit_field());
|
| result->set_bit_field2(bit_field2());
|
| result->set_bit_field3(bit_field3());
|
| - int new_bit_field3 = bit_field3();
|
| - new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
|
| - new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
|
| - new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
|
| - result->set_bit_field3(new_bit_field3);
|
| + result->SetNumberOfOwnDescriptors(0);
|
| + result->SetEnumLength(kInvalidEnumCache);
|
| return result;
|
| }
|
|
|
| @@ -4991,82 +4906,14 @@ MaybeObject* Map::CopyDropDescriptors() {
|
| }
|
|
|
|
|
| -MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) {
|
| - // Sanity check. This path is only to be taken if the map owns its descriptor
|
| - // array, implying that its NumberOfOwnDescriptors equals the number of
|
| - // descriptors in the descriptor array.
|
| - ASSERT(NumberOfOwnDescriptors() ==
|
| - instance_descriptors()->number_of_descriptors());
|
| - Map* result;
|
| - MaybeObject* maybe_result = CopyDropDescriptors();
|
| - if (!maybe_result->To(&result)) return maybe_result;
|
| -
|
| - String* name = descriptor->GetKey();
|
| -
|
| - TransitionArray* transitions;
|
| - MaybeObject* maybe_transitions =
|
| - AddTransition(name, result, SIMPLE_TRANSITION);
|
| - if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
| -
|
| - DescriptorArray* descriptors = instance_descriptors();
|
| - int old_size = descriptors->number_of_descriptors();
|
| -
|
| - DescriptorArray* new_descriptors;
|
| -
|
| - if (descriptors->NumberOfSlackDescriptors() > 0) {
|
| - new_descriptors = descriptors;
|
| - new_descriptors->Append(descriptor);
|
| - } 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
|
| - // 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
|
| - // enumerated descriptors than available in the original cache, the cache
|
| - // will be lazily replaced by the extended cache when needed.
|
| - if (descriptors->HasEnumCache()) {
|
| - new_descriptors->CopyEnumCacheFrom(descriptors);
|
| - }
|
| - }
|
| -
|
| - transitions->set_descriptors(new_descriptors);
|
| -
|
| - set_transitions(transitions);
|
| - result->SetBackPointer(this);
|
| - set_owns_descriptors(false);
|
| -
|
| - result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors());
|
| - ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
|
| -
|
| - return result;
|
| -}
|
| -
|
| -
|
| MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
| String* name,
|
| - TransitionFlag flag,
|
| - int descriptor_index) {
|
| - ASSERT(descriptors->IsSortedNoDuplicates());
|
| -
|
| + TransitionFlag flag) {
|
| Map* result;
|
| MaybeObject* maybe_result = CopyDropDescriptors();
|
| if (!maybe_result->To(&result)) return maybe_result;
|
|
|
| - // Unless we are creating a map with no descriptors and no back pointer, we
|
| - // insert the descriptor array locally.
|
| - if (!descriptors->IsEmpty()) {
|
| + if (descriptors->number_of_descriptors() != 0) {
|
| MaybeObject* maybe_failure = result->SetDescriptors(descriptors);
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
| result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors());
|
| @@ -5074,30 +4921,9 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
|
|
| if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
|
| TransitionArray* transitions;
|
| - SimpleTransitionFlag simple_flag =
|
| - (descriptor_index == descriptors->number_of_descriptors() - 1)
|
| - ? SIMPLE_TRANSITION
|
| - : FULL_TRANSITION;
|
| - MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
|
| + MaybeObject* maybe_transitions = AddTransition(name, result);
|
| if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
|
|
| - if (descriptors->IsEmpty()) {
|
| - if (owns_descriptors()) {
|
| - // If the copied map has no added fields, and the parent map owns its
|
| - // descriptors, those descriptors have to be empty. In that case,
|
| - // transfer ownership of the descriptors to the new child.
|
| - ASSERT(instance_descriptors()->IsEmpty());
|
| - set_owns_descriptors(false);
|
| - } else {
|
| - // If the parent did not own its own descriptors, it may share a larger
|
| - // descriptors array already. In that case, force a split by setting
|
| - // the descriptor array of the new map to the empty descriptor array.
|
| - MaybeObject* maybe_failure =
|
| - result->SetDescriptors(GetHeap()->empty_descriptor_array());
|
| - if (maybe_failure->IsFailure()) return maybe_failure;
|
| - }
|
| - }
|
| -
|
| set_transitions(transitions);
|
| result->SetBackPointer(this);
|
| }
|
| @@ -5107,6 +4933,12 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
|
|
|
|
| MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
|
| + // Create a new free-floating map only if we are not allowed to store it.
|
| + Map* new_map = NULL;
|
| + MaybeObject* maybe_new_map = Copy();
|
| + if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| + new_map->set_elements_kind(kind);
|
| +
|
| if (flag == INSERT_TRANSITION) {
|
| ASSERT(!HasElementsTransition() ||
|
| ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
|
| @@ -5117,49 +4949,10 @@ MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
|
| ASSERT(!IsFastElementsKind(kind) ||
|
| IsMoreGeneralElementsKindTransition(elements_kind(), kind));
|
| ASSERT(kind != elements_kind());
|
| - }
|
| -
|
| - if (flag == INSERT_TRANSITION && owns_descriptors()) {
|
| - // In case the map owned its own descriptors, share the descriptors and
|
| - // transfer ownership to the new map.
|
| - Map* new_map;
|
| - MaybeObject* maybe_new_map = CopyDropDescriptors();
|
| - if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
|
|
| MaybeObject* added_elements = set_elements_transition_map(new_map);
|
| if (added_elements->IsFailure()) return added_elements;
|
|
|
| - new_map->set_elements_kind(kind);
|
| - new_map->SetBackPointer(this);
|
| - new_map->SetNumberOfOwnDescriptors(NumberOfOwnDescriptors());
|
| - set_owns_descriptors(false);
|
| - return new_map;
|
| - }
|
| -
|
| - // In case the map did not own its own descriptors, a split is forced by
|
| - // copying the map; creating a new descriptor array cell.
|
| - // Create a new free-floating map only if we are not allowed to store it.
|
| - Map* new_map;
|
| - MaybeObject* maybe_new_map = Copy();
|
| - if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| - ASSERT(new_map->NumberOfOwnDescriptors() == NumberOfOwnDescriptors());
|
| - new_map->set_elements_kind(kind);
|
| -
|
| - if (flag == INSERT_TRANSITION) {
|
| - // Map::Copy does not store the descriptor array in case it is empty, since
|
| - // it does not insert a back pointer; implicitly indicating that its
|
| - // descriptor array is empty. Since in this case we do want to insert a back
|
| - // pointer, we have to manually set the empty descriptor array to force a
|
| - // split.
|
| - if (!new_map->StoresOwnDescriptors()) {
|
| - ASSERT(new_map->NumberOfOwnDescriptors() == 0);
|
| - MaybeObject* maybe_failure =
|
| - new_map->SetDescriptors(GetHeap()->empty_descriptor_array());
|
| - if (maybe_failure->IsFailure()) return maybe_failure;
|
| - }
|
| - MaybeObject* added_elements = set_elements_transition_map(new_map);
|
| - if (added_elements->IsFailure()) return added_elements;
|
| -
|
| new_map->SetBackPointer(this);
|
| }
|
|
|
| @@ -5177,25 +4970,13 @@ MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
|
| Map* map = ctor->initial_map();
|
| DescriptorArray* descriptors = map->instance_descriptors();
|
|
|
| - int number_of_own_descriptors = map->NumberOfOwnDescriptors();
|
| - DescriptorArray* new_descriptors;
|
| - MaybeObject* maybe_descriptors =
|
| - descriptors->CopyUpTo(number_of_own_descriptors);
|
| - if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
| -
|
| - return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
|
| + return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION);
|
| }
|
|
|
|
|
| MaybeObject* Map::Copy() {
|
| DescriptorArray* descriptors = instance_descriptors();
|
| - DescriptorArray* new_descriptors;
|
| - int number_of_own_descriptors = NumberOfOwnDescriptors();
|
| - MaybeObject* maybe_descriptors =
|
| - descriptors->CopyUpTo(number_of_own_descriptors);
|
| - if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
| -
|
| - return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
|
| + return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION);
|
| }
|
|
|
|
|
| @@ -5207,39 +4988,28 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
|
| MaybeObject* maybe_failure = descriptor->KeyToSymbol();
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
|
|
| - int old_size = NumberOfOwnDescriptors();
|
| - int new_size = old_size + 1;
|
| - descriptor->SetEnumerationIndex(new_size);
|
| + String* key = descriptor->GetKey();
|
| + ASSERT(descriptors->Search(key) == DescriptorArray::kNotFound);
|
|
|
| - if (flag == INSERT_TRANSITION &&
|
| - owns_descriptors() &&
|
| - CanHaveMoreTransitions()) {
|
| - return ShareDescriptor(descriptor);
|
| - }
|
| + int old_size = descriptors->number_of_descriptors();
|
| + int new_size = old_size + 1;
|
|
|
| DescriptorArray* new_descriptors;
|
| - MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1);
|
| + MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
|
| if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
|
|
| - DescriptorArray::WhitenessWitness witness(new_descriptors);
|
| + FixedArray::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);
|
| }
|
|
|
| - if (old_size != descriptors->number_of_descriptors()) {
|
| - new_descriptors->SetNumberOfDescriptors(new_size);
|
| - new_descriptors->Set(old_size, descriptor, witness);
|
| - new_descriptors->Sort();
|
| - } else {
|
| - new_descriptors->Append(descriptor, witness);
|
| - }
|
| + new_descriptors->Append(descriptor, witness, old_size);
|
|
|
| - String* key = descriptor->GetKey();
|
| - int insertion_index = new_descriptors->number_of_descriptors() - 1;
|
| + SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
|
|
|
| - return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
|
| + return CopyReplaceDescriptors(new_descriptors, key, flag);
|
| }
|
|
|
|
|
| @@ -5252,7 +5022,7 @@ MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
|
| if (maybe_result->IsFailure()) return maybe_result;
|
|
|
| // We replace the key if it is already present.
|
| - int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this);
|
| + int index = old_descriptors->SearchWithCache(descriptor->GetKey());
|
| if (index != DescriptorArray::kNotFound) {
|
| return CopyReplaceDescriptor(descriptor, index, flag);
|
| }
|
| @@ -5260,62 +5030,41 @@ MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
|
| }
|
|
|
|
|
| -MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) {
|
| - if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
|
| -
|
| - int size = enumeration_index;
|
| -
|
| - DescriptorArray* descriptors;
|
| - MaybeObject* maybe_descriptors = Allocate(size);
|
| - if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
|
| - DescriptorArray::WhitenessWitness witness(descriptors);
|
| -
|
| - for (int i = 0; i < size; ++i) {
|
| - descriptors->CopyFrom(i, this, i, witness);
|
| - }
|
| -
|
| - if (number_of_descriptors() != enumeration_index) descriptors->Sort();
|
| -
|
| - return descriptors;
|
| -}
|
| -
|
| -
|
| MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor,
|
| int insertion_index,
|
| TransitionFlag flag) {
|
| + DescriptorArray* descriptors = instance_descriptors();
|
| + int size = descriptors->number_of_descriptors();
|
| + ASSERT(0 <= insertion_index && insertion_index < size);
|
| +
|
| // Ensure the key is a symbol.
|
| MaybeObject* maybe_failure = descriptor->KeyToSymbol();
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
|
|
| - DescriptorArray* descriptors = instance_descriptors();
|
| -
|
| String* key = descriptor->GetKey();
|
| ASSERT(key == descriptors->GetKey(insertion_index));
|
|
|
| - int new_size = NumberOfOwnDescriptors();
|
| - ASSERT(0 <= insertion_index && insertion_index < new_size);
|
| -
|
| - PropertyDetails details = descriptors->GetDetails(insertion_index);
|
| - ASSERT_LE(details.descriptor_index(), new_size);
|
| - descriptor->SetEnumerationIndex(details.descriptor_index());
|
| -
|
| DescriptorArray* new_descriptors;
|
| - MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
|
| + MaybeObject* maybe_descriptors = DescriptorArray::Allocate(size);
|
| if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
| - DescriptorArray::WhitenessWitness witness(new_descriptors);
|
|
|
| - for (int i = 0; i < new_size; ++i) {
|
| - if (i == insertion_index) {
|
| - new_descriptors->Set(i, descriptor, witness);
|
| - } else {
|
| - new_descriptors->CopyFrom(i, descriptors, i, witness);
|
| - }
|
| + FixedArray::WhitenessWitness witness(new_descriptors);
|
| +
|
| + // Copy the descriptors, replacing a descriptor.
|
| + for (int index = 0; index < size; ++index) {
|
| + if (index == insertion_index) continue;
|
| + new_descriptors->CopyFrom(index, descriptors, index, witness);
|
| }
|
|
|
| - // Re-sort if descriptors were removed.
|
| - if (new_size != descriptors->length()) new_descriptors->Sort();
|
| + PropertyDetails original_details = descriptors->GetDetails(insertion_index);
|
| + descriptor->SetEnumerationIndex(original_details.descriptor_index());
|
| + descriptor->SetSortedKey(original_details.pointer());
|
| +
|
| + new_descriptors->Set(insertion_index, descriptor, witness);
|
| +
|
| + SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
|
|
|
| - return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
|
| + return CopyReplaceDescriptors(new_descriptors, key, flag);
|
| }
|
|
|
|
|
| @@ -6090,40 +5839,33 @@ bool FixedArray::IsEqualTo(FixedArray* other) {
|
| #endif
|
|
|
|
|
| -MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, int slack) {
|
| +MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
|
| Heap* heap = Isolate::Current()->heap();
|
| // Do not use DescriptorArray::cast on incomplete object.
|
| - int size = number_of_descriptors + slack;
|
| - if (size == 0) return heap->empty_descriptor_array();
|
| FixedArray* result;
|
| + if (number_of_descriptors == 0) return heap->empty_descriptor_array();
|
| // Allocate the array of keys.
|
| - MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size));
|
| + MaybeObject* maybe_array =
|
| + heap->AllocateFixedArray(LengthFor(number_of_descriptors));
|
| if (!maybe_array->To(&result)) return maybe_array;
|
|
|
| - result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
|
| result->set(kEnumCacheIndex, Smi::FromInt(0));
|
| return result;
|
| }
|
|
|
|
|
| -void DescriptorArray::ClearEnumCache() {
|
| - set(kEnumCacheIndex, Smi::FromInt(0));
|
| -}
|
| -
|
| -
|
| void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
|
| FixedArray* new_cache,
|
| Object* new_index_cache) {
|
| ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
|
| ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
|
| if (HasEnumCache()) {
|
| - ASSERT(new_cache->length() > GetEnumCache()->length());
|
| FixedArray::cast(get(kEnumCacheIndex))->
|
| set(kEnumCacheBridgeCacheIndex, new_cache);
|
| FixedArray::cast(get(kEnumCacheIndex))->
|
| set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
|
| } else {
|
| - ASSERT(!IsEmpty());
|
| + if (IsEmpty()) return; // Do nothing for empty descriptor array.
|
| FixedArray::cast(bridge_storage)->
|
| set(kEnumCacheBridgeCacheIndex, new_cache);
|
| FixedArray::cast(bridge_storage)->
|
| @@ -6199,7 +5941,6 @@ void DescriptorArray::Sort() {
|
| parent_index = child_index;
|
| }
|
| }
|
| - ASSERT(IsSortedNoDuplicates());
|
| }
|
|
|
|
|
| @@ -7390,6 +7131,7 @@ void StringHasher::AddSurrogatePairNoIndex(uc32 c) {
|
|
|
|
|
| uint32_t StringHasher::GetHashField() {
|
| + ASSERT(is_valid());
|
| if (length_ <= String::kMaxHashCalcLength) {
|
| if (is_array_index()) {
|
| return MakeArrayIndexHash(array_index(), length_);
|
| @@ -7446,58 +7188,15 @@ void String::PrintOn(FILE* file) {
|
|
|
| // Clear a possible back pointer in case the transition leads to a dead map.
|
| // Return true in case a back pointer has been cleared and false otherwise.
|
| -static bool ClearBackPointer(Heap* heap, Map* target) {
|
| - if (Marking::MarkBitFrom(target).Get()) return false;
|
| - target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
|
| +static bool ClearBackPointer(Heap* heap, Object* target) {
|
| + ASSERT(target->IsMap());
|
| + Map* map = Map::cast(target);
|
| + if (Marking::MarkBitFrom(map).Get()) return false;
|
| + map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
|
| return true;
|
| }
|
|
|
|
|
| -static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) {
|
| - int live_enum = map->EnumLength();
|
| - if (live_enum == Map::kInvalidEnumCache) {
|
| - live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
|
| - }
|
| - if (live_enum == 0) return descriptors->ClearEnumCache();
|
| -
|
| - FixedArray* enum_cache = descriptors->GetEnumCache();
|
| -
|
| - int to_trim = enum_cache->length() - live_enum;
|
| - if (to_trim <= 0) return;
|
| - RightTrimFixedArray<FROM_GC>(heap, descriptors->GetEnumCache(), to_trim);
|
| -
|
| - if (!descriptors->HasEnumIndicesCache()) return;
|
| - FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache();
|
| - RightTrimFixedArray<FROM_GC>(heap, enum_indices_cache, to_trim);
|
| -}
|
| -
|
| -
|
| -static void TrimDescriptorArray(Heap* heap,
|
| - Map* map,
|
| - DescriptorArray* descriptors,
|
| - int number_of_own_descriptors) {
|
| - int number_of_descriptors = descriptors->number_of_descriptors();
|
| - int to_trim = number_of_descriptors - number_of_own_descriptors;
|
| - if (to_trim <= 0) return;
|
| -
|
| - // Maximally keep 50% of unused descriptors.
|
| - 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()) TrimEnumCache(heap, map, descriptors);
|
| - descriptors->Sort();
|
| -}
|
| -
|
| -
|
| // TODO(mstarzinger): This method should be moved into MarkCompactCollector,
|
| // because it cannot be called from outside the GC and we already have methods
|
| // depending on the transitions layout in the GC anyways.
|
| @@ -7512,21 +7211,9 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
|
|
|
| int transition_index = 0;
|
|
|
| - DescriptorArray* descriptors = t->descriptors();
|
| - bool descriptors_owner_died = false;
|
| -
|
| // Compact all live descriptors to the left.
|
| for (int i = 0; i < t->number_of_transitions(); ++i) {
|
| - Map* target = t->GetTarget(i);
|
| - if (ClearBackPointer(heap, target)) {
|
| - ASSERT(!Marking::IsGrey(Marking::MarkBitFrom(target)));
|
| - DescriptorArray* target_descriptors = target->instance_descriptors();
|
| - if ((target_descriptors->number_of_descriptors() == 0 &&
|
| - target->NumberOfOwnDescriptors() > 0) ||
|
| - target_descriptors == descriptors) {
|
| - descriptors_owner_died = true;
|
| - }
|
| - } else {
|
| + if (!ClearBackPointer(heap, t->GetTarget(i))) {
|
| if (i != transition_index) {
|
| String* key = t->GetKey(i);
|
| t->SetKey(transition_index, key);
|
| @@ -7541,9 +7228,6 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
|
|
|
| if (t->HasElementsTransition() &&
|
| ClearBackPointer(heap, t->elements_transition())) {
|
| - if (t->elements_transition()->instance_descriptors() == descriptors) {
|
| - descriptors_owner_died = true;
|
| - }
|
| t->ClearElementsTransition();
|
| } else {
|
| // If there are no transitions to be cleared, return.
|
| @@ -7552,32 +7236,19 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
|
| if (transition_index == t->number_of_transitions()) return;
|
| }
|
|
|
| - int number_of_own_descriptors = NumberOfOwnDescriptors();
|
| -
|
| - if (descriptors_owner_died) {
|
| - if (number_of_own_descriptors > 0) {
|
| - TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors);
|
| - ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
|
| - } else {
|
| - t->set_descriptors(heap->empty_descriptor_array());
|
| - }
|
| - set_owns_descriptors(true);
|
| - }
|
| -
|
| // If the final transition array does not contain any live transitions, remove
|
| // the transition array from the map.
|
| if (transition_index == 0 &&
|
| !t->HasElementsTransition() &&
|
| !t->HasPrototypeTransitions() &&
|
| - number_of_own_descriptors == 0) {
|
| - ASSERT(owns_descriptors());
|
| + t->descriptors()->IsEmpty()) {
|
| return ClearTransitions(heap);
|
| }
|
|
|
| int trim = t->number_of_transitions() - transition_index;
|
| if (trim > 0) {
|
| - RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition()
|
| - ? trim : trim * TransitionArray::kTransitionSize);
|
| + RightTrimFixedArray<FROM_GC>(
|
| + heap, t, trim * TransitionArray::kTransitionSize);
|
| }
|
| }
|
|
|
| @@ -10524,7 +10195,7 @@ InterceptorInfo* JSObject::GetIndexedInterceptor() {
|
|
|
|
|
| MaybeObject* JSObject::GetPropertyPostInterceptor(
|
| - Object* receiver,
|
| + JSReceiver* receiver,
|
| String* name,
|
| PropertyAttributes* attributes) {
|
| // Check local property in holder, ignore interceptor.
|
| @@ -10542,7 +10213,7 @@ MaybeObject* JSObject::GetPropertyPostInterceptor(
|
|
|
|
|
| MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
|
| - Object* receiver,
|
| + JSReceiver* receiver,
|
| String* name,
|
| PropertyAttributes* attributes) {
|
| // Check local property in holder, ignore interceptor.
|
| @@ -10556,13 +10227,13 @@ MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
|
|
|
|
|
| MaybeObject* JSObject::GetPropertyWithInterceptor(
|
| - Object* receiver,
|
| + JSReceiver* receiver,
|
| String* name,
|
| PropertyAttributes* attributes) {
|
| Isolate* isolate = GetIsolate();
|
| InterceptorInfo* interceptor = GetNamedInterceptor();
|
| HandleScope scope(isolate);
|
| - Handle<Object> receiver_handle(receiver);
|
| + Handle<JSReceiver> receiver_handle(receiver);
|
| Handle<JSObject> holder_handle(this);
|
| Handle<String> name_handle(name);
|
|
|
| @@ -10694,16 +10365,9 @@ bool JSObject::HasRealNamedCallbackProperty(String* key) {
|
|
|
|
|
| int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
|
| - if (HasFastProperties()) {
|
| - Map* map = this->map();
|
| - if (filter == NONE) return map->NumberOfOwnDescriptors();
|
| - if (filter == DONT_ENUM) {
|
| - int result = map->EnumLength();
|
| - if (result != Map::kInvalidEnumCache) return result;
|
| - }
|
| - return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
|
| - }
|
| - return property_dictionary()->NumberOfElementsFilterAttributes(filter);
|
| + return HasFastProperties() ?
|
| + map()->NumberOfDescribedProperties(filter) :
|
| + property_dictionary()->NumberOfElementsFilterAttributes(filter);
|
| }
|
|
|
|
|
| @@ -10826,10 +10490,9 @@ void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
|
| void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
|
| ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
|
| if (HasFastProperties()) {
|
| - int real_size = map()->NumberOfOwnDescriptors();
|
| DescriptorArray* descs = map()->instance_descriptors();
|
| - ASSERT(storage->length() >= index + real_size);
|
| - for (int i = 0; i < real_size; i++) {
|
| + ASSERT(storage->length() >= index + descs->number_of_descriptors());
|
| + for (int i = 0; i < descs->number_of_descriptors(); i++) {
|
| storage->set(index + i, descs->GetKey(i));
|
| }
|
| } else {
|
| @@ -12532,8 +12195,8 @@ MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
|
| int pos = 0;
|
| for (int i = 0; i < capacity; i++) {
|
| if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
|
| - int index = DetailsAt(i).dictionary_index();
|
| - enumeration_order->set(pos++, Smi::FromInt(index));
|
| + enumeration_order->set(
|
| + pos++, Smi::FromInt(DetailsAt(i).dictionary_index()));
|
| }
|
| }
|
|
|
| @@ -12662,8 +12325,7 @@ MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key,
|
| uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
|
| // Insert element at empty or deleted entry
|
| if (!details.IsDeleted() &&
|
| - details.dictionary_index() == 0 &&
|
| - Shape::kIsEnumerable) {
|
| + details.dictionary_index() == 0 && Shape::kIsEnumerable) {
|
| // Assign an enumeration index to the property and update
|
| // SetNextEnumerationIndex.
|
| int index = NextEnumerationIndex();
|
| @@ -12969,7 +12631,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
|
| return maybe_descriptors;
|
| }
|
|
|
| - DescriptorArray::WhitenessWitness witness(descriptors);
|
| + FixedArray::WhitenessWitness witness(descriptors);
|
|
|
| int number_of_allocated_fields =
|
| number_of_fields + unused_property_fields - inobject_props;
|
|
|