Commit 75407ae2 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Moving prototype transitions into the header of the transition array.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12022 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 090830e4
......@@ -2082,7 +2082,7 @@ MaybeObject* Heap::AllocateMap(InstanceType instance_type,
map->set_pre_allocated_property_fields(0);
map->init_instance_descriptors();
map->set_code_cache(empty_fixed_array(), SKIP_WRITE_BARRIER);
map->init_prototype_transitions(undefined_value());
map->init_back_pointer(undefined_value());
map->set_unused_property_fields(0);
map->set_bit_field(0);
map->set_bit_field2(1 << Map::kIsExtensible);
......@@ -2221,15 +2221,15 @@ bool Heap::CreateInitialMaps() {
// Fix the instance_descriptors for the existing maps.
meta_map()->init_instance_descriptors();
meta_map()->set_code_cache(empty_fixed_array());
meta_map()->init_prototype_transitions(undefined_value());
meta_map()->init_back_pointer(undefined_value());
fixed_array_map()->init_instance_descriptors();
fixed_array_map()->set_code_cache(empty_fixed_array());
fixed_array_map()->init_prototype_transitions(undefined_value());
fixed_array_map()->init_back_pointer(undefined_value());
oddball_map()->init_instance_descriptors();
oddball_map()->set_code_cache(empty_fixed_array());
oddball_map()->init_prototype_transitions(undefined_value());
oddball_map()->init_back_pointer(undefined_value());
// Fix prototype object for existing maps.
meta_map()->set_prototype(null_value());
......
......@@ -1823,24 +1823,6 @@ template void Marker<MarkCompactCollector>::MarkMapContents(Map* map);
template <class T>
void Marker<T>::MarkMapContents(Map* map) {
// Mark prototype transitions array but don't push it into marking stack.
// This will make references from it weak. We will clean dead prototype
// transitions in ClearNonLiveTransitions.
Object** proto_trans_slot =
HeapObject::RawField(map, Map::kPrototypeTransitionsOrBackPointerOffset);
HeapObject* prototype_transitions = HeapObject::cast(*proto_trans_slot);
if (prototype_transitions->IsFixedArray()) {
mark_compact_collector()->RecordSlot(proto_trans_slot,
proto_trans_slot,
prototype_transitions);
MarkBit mark = Marking::MarkBitFrom(prototype_transitions);
if (!mark.Get()) {
mark.Set();
MemoryChunk::IncrementLiveBytesFromGC(prototype_transitions->address(),
prototype_transitions->Size());
}
}
// Make sure that the back pointer stored either in the map itself or inside
// its prototype transitions array is marked. Treat pointers in the descriptor
// array as weak and also mark that array to prevent visiting it later.
......@@ -1855,13 +1837,12 @@ void Marker<T>::MarkMapContents(Map* map) {
// Mark the Object* fields of the Map. Since the descriptor array has been
// marked already, it is fine that one of these fields contains a pointer
// to it. But make sure to skip back pointer and prototype transitions.
// to it. But make sure to skip back pointer.
STATIC_ASSERT(Map::kPointerFieldsEndOffset ==
Map::kPrototypeTransitionsOrBackPointerOffset + kPointerSize);
Object** start_slot = HeapObject::RawField(
map, Map::kPointerFieldsBeginOffset);
Object** end_slot = HeapObject::RawField(
map, Map::kPrototypeTransitionsOrBackPointerOffset);
Map::kBackPointerOffset + kPointerSize);
Object** start_slot =
HeapObject::RawField(map, Map::kPointerFieldsBeginOffset);
Object** end_slot = HeapObject::RawField(map, Map::kBackPointerOffset);
for (Object** slot = start_slot; slot < end_slot; slot++) {
Object* obj = *slot;
if (!obj->NonFailureIsHeapObject()) continue;
......@@ -1952,9 +1933,21 @@ void Marker<T>::MarkTransitionArray(TransitionArray* transitions) {
Object** transitions_start = transitions->data_start();
if (transitions->HasElementsTransition()) {
mark_compact_collector()->RecordSlot(transitions_start,
transitions->GetElementsSlot(),
transitions->elements_transition());
mark_compact_collector()->RecordSlot(
transitions_start,
transitions->GetElementsTransitionSlot(),
transitions->elements_transition());
}
if (transitions->HasPrototypeTransitions()) {
// Mark prototype transitions array but don't push it into marking stack.
// This will make references from it weak. We will clean dead prototype
// transitions in ClearNonLiveTransitions.
Object** proto_trans_slot = transitions->GetPrototypeTransitionsSlot();
HeapObject* prototype_transitions = HeapObject::cast(*proto_trans_slot);
base_marker()->MarkObjectWithoutPush(prototype_transitions);
mark_compact_collector()->RecordSlot(
transitions_start, proto_trans_slot, prototype_transitions);
}
for (int i = 0; i < transitions->number_of_transitions(); ++i) {
......@@ -2545,7 +2538,7 @@ void MarkCompactCollector::ClearNonLiveTransitions() {
void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) {
int number_of_transitions = map->NumberOfProtoTransitions();
FixedArray* prototype_transitions = map->prototype_transitions();
FixedArray* prototype_transitions = map->GetPrototypeTransitions();
int new_number_of_transitions = 0;
const int header = Map::kProtoTransitionHeaderSize;
......
......@@ -1006,7 +1006,6 @@ void NormalizedMapCache::NormalizedMapCacheVerify() {
void Map::ZapTransitions() {
TransitionArray* transition_array = transitions();
if (transition_array == NULL) return;
MemsetPointer(transition_array->data_start(),
GetHeap()->the_hole_value(),
transition_array->length());
......@@ -1014,7 +1013,7 @@ void Map::ZapTransitions() {
void Map::ZapPrototypeTransitions() {
FixedArray* proto_transitions = prototype_transitions();
FixedArray* proto_transitions = GetPrototypeTransitions();
MemsetPointer(proto_transitions->data_start(),
GetHeap()->the_hole_value(),
proto_transitions->length());
......
......@@ -3524,12 +3524,7 @@ void Map::set_bit_field3(int value) {
Object* Map::GetBackPointer() {
Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset);
if (object->IsFixedArray()) {
return FixedArray::cast(object)->get(kProtoTransitionBackPointerOffset);
} else {
return object;
}
return READ_FIELD(this, kBackPointerOffset);
}
......@@ -3567,9 +3562,9 @@ static MaybeObject* AllowTransitions(Map* map) {
}
// If the descriptor does not have a transition array, install a new
// transition array that has room for an element transition.
static MaybeObject* AllowElementsTransition(Map* map) {
// If the descriptor is using the empty transition array, install a new empty
// transition array that will have place for an element transition.
static MaybeObject* EnsureHasTransitionArray(Map* map) {
if (map->HasTransitionArray()) return map;
AllowTransitions(map);
......@@ -3584,13 +3579,41 @@ static MaybeObject* AllowElementsTransition(Map* map) {
MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
MaybeObject* allow_elements = AllowElementsTransition(this);
MaybeObject* allow_elements = EnsureHasTransitionArray(this);
if (allow_elements->IsFailure()) return allow_elements;
transitions()->set_elements_transition(transitioned_map);
return this;
}
FixedArray* Map::GetPrototypeTransitions() {
if (!HasTransitionArray()) return GetHeap()->empty_fixed_array();
if (!transitions()->HasPrototypeTransitions()) {
return GetHeap()->empty_fixed_array();
}
return transitions()->GetPrototypeTransitions();
}
MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) {
MaybeObject* allow_prototype = EnsureHasTransitionArray(this);
if (allow_prototype->IsFailure()) return allow_prototype;
#ifdef DEBUG
if (HasPrototypeTransitions()) {
ASSERT(GetPrototypeTransitions() != proto_transitions);
ZapPrototypeTransitions();
}
#endif
transitions()->SetPrototypeTransitions(proto_transitions);
return this;
}
bool Map::HasPrototypeTransitions() {
return HasTransitionArray() && transitions()->HasPrototypeTransitions();
}
TransitionArray* Map::transitions() {
return instance_descriptors()->transitions();
}
......@@ -3623,57 +3646,38 @@ MaybeObject* Map::set_transitions(TransitionArray* transitions_array) {
}
void Map::init_back_pointer(Object* undefined) {
ASSERT(undefined->IsUndefined());
WRITE_FIELD(this, kBackPointerOffset, undefined);
}
void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
Heap* heap = GetHeap();
ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE);
ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) ||
(value->IsMap() && GetBackPointer()->IsUndefined()));
Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset);
if (object->IsFixedArray()) {
FixedArray::cast(object)->set(
kProtoTransitionBackPointerOffset, value, mode);
} else {
WRITE_FIELD(this, kPrototypeTransitionsOrBackPointerOffset, value);
CONDITIONAL_WRITE_BARRIER(
heap, this, kPrototypeTransitionsOrBackPointerOffset, value, mode);
}
}
FixedArray* Map::prototype_transitions() {
Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset);
if (object->IsFixedArray()) {
return FixedArray::cast(object);
} else {
return GetHeap()->empty_fixed_array();
}
WRITE_FIELD(this, kBackPointerOffset, value);
CONDITIONAL_WRITE_BARRIER(heap, this, kBackPointerOffset, value, mode);
}
void Map::set_prototype_transitions(FixedArray* value, WriteBarrierMode mode) {
Heap* heap = GetHeap();
ASSERT(value != heap->empty_fixed_array());
value->set(kProtoTransitionBackPointerOffset, GetBackPointer());
#ifdef DEBUG
if (value != prototype_transitions()) {
ZapPrototypeTransitions();
}
#endif
WRITE_FIELD(this, kPrototypeTransitionsOrBackPointerOffset, value);
CONDITIONAL_WRITE_BARRIER(
heap, this, kPrototypeTransitionsOrBackPointerOffset, value, mode);
}
void Map::init_prototype_transitions(Object* undefined) {
ASSERT(undefined->IsUndefined());
WRITE_FIELD(this, kPrototypeTransitionsOrBackPointerOffset, undefined);
// Can either be Smi (no transitions), normal transition array, or a transition
// array with the header overwritten as a Smi (thus iterating).
TransitionArray* Map::unchecked_transition_array() {
ASSERT(HasTransitionArray());
Object* object = *HeapObject::RawField(instance_descriptors(),
DescriptorArray::kTransitionsOffset);
ASSERT(!object->IsSmi());
TransitionArray* transition_array = static_cast<TransitionArray*>(object);
return transition_array;
}
HeapObject* Map::unchecked_prototype_transitions() {
Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset);
return reinterpret_cast<HeapObject*>(object);
HeapObject* Map::UncheckedPrototypeTransitions() {
ASSERT(HasTransitionArray());
ASSERT(unchecked_transition_array()->HasPrototypeTransitions());
return unchecked_transition_array()->UncheckedPrototypeTransitions();
}
......
......@@ -5147,11 +5147,11 @@ class IntrusivePrototypeTransitionIterator {
void Start() {
ASSERT(!IsIterating());
if (HasTransitions()) *Header() = Smi::FromInt(0);
*Header() = Smi::FromInt(0);
}
bool IsIterating() {
return HasTransitions() && (*Header())->IsSmi();
return (*Header())->IsSmi();
}
Map* Next() {
......@@ -5166,23 +5166,17 @@ class IntrusivePrototypeTransitionIterator {
}
private:
bool HasTransitions() {
return proto_trans_->map()->IsSmi() || proto_trans_->IsFixedArray();
}
Object** Header() {
return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
}
int NumberOfTransitions() {
ASSERT(HasTransitions());
FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
return Smi::cast(num)->value();
}
Map* GetTransition(int transitionNumber) {
ASSERT(HasTransitions());
FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
}
......@@ -5232,42 +5226,41 @@ class TraversableMap : public Map {
return old_parent;
}
// Can either be Smi (no instance descriptors), or a descriptor array with the
// header overwritten as a Smi (thus iterating).
TransitionArray* MutatedTransitions() {
Object* object = *HeapObject::RawField(instance_descriptors(),
DescriptorArray::kTransitionsOffset);
TransitionArray* transition_array = static_cast<TransitionArray*>(object);
return transition_array;
}
// Start iterating over this map's children, possibly destroying a FixedArray
// map (see explanation above).
void ChildIteratorStart() {
if (HasTransitionArray()) {
if (HasPrototypeTransitions()) {
IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start();
}
IntrusiveMapTransitionIterator(transitions()).Start();
}
IntrusivePrototypeTransitionIterator(
unchecked_prototype_transitions()).Start();
}
// If we have an unvisited child map, return that one and advance. If we have
// none, return NULL and reset any destroyed FixedArray maps.
TraversableMap* ChildIteratorNext() {
IntrusivePrototypeTransitionIterator
proto_iterator(unchecked_prototype_transitions());
if (proto_iterator.IsIterating()) {
Map* next = proto_iterator.Next();
if (next != NULL) return static_cast<TraversableMap*>(next);
}
if (HasTransitionArray()) {
IntrusiveMapTransitionIterator
transitions_iterator(MutatedTransitions());
if (transitions_iterator.IsIterating()) {
Map* next = transitions_iterator.Next();
TransitionArray* transition_array = unchecked_transition_array();
if (transition_array->HasPrototypeTransitions()) {
HeapObject* proto_transitions =
transition_array->UncheckedPrototypeTransitions();
IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions);
if (proto_iterator.IsIterating()) {
Map* next = proto_iterator.Next();
if (next != NULL) return static_cast<TraversableMap*>(next);
}
}
IntrusiveMapTransitionIterator transition_iterator(transition_array);
if (transition_iterator.IsIterating()) {
Map* next = transition_iterator.Next();
if (next != NULL) return static_cast<TraversableMap*>(next);
}
}
return NULL;
}
};
......@@ -7417,7 +7410,9 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
// If the final transition array does not contain any live transitions, remove
// the transition array from the map.
if (transition_index == 0 && !t->HasElementsTransition()) {
if (transition_index == 0 &&
!t->HasElementsTransition() &&
!t->HasPrototypeTransitions()) {
return ClearTransitions();
}
......@@ -8835,7 +8830,7 @@ MaybeObject* JSArray::SetElementsLength(Object* len) {
Map* Map::GetPrototypeTransition(Object* prototype) {
FixedArray* cache = prototype_transitions();
FixedArray* cache = GetPrototypeTransitions();
int number_of_transitions = NumberOfProtoTransitions();
const int proto_offset =
kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
......@@ -8857,7 +8852,7 @@ MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
// Don't cache prototype transition if this map is shared.
if (is_shared() || !FLAG_cache_prototype_transitions) return this;
FixedArray* cache = prototype_transitions();
FixedArray* cache = GetPrototypeTransitions();
const int step = kProtoTransitionElementsPerEntry;
const int header = kProtoTransitionHeaderSize;
......@@ -8880,7 +8875,8 @@ MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
new_cache->set(i + header, cache->get(i + header));
}
cache = new_cache;
set_prototype_transitions(cache);
MaybeObject* set_result = SetPrototypeTransitions(cache);
if (set_result->IsFailure()) return set_result;
}
int last = transitions - 1;
......
......@@ -4864,6 +4864,7 @@ class Map: public HeapObject {
inline Object* GetBackPointer();
inline void SetBackPointer(Object* value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void init_back_pointer(Object* undefined);
// [prototype transitions]: cache of prototype transitions.
// Prototype transition is a transition that happens
......@@ -4873,27 +4874,29 @@ class Map: public HeapObject {
// 1: back pointer that overlaps with prototype transitions field.
// 2 + 2 * i: prototype
// 3 + 2 * i: target map
DECL_ACCESSORS(prototype_transitions, FixedArray)
inline FixedArray* GetPrototypeTransitions();
MUST_USE_RESULT inline MaybeObject* SetPrototypeTransitions(
FixedArray* prototype_transitions);
inline bool HasPrototypeTransitions();
inline void init_prototype_transitions(Object* undefined);
inline HeapObject* unchecked_prototype_transitions();
inline HeapObject* UncheckedPrototypeTransitions();
inline TransitionArray* unchecked_transition_array();
static const int kProtoTransitionHeaderSize = 2;
static const int kProtoTransitionHeaderSize = 1;
static const int kProtoTransitionNumberOfEntriesOffset = 0;
static const int kProtoTransitionBackPointerOffset = 1;
static const int kProtoTransitionElementsPerEntry = 2;
static const int kProtoTransitionPrototypeOffset = 0;
static const int kProtoTransitionMapOffset = 1;
inline int NumberOfProtoTransitions() {
FixedArray* cache = prototype_transitions();
FixedArray* cache = GetPrototypeTransitions();
if (cache->length() == 0) return 0;
return
Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value();
}
inline void SetNumberOfProtoTransitions(int value) {
FixedArray* cache = prototype_transitions();
FixedArray* cache = GetPrototypeTransitions();
ASSERT(cache->length() != 0);
cache->set_unchecked(kProtoTransitionNumberOfEntriesOffset,
Smi::FromInt(value));
......@@ -5053,17 +5056,14 @@ class Map: public HeapObject {
kConstructorOffset + kPointerSize;
static const int kCodeCacheOffset =
kInstanceDescriptorsOrBitField3Offset + kPointerSize;
static const int kPrototypeTransitionsOrBackPointerOffset =
kCodeCacheOffset + kPointerSize;
static const int kPadStart =
kPrototypeTransitionsOrBackPointerOffset + kPointerSize;
static const int kBackPointerOffset = kCodeCacheOffset + kPointerSize;
static const int kPadStart = kBackPointerOffset + kPointerSize;
static const int kSize = MAP_POINTER_ALIGN(kPadStart);
// Layout of pointer fields. Heap iteration code relies on them
// being continuously allocated.
static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
static const int kPointerFieldsEndOffset =
kPrototypeTransitionsOrBackPointerOffset + kPointerSize;
static const int kPointerFieldsEndOffset = kBackPointerOffset + kPointerSize;
// Byte offsets within kInstanceSizesOffset.
static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
......
......@@ -2013,16 +2013,6 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
"descriptors", map->instance_descriptors(),
Map::kInstanceDescriptorsOrBitField3Offset);
}
if (map->unchecked_prototype_transitions()->IsFixedArray()) {
TagObject(map->prototype_transitions(), "(prototype transitions)");
SetInternalReference(map, entry,
"prototype_transitions", map->prototype_transitions(),
Map::kPrototypeTransitionsOrBackPointerOffset);
} else {
SetInternalReference(map, entry,
"back_pointer", map->GetBackPointer(),
Map::kPrototypeTransitionsOrBackPointerOffset);
}
SetInternalReference(map, entry,
"code_cache", map->code_cache(),
Map::kCodeCacheOffset);
......
......@@ -82,6 +82,42 @@ void TransitionArray::set_elements_transition(Map* transition_map,
}
bool TransitionArray::HasPrototypeTransitions() {
Object* prototype_transitions = get(kPrototypeTransitionsIndex);
return prototype_transitions != Smi::FromInt(0);
}
FixedArray* TransitionArray::GetPrototypeTransitions() {
Object* prototype_transitions = get(kPrototypeTransitionsIndex);
return FixedArray::cast(prototype_transitions);
}
HeapObject* TransitionArray::UncheckedPrototypeTransitions() {
Object* prototype_transitions = get(kPrototypeTransitionsIndex);
if (prototype_transitions == Smi::FromInt(0)) return NULL;
return reinterpret_cast<HeapObject*>(prototype_transitions);
}
void TransitionArray::SetPrototypeTransitions(FixedArray* transitions,
WriteBarrierMode mode) {
ASSERT(this != NULL);
ASSERT(transitions->IsFixedArray());
Heap* heap = GetHeap();
WRITE_FIELD(this, kPrototypeTransitionsOffset, transitions);
CONDITIONAL_WRITE_BARRIER(
heap, this, kPrototypeTransitionsOffset, transitions, mode);
}
Object** TransitionArray::GetPrototypeTransitionsSlot() {
return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
kPrototypeTransitionsOffset);
}
Object** TransitionArray::GetKeySlot(int transition_number) {
ASSERT(transition_number < number_of_transitions());
return HeapObject::RawField(
......@@ -148,7 +184,7 @@ PropertyDetails TransitionArray::GetTargetDetails(int transition_number) {
}
Object** TransitionArray::GetElementsSlot() {
Object** TransitionArray::GetElementsTransitionSlot() {
return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
kElementsTransitionOffset);
}
......
......@@ -45,6 +45,7 @@ MaybeObject* TransitionArray::Allocate(int number_of_transitions) {
}
array->set(kElementsTransitionIndex, Smi::FromInt(0));
array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
return array;
}
......@@ -98,6 +99,10 @@ MaybeObject* TransitionArray::CopyInsert(String* name, Object* value) {
result->set_elements_transition(elements_transition());
}
if (HasPrototypeTransitions()) {
result->SetPrototypeTransitions(GetPrototypeTransitions());
}
FixedArray::WhitenessWitness witness(result);
if (insertion_index != kNotFound) {
......
......@@ -46,22 +46,33 @@ namespace internal {
// [length() - kTransitionSize] Last transition
class TransitionArray: public FixedArray {
public:
inline Map* elements_transition();
inline void set_elements_transition(
Map* value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void ClearElementsTransition();
inline bool HasElementsTransition();
// Accessors for fetching instance transition at transition number.
inline String* GetKey(int transition_number);
inline Object** GetKeySlot(int transition_number);
inline void SetKey(int transition_number, String* value);
inline Object** GetKeySlot(int transition_number);
inline Object* GetValue(int transition_number);
inline Object** GetValueSlot(int transition_number);
inline void SetValue(int transition_number, Object* value);
inline Object** GetValueSlot(int transition_number);
inline Map* GetTargetMap(int transition_number);
inline PropertyDetails GetTargetDetails(int transition_number);
inline Object** GetElementsSlot();
inline Map* elements_transition();
inline void set_elements_transition(
Map* value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline Object** GetElementsTransitionSlot();
inline bool HasElementsTransition();
inline void ClearElementsTransition();
inline FixedArray* GetPrototypeTransitions();
inline void SetPrototypeTransitions(
FixedArray* prototype_transitions,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline Object** GetPrototypeTransitionsSlot();
inline bool HasPrototypeTransitions();
inline HeapObject* UncheckedPrototypeTransitions();
// Returns the number of transitions in the array.
int number_of_transitions() {
......@@ -99,11 +110,14 @@ class TransitionArray: public FixedArray {
static const int kNotFound = -1;
static const int kElementsTransitionIndex = 0;
static const int kFirstIndex = 1;
static const int kPrototypeTransitionsIndex = 1;
static const int kFirstIndex = 2;
// Layout transition array header.
static const int kElementsTransitionOffset = FixedArray::kHeaderSize;
static const int kFirstOffset = kElementsTransitionOffset + kPointerSize;
static const int kPrototypeTransitionsOffset = kElementsTransitionOffset +
kPointerSize;
static const int kFirstOffset = kPrototypeTransitionsOffset + kPointerSize;
// Layout of map transition.
static const int kTransitionKey = 0;
......
......@@ -1587,7 +1587,7 @@ TEST(PrototypeTransitionClearing) {
CHECK_EQ(transitions, baseObject->map()->NumberOfProtoTransitions());
// Verify that prototype transitions array was compacted.
FixedArray* trans = baseObject->map()->prototype_transitions();
FixedArray* trans = baseObject->map()->GetPrototypeTransitions();
for (int i = 0; i < transitions; i++) {
int j = Map::kProtoTransitionHeaderSize +
i * Map::kProtoTransitionElementsPerEntry;
......@@ -1608,7 +1608,8 @@ TEST(PrototypeTransitionClearing) {
// clearing correctly records slots in prototype transition array.
i::FLAG_always_compact = true;
Handle<Map> map(baseObject->map());
CHECK(!space->LastPage()->Contains(map->prototype_transitions()->address()));
CHECK(!space->LastPage()->Contains(
map->GetPrototypeTransitions()->address()));
CHECK(space->LastPage()->Contains(prototype->address()));
baseObject->SetPrototype(*prototype, false)->ToObjectChecked();
CHECK(map->GetPrototypeTransition(*prototype)->IsMap());
......
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