| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index de41ce1eb99781b7a1ad8a9745e03d393e0c37b0..1a3500c3abd7801b981117f2f9dea976263cd7d1 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -2859,18 +2859,11 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
|
| attributes,
|
| strict_mode);
|
| case TRANSITION: {
|
| - Object* transition = result->GetTransitionValue();
|
| + Map* transition_map = result->GetTransitionTarget();
|
|
|
| - if (transition->IsAccessorPair()) {
|
| - ASSERT(!AccessorPair::cast(transition)->ContainsAccessor());
|
| - return ConvertDescriptorToField(*name, *value, attributes);
|
| - }
|
| -
|
| - Map* transition_map = Map::cast(transition);
|
| DescriptorArray* descriptors = transition_map->instance_descriptors();
|
| int descriptor = descriptors->LastAdded();
|
| PropertyDetails details = descriptors->GetDetails(descriptor);
|
| - ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION);
|
|
|
| if (details.type() == FIELD) {
|
| if (attributes == details.attributes()) {
|
| @@ -2881,9 +2874,12 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
|
| field_index);
|
| }
|
| return self->ConvertDescriptorToField(*name, *value, attributes);
|
| + } else if (details.type() == CALLBACKS) {
|
| + return ConvertDescriptorToField(*name, *value, attributes);
|
| }
|
|
|
| - // Is transition to CONSTANT_FUNCTION.
|
| + ASSERT(details.type() == CONSTANT_FUNCTION);
|
| +
|
| Object* constant_function = descriptors->GetValue(descriptor);
|
| // If the same constant function is being added we can simply
|
| // transition to the target map.
|
| @@ -2983,18 +2979,11 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
|
| // Override callback in clone
|
| return ConvertDescriptorToField(name, value, attributes);
|
| case TRANSITION: {
|
| - Object* transition = result.GetTransitionValue();
|
| -
|
| - if (transition->IsAccessorPair()) {
|
| - ASSERT(!AccessorPair::cast(transition)->ContainsAccessor());
|
| - return ConvertDescriptorToField(name, value, attributes);
|
| - }
|
| + Map* transition_map = result.GetTransitionTarget();
|
|
|
| - Map* transition_map = Map::cast(transition);
|
| DescriptorArray* descriptors = transition_map->instance_descriptors();
|
| int descriptor = descriptors->LastAdded();
|
| PropertyDetails details = descriptors->GetDetails(descriptor);
|
| - ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION);
|
|
|
| if (details.type() == FIELD) {
|
| if (attributes == details.attributes()) {
|
| @@ -3005,10 +2994,14 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
|
| field_index);
|
| }
|
| return ConvertDescriptorToField(name, value, attributes);
|
| + } else if (details.type() == CALLBACKS) {
|
| + return ConvertDescriptorToField(name, value, attributes);
|
| }
|
|
|
| - // Was transition to CONSTANT_FUNCTION. Replace with a map transition to a
|
| - // new map with a FIELD, even if the value is a function.
|
| + ASSERT(details.type() == CONSTANT_FUNCTION);
|
| +
|
| + // Replace transition to CONSTANT FUNCTION with a map transition to a new
|
| + // map with a FIELD, even if the value is a function.
|
| return ConvertTransitionToMapTransition(
|
| result.GetTransitionIndex(), name, value, attributes);
|
| }
|
| @@ -3294,11 +3287,6 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
|
| }
|
| case CALLBACKS: {
|
| Object* value = descs->GetCallbacksObject(i);
|
| - if (value->IsAccessorPair()) {
|
| - MaybeObject* maybe_copy =
|
| - AccessorPair::cast(value)->CopyWithoutTransitions();
|
| - if (!maybe_copy->To(&value)) return maybe_copy;
|
| - }
|
| MaybeObject* maybe_dictionary =
|
| dictionary->Add(descs->GetKey(i), value, details);
|
| if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
|
| @@ -4231,7 +4219,7 @@ void JSObject::LookupCallback(String* name, LookupResult* result) {
|
| current != heap->null_value() && current->IsJSObject();
|
| current = JSObject::cast(current)->GetPrototype()) {
|
| JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
|
| - if (result->IsCallbacks()) return;
|
| + if (result->IsPropertyCallbacks()) return;
|
| }
|
| result->NotFound();
|
| }
|
| @@ -4343,7 +4331,7 @@ MaybeObject* JSObject::CreateAccessorPairFor(String* name) {
|
| // DefinePropertyAccessor below.
|
| Object* obj = result.GetCallbackObject();
|
| if (obj->IsAccessorPair()) {
|
| - return AccessorPair::cast(obj)->CopyWithoutTransitions();
|
| + return AccessorPair::cast(obj)->Copy();
|
| }
|
| }
|
| return GetHeap()->AllocateAccessorPair();
|
| @@ -4377,9 +4365,9 @@ MaybeObject* JSObject::DefinePropertyAccessor(String* name,
|
| }
|
|
|
| AccessorPair* accessors;
|
| - { MaybeObject* maybe_accessors = CreateAccessorPairFor(name);
|
| - if (!maybe_accessors->To(&accessors)) return maybe_accessors;
|
| - }
|
| + MaybeObject* maybe_accessors = CreateAccessorPairFor(name);
|
| + if (!maybe_accessors->To(&accessors)) return maybe_accessors;
|
| +
|
| accessors->SetComponents(getter, setter);
|
| return SetPropertyCallback(name, accessors, attributes);
|
| }
|
| @@ -4451,17 +4439,16 @@ MaybeObject* JSObject::SetPropertyCallback(String* name,
|
| Object* structure,
|
| PropertyAttributes attributes) {
|
| // Normalize object to make this operation simple.
|
| - { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
|
| - if (maybe_ok->IsFailure()) return maybe_ok;
|
| - }
|
| + MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
|
| + if (maybe_ok->IsFailure()) return maybe_ok;
|
|
|
| // For the global object allocate a new map to invalidate the global inline
|
| // caches which have a global property cell reference directly in the code.
|
| if (IsGlobalObject()) {
|
| Map* new_map;
|
| - { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
|
| - if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| - }
|
| + MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
|
| + if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| +
|
| set_map(new_map);
|
| // When running crankshaft, changing the map is not enough. We
|
| // need to deoptimize all functions that rely on this global
|
| @@ -4471,9 +4458,8 @@ MaybeObject* JSObject::SetPropertyCallback(String* name,
|
|
|
| // Update the dictionary with the new CALLBACKS property.
|
| PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
|
| - { MaybeObject* maybe_ok = SetNormalizedProperty(name, structure, details);
|
| - if (maybe_ok->IsFailure()) return maybe_ok;
|
| - }
|
| + maybe_ok = SetNormalizedProperty(name, structure, details);
|
| + if (maybe_ok->IsFailure()) return maybe_ok;
|
|
|
| return GetHeap()->undefined_value();
|
| }
|
| @@ -4525,73 +4511,32 @@ MaybeObject* JSObject::DefineAccessor(String* name,
|
| }
|
|
|
|
|
| -static MaybeObject* CreateFreshAccessor(JSObject* obj,
|
| - String* name,
|
| - AccessorComponent component,
|
| - Object* accessor,
|
| - PropertyAttributes attributes) {
|
| - // step 1: create a new getter/setter pair with only the accessor in it
|
| - Heap* heap = obj->GetHeap();
|
| - AccessorPair* accessors2;
|
| - { MaybeObject* maybe_accessors2 = heap->AllocateAccessorPair();
|
| - if (!maybe_accessors2->To(&accessors2)) return maybe_accessors2;
|
| - }
|
| - accessors2->set(component, accessor);
|
| -
|
| - // step 2: create a copy of the descriptors, incl. the new getter/setter pair
|
| - Map* map1 = obj->map();
|
| - CallbacksDescriptor callbacks_descr2(name, accessors2, attributes, 0);
|
| - DescriptorArray* descriptors2;
|
| - { MaybeObject* maybe_descriptors2 =
|
| - map1->instance_descriptors()->CopyAdd(&callbacks_descr2);
|
| - if (!maybe_descriptors2->To(&descriptors2)) return maybe_descriptors2;
|
| - }
|
| -
|
| - // step 3: create a new map with the new descriptors
|
| - Map* map2;
|
| - { MaybeObject* maybe_map2 = map1->CopyReplaceDescriptors(descriptors2);
|
| - if (!maybe_map2->To(&map2)) return maybe_map2;
|
| - }
|
| +static MaybeObject* TryAccessorTransition(JSObject* self,
|
| + Map* transitioned_map,
|
| + String* name,
|
| + AccessorComponent component,
|
| + Object* accessor,
|
| + PropertyAttributes attributes) {
|
| + DescriptorArray* descs = transitioned_map->instance_descriptors();
|
| + int number = descs->LastAdded();
|
| + PropertyDetails details = descs->GetDetails(number);
|
|
|
| - // step 4: create a new getter/setter pair with a transition to the new map
|
| - AccessorPair* accessors1;
|
| - { MaybeObject* maybe_accessors1 = heap->AllocateAccessorPair();
|
| - if (!maybe_accessors1->To(&accessors1)) return maybe_accessors1;
|
| - }
|
| - accessors1->set(component, map2);
|
| + // If the transition target was not callbacks, fall back to the slow case.
|
| + if (details.type() != CALLBACKS) return self->GetHeap()->null_value();
|
|
|
| - // step 5: create a copy of the descriptors, incl. the new getter/setter pair
|
| - // with the transition
|
| - TransitionArray* new_transitions;
|
| - { MaybeObject* maybe_new_transitions = map1->AddTransition(name, accessors1);
|
| - if (!maybe_new_transitions->To(&new_transitions)) {
|
| - return maybe_new_transitions;
|
| - }
|
| - }
|
| + Object* target_accessor =
|
| + AccessorPair::cast(descs->GetCallbacksObject(number))->get(component);
|
| + PropertyAttributes target_attributes = details.attributes();
|
|
|
| - // step 6: everything went well so far, so we make our changes visible
|
| - { MaybeObject* transition_added = map1->set_transitions(new_transitions);
|
| - if (transition_added->IsFailure()) return transition_added;
|
| + // Reuse transition if adding same accessor with same attributes.
|
| + if (target_accessor == accessor && target_attributes == attributes) {
|
| + self->set_map(transitioned_map);
|
| + return self;
|
| }
|
|
|
| - map2->SetBackPointer(map1);
|
| - obj->set_map(map2);
|
| - return obj;
|
| -}
|
| -
|
| -
|
| -static bool TransitionToSameAccessor(Object* map,
|
| - String* name,
|
| - AccessorComponent component,
|
| - Object* accessor,
|
| - PropertyAttributes attributes ) {
|
| - Map* transitioned_map = Map::cast(map);
|
| - DescriptorArray* descs = transitioned_map->instance_descriptors();
|
| - int number = descs->LastAdded();
|
| - Object* target_accessor =
|
| - AccessorPair::cast(descs->GetCallbacksObject(number))->get(component);
|
| - PropertyAttributes target_attributes = descs->GetDetails(number).attributes();
|
| - return target_accessor == accessor && target_attributes == attributes;
|
| + // If either not the same accessor, or not the same attributes, fall back to
|
| + // the slow case.
|
| + return self->GetHeap()->null_value();
|
| }
|
|
|
|
|
| @@ -4600,43 +4545,31 @@ static MaybeObject* NewCallbackTransition(JSObject* obj,
|
| AccessorComponent component,
|
| Object* accessor,
|
| PropertyAttributes attributes,
|
| - AccessorPair* accessors2) {
|
| - // step 1: copy the old getter/setter pair and set the new accessor
|
| - AccessorPair* accessors3;
|
| - { MaybeObject* maybe_accessors3 = accessors2->CopyWithoutTransitions();
|
| - if (!maybe_accessors3->To(&accessors3)) return maybe_accessors3;
|
| - }
|
| - accessors3->set(component, accessor);
|
| -
|
| - // step 2: create a copy of the descriptors, incl. the new getter/setter pair
|
| - Map* map2 = obj->map();
|
| - CallbacksDescriptor callbacks_descr3(name, accessors3, attributes, 0);
|
| - DescriptorArray* descriptors3;
|
| - { MaybeObject* maybe_descriptors3 =
|
| - map2->instance_descriptors()->CopyInsert(&callbacks_descr3);
|
| - if (!maybe_descriptors3->To(&descriptors3)) return maybe_descriptors3;
|
| - }
|
| + AccessorPair* new_accessors) {
|
| + // step 1: create a copy of the descriptors, incl. the new getter/setter pair
|
| + Map* old_map = obj->map();
|
| + CallbacksDescriptor new_accessors_desc(name, new_accessors, attributes);
|
| + DescriptorArray* descriptors;
|
| + MaybeObject* maybe_descriptors =
|
| + old_map->instance_descriptors()->CopyInsert(&new_accessors_desc);
|
| + if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
|
|
|
| - // step 3: create a new map with the new descriptors
|
| - Map* map3;
|
| - { MaybeObject* maybe_map3 = map2->CopyReplaceDescriptors(descriptors3);
|
| - if (!maybe_map3->To(&map3)) return maybe_map3;
|
| - }
|
| + // step 2: create a new map with the new descriptors
|
| + Map* new_map;
|
| + MaybeObject* maybe_new_map = old_map->CopyReplaceDescriptors(descriptors);
|
| + if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
|
|
| - // step 4: add a new transition to the new map
|
| - TransitionArray* new_transitions;
|
| - { MaybeObject* maybe_transitions = map2->AddTransition(name, accessors2);
|
| - if (!maybe_transitions->To(&new_transitions)) return maybe_transitions;
|
| - }
|
| + // step 3: add a new transition to the new map
|
| + TransitionArray* transitions;
|
| + MaybeObject* maybe_transitions = old_map->AddTransition(name, new_map);
|
| + if (!maybe_transitions->To(&transitions)) return maybe_transitions;
|
|
|
| - // step 5: everything went well so far, so we make our changes visible
|
| - { MaybeObject* transition_added = map2->set_transitions(new_transitions);
|
| - if (transition_added->IsFailure()) return transition_added;
|
| - }
|
| + // step 4: everything went well so far, so we make our changes visible
|
| + MaybeObject* transition_added = old_map->set_transitions(transitions);
|
| + if (transition_added->IsFailure()) return transition_added;
|
|
|
| - map3->SetBackPointer(map2);
|
| - obj->set_map(map3);
|
| - accessors2->set(component, map3);
|
| + new_map->SetBackPointer(old_map);
|
| + obj->set_map(new_map);
|
| return obj;
|
| }
|
|
|
| @@ -4649,40 +4582,54 @@ MaybeObject* JSObject::DefineFastAccessor(String* name,
|
| LookupResult result(GetIsolate());
|
| LocalLookup(name, &result);
|
|
|
| - // If we have a new property, create a fresh accessor plus a transition to it.
|
| - if (!result.IsFound()) {
|
| - return CreateFreshAccessor(this, name, component, accessor, attributes);
|
| - }
|
| + if (result.IsFound()
|
| + && !result.IsPropertyCallbacks()
|
| + && !result.IsTransition()) return GetHeap()->null_value();
|
|
|
| - // If the property is not a JavaScript accessor, fall back to the slow case.
|
| - if (!result.IsCallbacks()) return GetHeap()->null_value();
|
| + // Return success if the same accessor with the same attributes already exist.
|
| + AccessorPair* source_accessors = NULL;
|
| + if (result.IsPropertyCallbacks()) {
|
| + Object* callback_value = result.GetCallbackObject();
|
| + if (callback_value->IsAccessorPair()) {
|
| + source_accessors = AccessorPair::cast(callback_value);
|
| + Object* entry = source_accessors->get(component);
|
| + if (entry == accessor && result.GetAttributes() == attributes) {
|
| + return this;
|
| + }
|
| + }
|
| + }
|
|
|
| - Object* callback_value = result.GetCallbackObject();
|
| - if (!callback_value->IsAccessorPair()) return GetHeap()->null_value();
|
| - AccessorPair* accessors = AccessorPair::cast(callback_value);
|
| + // If not, lookup a transition.
|
| + map()->LookupTransition(this, name, &result);
|
|
|
| - // Follow a callback transition, if there is a fitting one.
|
| - Object* entry = accessors->get(component);
|
| - if (entry->IsMap() &&
|
| - TransitionToSameAccessor(entry, name, component, accessor, attributes)) {
|
| - set_map(Map::cast(entry));
|
| - return this;
|
| + // If there is a transition, try to follow it.
|
| + if (result.IsFound()) {
|
| + Map* target = result.GetTransitionTarget();
|
| + return TryAccessorTransition(
|
| + this, target, name, component, accessor, attributes);
|
| }
|
|
|
| - if (entry == accessor && result.GetAttributes() == attributes) return this;
|
| + // If there is no transition yet, add a transition to the a new accessor pair
|
| + // containing the accessor.
|
| + AccessorPair* accessors;
|
| + MaybeObject* maybe_accessors;
|
|
|
| - // Only the other accessor has been set so far, create a new transition.
|
| - if (entry->IsTheHole()) {
|
| - return NewCallbackTransition(this,
|
| - name,
|
| - component,
|
| - accessor,
|
| - attributes,
|
| - accessors);
|
| + // Allocate a new pair if there were no source accessors. Otherwise, copy the
|
| + // pair and modify the accessor.
|
| + if (source_accessors != NULL) {
|
| + maybe_accessors = source_accessors->Copy();
|
| + } else {
|
| + maybe_accessors = GetHeap()->AllocateAccessorPair();
|
| }
|
| + if (!maybe_accessors->To(&accessors)) return maybe_accessors;
|
| + accessors->set(component, accessor);
|
|
|
| - // Nothing from the above worked, so we have to fall back to the slow case.
|
| - return GetHeap()->null_value();
|
| + return NewCallbackTransition(this,
|
| + name,
|
| + component,
|
| + accessor,
|
| + attributes,
|
| + accessors);
|
| }
|
|
|
|
|
| @@ -5012,44 +4959,17 @@ class IntrusiveMapTransitionIterator {
|
|
|
| Map* Next() {
|
| ASSERT(IsIterating());
|
| - // Attention, tricky index manipulation ahead: Two consecutive indices are
|
| - // assigned to each descriptor. Most descriptors directly advance to the
|
| - // next descriptor by adding 2 to the index. The exceptions are the
|
| - // CALLBACKS entries: An even index means we look at its getter, and an odd
|
| - // index means we look at its setter.
|
| - int raw_index = Smi::cast(*TransitionArrayHeader())->value();
|
| - int index = raw_index / 2;
|
| + int index = Smi::cast(*TransitionArrayHeader())->value();
|
| int number_of_transitions = transition_array_->number_of_transitions();
|
| while (index < number_of_transitions) {
|
| - Object* value = transition_array_->GetValue(index);
|
| -
|
| - if (value->IsMap()) {
|
| - *TransitionArrayHeader() = Smi::FromInt(raw_index + 2);
|
| - return static_cast<Map*>(value);
|
| - }
|
| -
|
| - ASSERT(value->IsAccessorPair());
|
| -
|
| - // We might have a map transition in a getter or in a setter.
|
| - AccessorPair* accessors = static_cast<AccessorPair*>(value);
|
| - Object* accessor;
|
| - if ((raw_index & 1) == 0) {
|
| - accessor = accessors->setter();
|
| - } else {
|
| - ++index;
|
| - accessor = accessors->getter();
|
| - }
|
| - ++raw_index;
|
| - if (accessor->IsMap()) {
|
| - *TransitionArrayHeader() = Smi::FromInt(raw_index);
|
| - return static_cast<Map*>(accessor);
|
| - }
|
| + *TransitionArrayHeader() = Smi::FromInt(index + 1);
|
| + return transition_array_->GetTarget(index);
|
| }
|
|
|
| - if (index == transition_array_->number_of_transitions() &&
|
| + if (index == number_of_transitions &&
|
| transition_array_->HasElementsTransition()) {
|
| Map* elements_transition = transition_array_->elements_transition();
|
| - *TransitionArrayHeader() = Smi::FromInt(raw_index + 2);
|
| + *TransitionArrayHeader() = Smi::FromInt(index + 1);
|
| return elements_transition;
|
| }
|
| *TransitionArrayHeader() = transition_array_->GetHeap()->fixed_array_map();
|
| @@ -5786,30 +5706,14 @@ static bool InsertionPointFound(String* key1, String* key2) {
|
| }
|
|
|
|
|
| -void DescriptorArray::CopyFrom(Handle<DescriptorArray> dst,
|
| - int dst_index,
|
| - Handle<DescriptorArray> src,
|
| +void DescriptorArray::CopyFrom(int dst_index,
|
| + DescriptorArray* src,
|
| int src_index,
|
| const WhitenessWitness& witness) {
|
| - CALL_HEAP_FUNCTION_VOID(dst->GetIsolate(),
|
| - dst->CopyFrom(dst_index, *src, src_index, witness));
|
| -}
|
| -
|
| -
|
| -MaybeObject* DescriptorArray::CopyFrom(int dst_index,
|
| - DescriptorArray* src,
|
| - int src_index,
|
| - const WhitenessWitness& witness) {
|
| Object* value = src->GetValue(src_index);
|
| PropertyDetails details = src->GetDetails(src_index);
|
| - if (details.type() == CALLBACKS && value->IsAccessorPair()) {
|
| - MaybeObject* maybe_copy =
|
| - AccessorPair::cast(value)->CopyWithoutTransitions();
|
| - if (!maybe_copy->To(&value)) return maybe_copy;
|
| - }
|
| Descriptor desc(src->GetKey(src_index), value, details);
|
| Set(dst_index, &desc, witness);
|
| - return this;
|
| }
|
|
|
| MaybeObject* DescriptorArray::CopyReplace(Descriptor* descriptor,
|
| @@ -5833,9 +5737,7 @@ MaybeObject* DescriptorArray::CopyReplace(Descriptor* descriptor,
|
| // Copy the descriptors, replacing a descriptor.
|
| for (int index = 0; index < size; ++index) {
|
| if (index == insertion_index) continue;
|
| - MaybeObject* copy_result =
|
| - new_descriptors->CopyFrom(index, this, index, witness);
|
| - if (copy_result->IsFailure()) return copy_result;
|
| + new_descriptors->CopyFrom(index, this, index, witness);
|
| }
|
|
|
| descriptor->SetEnumerationIndex(GetDetails(insertion_index).index());
|
| @@ -5850,9 +5752,8 @@ MaybeObject* DescriptorArray::CopyReplace(Descriptor* descriptor,
|
|
|
| MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor) {
|
| // Ensure the key is a symbol.
|
| - { MaybeObject* maybe_result = descriptor->KeyToSymbol();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| - }
|
| + MaybeObject* maybe_result = descriptor->KeyToSymbol();
|
| + if (maybe_result->IsFailure()) return maybe_result;
|
|
|
| // We replace the key if it is already present.
|
| int index = SearchWithCache(descriptor->GetKey());
|
| @@ -5863,9 +5764,8 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor) {
|
|
|
| MaybeObject* DescriptorArray::CopyAdd(Descriptor* descriptor) {
|
| // Ensure the key is a symbol.
|
| - { MaybeObject* maybe_result = descriptor->KeyToSymbol();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| - }
|
| + MaybeObject* maybe_result = descriptor->KeyToSymbol();
|
| + if (maybe_result->IsFailure()) return maybe_result;
|
|
|
| String* key = descriptor->GetKey();
|
| ASSERT(Search(key) == kNotFound);
|
| @@ -5873,9 +5773,8 @@ MaybeObject* DescriptorArray::CopyAdd(Descriptor* descriptor) {
|
| int new_size = number_of_descriptors() + 1;
|
|
|
| DescriptorArray* new_descriptors;
|
| - { MaybeObject* maybe_result = Allocate(new_size, MAY_BE_SHARED);
|
| - if (!maybe_result->To(&new_descriptors)) return maybe_result;
|
| - }
|
| + MaybeObject* maybe_descriptors = Allocate(new_size, MAY_BE_SHARED);
|
| + if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
|
|
| FixedArray::WhitenessWitness witness(new_descriptors);
|
|
|
| @@ -5886,9 +5785,7 @@ MaybeObject* DescriptorArray::CopyAdd(Descriptor* descriptor) {
|
| if (insertion_index < 0 && InsertionPointFound(GetKey(from), key)) {
|
| insertion_index = to++;
|
| }
|
| - MaybeObject* copy_result =
|
| - new_descriptors->CopyFrom(to++, this, from, witness);
|
| - if (copy_result->IsFailure()) return copy_result;
|
| + new_descriptors->CopyFrom(to++, this, from, witness);
|
| }
|
| if (insertion_index < 0) insertion_index = to++;
|
|
|
| @@ -5909,18 +5806,14 @@ MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) {
|
| // Allocate the new descriptor array.
|
| int number_of_descriptors = this->number_of_descriptors();
|
| DescriptorArray* new_descriptors;
|
| - { MaybeObject* maybe_result = Allocate(number_of_descriptors,
|
| - shared_mode);
|
| - if (!maybe_result->To(&new_descriptors)) return maybe_result;
|
| - }
|
| + MaybeObject* maybe_result = Allocate(number_of_descriptors, shared_mode);
|
| + if (!maybe_result->To(&new_descriptors)) return maybe_result;
|
|
|
| // Copy the content.
|
| if (number_of_descriptors > 0) {
|
| FixedArray::WhitenessWitness witness(new_descriptors);
|
| for (int i = 0; i < number_of_descriptors; i++) {
|
| - MaybeObject* copy_result =
|
| - new_descriptors->CopyFrom(i, this, i, witness);
|
| - if (copy_result->IsFailure()) return copy_result;
|
| + new_descriptors->CopyFrom(i, this, i, witness);
|
| }
|
| new_descriptors->SetLastAdded(LastAdded());
|
| }
|
| @@ -6020,14 +5913,14 @@ void DescriptorArray::Sort(const WhitenessWitness& witness) {
|
| }
|
|
|
|
|
| -MaybeObject* AccessorPair::CopyWithoutTransitions() {
|
| +MaybeObject* AccessorPair::Copy() {
|
| Heap* heap = GetHeap();
|
| AccessorPair* copy;
|
| - { MaybeObject* maybe_copy = heap->AllocateAccessorPair();
|
| - if (!maybe_copy->To(©)) return maybe_copy;
|
| - }
|
| - copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter());
|
| - copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter());
|
| + MaybeObject* maybe_copy = heap->AllocateAccessorPair();
|
| + if (!maybe_copy->To(©)) return maybe_copy;
|
| +
|
| + copy->set_getter(getter());
|
| + copy->set_setter(setter());
|
| return copy;
|
| }
|
|
|
| @@ -7313,40 +7206,6 @@ static bool ClearBackPointer(Heap* heap, Object* target) {
|
| }
|
|
|
|
|
| -static bool ClearAccessorComponent(Heap* heap,
|
| - AccessorPair* accessors,
|
| - AccessorComponent component) {
|
| - Object* component_value = accessors->get(component);
|
| - if (!component_value->IsMap()) return true;
|
| - if (ClearBackPointer(heap, component_value)) {
|
| - accessors->set(component, heap->the_hole_value());
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -
|
| -static bool ClearNonLiveTransition(Heap* heap,
|
| - TransitionArray* t,
|
| - int transition_index) {
|
| - // If the value is a map, check if the target is live. If not, clear the
|
| - // transition. Also drop the back pointer for that map transition, so that
|
| - // this map is not reached again by following a back pointer from that
|
| - // non-live map.
|
| - Object* value = t->GetValue(transition_index);
|
| - if (value->IsMap()) {
|
| - return ClearBackPointer(heap, t->GetValue(transition_index));
|
| - }
|
| -
|
| - ASSERT(value->IsAccessorPair());
|
| -
|
| - AccessorPair* accessors = AccessorPair::cast(value);
|
| - bool getter = ClearAccessorComponent(heap, accessors, ACCESSOR_GETTER);
|
| - bool setter = ClearAccessorComponent(heap, accessors, ACCESSOR_SETTER);
|
| - return getter && setter;
|
| -}
|
| -
|
| -
|
| // 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.
|
| @@ -7362,17 +7221,17 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
|
|
|
| // Compact all live descriptors to the left.
|
| for (int i = 0; i < t->number_of_transitions(); ++i) {
|
| - if (!ClearNonLiveTransition(heap, t, i)) {
|
| + if (!ClearBackPointer(heap, t->GetTarget(i))) {
|
| if (i != transition_index) {
|
| String* key = t->GetKey(i);
|
| - Object* value = t->GetValue(i);
|
| + Map* target = t->GetTarget(i);
|
| t->SetKey(transition_index, key);
|
| - t->SetValue(transition_index, value);
|
| + t->SetTarget(transition_index, target);
|
| MarkCompactCollector* collector = heap->mark_compact_collector();
|
| Object** key_slot = t->GetKeySlot(transition_index);
|
| collector->RecordSlot(key_slot, key_slot, key);
|
| - Object** value_slot = t->GetValueSlot(transition_index);
|
| - collector->RecordSlot(value_slot, value_slot, value);
|
| + Object** target_slot = t->GetTargetSlot(transition_index);
|
| + collector->RecordSlot(target_slot, target_slot, target);
|
| }
|
| transition_index++;
|
| }
|
| @@ -10472,7 +10331,7 @@ bool JSObject::HasRealNamedCallbackProperty(String* key) {
|
|
|
| LookupResult result(isolate);
|
| LocalLookupRealNamedProperty(key, &result);
|
| - return result.IsCallbacks();
|
| + return result.IsPropertyCallbacks();
|
| }
|
|
|
|
|
| @@ -12696,15 +12555,15 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
|
| if (IsKey(k)) {
|
| Object* value = ValueAt(i);
|
| // Ensure the key is a symbol before writing into the instance descriptor.
|
| - Object* key;
|
| - { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
|
| - if (!maybe_key->ToObject(&key)) return maybe_key;
|
| - }
|
| + String* key;
|
| + MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
|
| + if (!maybe_key->To(&key)) return maybe_key;
|
| +
|
| PropertyDetails details = DetailsAt(i);
|
| PropertyType type = details.type();
|
|
|
| if (value->IsJSFunction() && !heap->InNewSpace(value)) {
|
| - ConstantFunctionDescriptor d(String::cast(key),
|
| + ConstantFunctionDescriptor d(key,
|
| JSFunction::cast(value),
|
| details.attributes(),
|
| details.index());
|
| @@ -12718,18 +12577,13 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
|
| int offset = current_offset - inobject_props;
|
| FixedArray::cast(fields)->set(offset, value);
|
| }
|
| - FieldDescriptor d(String::cast(key),
|
| + FieldDescriptor d(key,
|
| current_offset++,
|
| details.attributes(),
|
| details.index());
|
| descriptors->Set(next_descriptor, &d, witness);
|
| } else if (type == CALLBACKS) {
|
| - if (value->IsAccessorPair()) {
|
| - MaybeObject* maybe_copy =
|
| - AccessorPair::cast(value)->CopyWithoutTransitions();
|
| - if (!maybe_copy->To(&value)) return maybe_copy;
|
| - }
|
| - CallbacksDescriptor d(String::cast(key),
|
| + CallbacksDescriptor d(key,
|
| value,
|
| details.attributes(),
|
| details.index());
|
| @@ -12745,10 +12599,8 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
|
| descriptors->Sort(witness);
|
| // Allocate new map.
|
| Map* new_map;
|
| - { MaybeObject* maybe_new_map =
|
| - obj->map()->CopyReplaceDescriptors(descriptors);
|
| - if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| - }
|
| + MaybeObject* maybe_new_map = obj->map()->CopyReplaceDescriptors(descriptors);
|
| + if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
|
|
| new_map->set_unused_property_fields(unused_property_fields);
|
|
|
|
|