| Index: src/objects-inl.h
|
| diff --git a/src/objects-inl.h b/src/objects-inl.h
|
| index 926e1c7a73e60a70beb93ddceb61d6bc5bf9bf7e..4ea0a0819b7fae40a51ae1265bdfd210461531ac 100644
|
| --- a/src/objects-inl.h
|
| +++ b/src/objects-inl.h
|
| @@ -5360,13 +5360,11 @@ void Map::AppendDescriptor(Descriptor* desc) {
|
|
|
|
|
| Object* Map::GetBackPointer() {
|
| - Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
|
| - if (object->IsTransitionArray()) {
|
| - return TransitionArray::cast(object)->back_pointer_storage();
|
| - } else {
|
| - DCHECK(object->IsMap() || object->IsUndefined());
|
| + Object* object = constructor_or_backpointer();
|
| + if (object->IsMap()) {
|
| return object;
|
| }
|
| + return GetIsolate()->heap()->undefined_value();
|
| }
|
|
|
|
|
| @@ -5376,7 +5374,7 @@ bool Map::HasElementsTransition() {
|
|
|
|
|
| bool Map::HasTransitionArray() const {
|
| - Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
|
| + Object* object = READ_FIELD(this, kTransitionsOffset);
|
| return object->IsTransitionArray();
|
| }
|
|
|
| @@ -5446,7 +5444,7 @@ bool Map::HasPrototypeTransitions() {
|
|
|
| TransitionArray* Map::transitions() const {
|
| DCHECK(HasTransitionArray());
|
| - Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
|
| + Object* object = READ_FIELD(this, kTransitionsOffset);
|
| return TransitionArray::cast(object);
|
| }
|
|
|
| @@ -5481,15 +5479,15 @@ void Map::set_transitions(TransitionArray* transition_array,
|
| ZapTransitions();
|
| }
|
|
|
| - WRITE_FIELD(this, kTransitionsOrBackPointerOffset, transition_array);
|
| - CONDITIONAL_WRITE_BARRIER(
|
| - GetHeap(), this, kTransitionsOrBackPointerOffset, transition_array, mode);
|
| + WRITE_FIELD(this, kTransitionsOffset, transition_array);
|
| + CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTransitionsOffset,
|
| + transition_array, mode);
|
| }
|
|
|
|
|
| -void Map::init_back_pointer(Object* undefined) {
|
| +void Map::init_transitions(Object* undefined) {
|
| DCHECK(undefined->IsUndefined());
|
| - WRITE_FIELD(this, kTransitionsOrBackPointerOffset, undefined);
|
| + WRITE_FIELD(this, kTransitionsOffset, undefined);
|
| }
|
|
|
|
|
| @@ -5497,20 +5495,31 @@ void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
|
| DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE);
|
| DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) ||
|
| (value->IsMap() && GetBackPointer()->IsUndefined()));
|
| - Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
|
| - if (object->IsTransitionArray()) {
|
| - TransitionArray::cast(object)->set_back_pointer_storage(value);
|
| - } else {
|
| - WRITE_FIELD(this, kTransitionsOrBackPointerOffset, value);
|
| - CONDITIONAL_WRITE_BARRIER(
|
| - GetHeap(), this, kTransitionsOrBackPointerOffset, value, mode);
|
| - }
|
| + DCHECK(!value->IsMap() ||
|
| + Map::cast(value)->GetConstructor() == constructor_or_backpointer());
|
| + set_constructor_or_backpointer(value, mode);
|
| }
|
|
|
|
|
| ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
|
| ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
|
| -ACCESSORS(Map, constructor, Object, kConstructorOffset)
|
| +ACCESSORS(Map, constructor_or_backpointer, Object,
|
| + kConstructorOrBackPointerOffset)
|
| +
|
| +Object* Map::GetConstructor() const {
|
| + Object* maybe_constructor = constructor_or_backpointer();
|
| + // Follow any back pointers.
|
| + while (maybe_constructor->IsMap()) {
|
| + maybe_constructor =
|
| + Map::cast(maybe_constructor)->constructor_or_backpointer();
|
| + }
|
| + return maybe_constructor;
|
| +}
|
| +void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) {
|
| + // Never overwrite a back pointer with a constructor.
|
| + DCHECK(!constructor_or_backpointer()->IsMap());
|
| + set_constructor_or_backpointer(constructor, mode);
|
| +}
|
|
|
| ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
|
| ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
|
| @@ -6199,7 +6208,12 @@ Object* JSFunction::prototype() {
|
| DCHECK(has_prototype());
|
| // If the function's prototype property has been set to a non-JSObject
|
| // value, that value is stored in the constructor field of the map.
|
| - if (map()->has_non_instance_prototype()) return map()->constructor();
|
| + if (map()->has_non_instance_prototype()) {
|
| + Object* prototype = map()->GetConstructor();
|
| + // The map must have a prototype in that field, not a back pointer.
|
| + DCHECK(!prototype->IsMap());
|
| + return prototype;
|
| + }
|
| return instance_prototype();
|
| }
|
|
|
|
|