Commit 8bf73830 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[in-place weak refs] Replace WeakCells in TransitionArray::PrototypeTransitions.

BUG=v8:7308

Change-Id: Ib3926bfa22b8639d84374cf423d26d6362e3f46e
Reviewed-on: https://chromium-review.googlesource.com/1019141
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52694}
parent 2998a176
...@@ -1884,6 +1884,30 @@ Handle<FixedArray> Factory::CopyFixedArrayAndGrow(Handle<FixedArray> array, ...@@ -1884,6 +1884,30 @@ Handle<FixedArray> Factory::CopyFixedArrayAndGrow(Handle<FixedArray> array,
return CopyArrayAndGrow(array, grow_by, pretenure); return CopyArrayAndGrow(array, grow_by, pretenure);
} }
Handle<WeakFixedArray> Factory::CopyWeakFixedArrayAndGrow(
Handle<WeakFixedArray> src, int grow_by, PretenureFlag pretenure) {
DCHECK(
!src->IsTransitionArray()); // Compacted by GC, this code doesn't work.
int old_len = src->length();
int new_len = old_len + grow_by;
DCHECK_GE(new_len, old_len);
HeapObject* obj = AllocateRawFixedArray(new_len, pretenure);
DCHECK_EQ(old_len, src->length());
obj->set_map_after_allocation(src->map(), SKIP_WRITE_BARRIER);
WeakFixedArray* result = WeakFixedArray::cast(obj);
result->set_length(new_len);
// Copy the content.
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = obj->GetWriteBarrierMode(no_gc);
for (int i = 0; i < old_len; i++) result->Set(i, src->Get(i), mode);
HeapObjectReference* undefined_reference =
HeapObjectReference::Strong(isolate()->heap()->undefined_value());
MemsetPointer(result->data_start() + old_len, undefined_reference, grow_by);
return Handle<WeakFixedArray>(result, isolate());
}
Handle<WeakArrayList> Factory::CopyWeakArrayListAndGrow( Handle<WeakArrayList> Factory::CopyWeakArrayListAndGrow(
Handle<WeakArrayList> src, int grow_by, PretenureFlag pretenure) { Handle<WeakArrayList> src, int grow_by, PretenureFlag pretenure) {
int old_capacity = src->capacity(); int old_capacity = src->capacity();
......
...@@ -486,6 +486,10 @@ class V8_EXPORT_PRIVATE Factory { ...@@ -486,6 +486,10 @@ class V8_EXPORT_PRIVATE Factory {
Handle<FixedArray> array, int grow_by, Handle<FixedArray> array, int grow_by,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
Handle<WeakFixedArray> CopyWeakFixedArrayAndGrow(
Handle<WeakFixedArray> array, int grow_by,
PretenureFlag pretenure = NOT_TENURED);
Handle<WeakArrayList> CopyWeakArrayListAndGrow( Handle<WeakArrayList> CopyWeakArrayListAndGrow(
Handle<WeakArrayList> array, int grow_by, Handle<WeakArrayList> array, int grow_by,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
......
...@@ -237,6 +237,14 @@ void WeakFixedArray::Set(int index, MaybeObject* value) { ...@@ -237,6 +237,14 @@ void WeakFixedArray::Set(int index, MaybeObject* value) {
WEAK_WRITE_BARRIER(GetHeap(), this, offset, value); WEAK_WRITE_BARRIER(GetHeap(), this, offset, value);
} }
void WeakFixedArray::Set(int index, MaybeObject* value, WriteBarrierMode mode) {
DCHECK_GE(index, 0);
DCHECK_LT(index, length());
int offset = OffsetOfElementAt(index);
RELAXED_WRITE_FIELD(this, offset, value);
CONDITIONAL_WEAK_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
}
MaybeObject** WeakFixedArray::data_start() { MaybeObject** WeakFixedArray::data_start() {
return HeapObject::RawMaybeWeakField(this, kHeaderSize); return HeapObject::RawMaybeWeakField(this, kHeaderSize);
} }
......
...@@ -256,6 +256,9 @@ class WeakFixedArray : public HeapObject { ...@@ -256,6 +256,9 @@ class WeakFixedArray : public HeapObject {
// Setter that uses write barrier. // Setter that uses write barrier.
inline void Set(int index, MaybeObject* value); inline void Set(int index, MaybeObject* value);
// Setter with explicit barrier mode.
inline void Set(int index, MaybeObject* value, WriteBarrierMode mode);
static constexpr int SizeFor(int length) { static constexpr int SizeFor(int length) {
return kHeaderSize + length * kPointerSize; return kHeaderSize + length * kPointerSize;
} }
......
...@@ -28,12 +28,11 @@ bool TransitionArray::HasPrototypeTransitions() { ...@@ -28,12 +28,11 @@ bool TransitionArray::HasPrototypeTransitions() {
return Get(kPrototypeTransitionsIndex) != MaybeObject::FromSmi(Smi::kZero); return Get(kPrototypeTransitionsIndex) != MaybeObject::FromSmi(Smi::kZero);
} }
WeakFixedArray* TransitionArray::GetPrototypeTransitions() {
FixedArray* TransitionArray::GetPrototypeTransitions() {
DCHECK(HasPrototypeTransitions()); // Callers must check first. DCHECK(HasPrototypeTransitions()); // Callers must check first.
Object* prototype_transitions = Object* prototype_transitions =
Get(kPrototypeTransitionsIndex)->ToStrongHeapObject(); Get(kPrototypeTransitionsIndex)->ToStrongHeapObject();
return FixedArray::cast(prototype_transitions); return WeakFixedArray::cast(prototype_transitions);
} }
HeapObjectReference** TransitionArray::GetKeySlot(int transition_number) { HeapObjectReference** TransitionArray::GetKeySlot(int transition_number) {
...@@ -42,12 +41,19 @@ HeapObjectReference** TransitionArray::GetKeySlot(int transition_number) { ...@@ -42,12 +41,19 @@ HeapObjectReference** TransitionArray::GetKeySlot(int transition_number) {
RawFieldOfElementAt(ToKeyIndex(transition_number))); RawFieldOfElementAt(ToKeyIndex(transition_number)));
} }
void TransitionArray::SetPrototypeTransitions(FixedArray* transitions) { void TransitionArray::SetPrototypeTransitions(WeakFixedArray* transitions) {
DCHECK(transitions->IsFixedArray()); DCHECK(transitions->IsWeakFixedArray());
WeakFixedArray::Set(kPrototypeTransitionsIndex, WeakFixedArray::Set(kPrototypeTransitionsIndex,
HeapObjectReference::Strong(transitions)); HeapObjectReference::Strong(transitions));
} }
int TransitionArray::NumberOfPrototypeTransitions(
WeakFixedArray* proto_transitions) {
if (proto_transitions->length() == 0) return 0;
MaybeObject* raw =
proto_transitions->Get(kProtoTransitionNumberOfEntriesOffset);
return Smi::ToInt(raw->ToSmi());
}
Name* TransitionArray::GetKey(int transition_number) { Name* TransitionArray::GetKey(int transition_number) {
DCHECK(transition_number < number_of_transitions()); DCHECK(transition_number < number_of_transitions());
......
...@@ -309,7 +309,7 @@ bool TransitionsAccessor::IsMatchingMap(Map* target, Name* name, ...@@ -309,7 +309,7 @@ bool TransitionsAccessor::IsMatchingMap(Map* target, Name* name,
} }
// static // static
bool TransitionArray::CompactPrototypeTransitionArray(FixedArray* array) { bool TransitionArray::CompactPrototypeTransitionArray(WeakFixedArray* array) {
const int header = kProtoTransitionHeaderSize; const int header = kProtoTransitionHeaderSize;
int number_of_transitions = NumberOfPrototypeTransitions(array); int number_of_transitions = NumberOfPrototypeTransitions(array);
if (number_of_transitions == 0) { if (number_of_transitions == 0) {
...@@ -318,17 +318,21 @@ bool TransitionArray::CompactPrototypeTransitionArray(FixedArray* array) { ...@@ -318,17 +318,21 @@ bool TransitionArray::CompactPrototypeTransitionArray(FixedArray* array) {
} }
int new_number_of_transitions = 0; int new_number_of_transitions = 0;
for (int i = 0; i < number_of_transitions; i++) { for (int i = 0; i < number_of_transitions; i++) {
Object* cell = array->get(header + i); MaybeObject* target = array->Get(header + i);
if (!WeakCell::cast(cell)->cleared()) { DCHECK(target->IsClearedWeakHeapObject() ||
(target->IsWeakHeapObject() && target->ToWeakHeapObject()->IsMap()));
if (!target->IsClearedWeakHeapObject()) {
if (new_number_of_transitions != i) { if (new_number_of_transitions != i) {
array->set(header + new_number_of_transitions, cell); array->Set(header + new_number_of_transitions, target);
} }
new_number_of_transitions++; new_number_of_transitions++;
} }
} }
// Fill slots that became free with undefined value. // Fill slots that became free with undefined value.
MaybeObject* undefined = MaybeObject::FromObject(
*array->GetIsolate()->factory()->undefined_value());
for (int i = new_number_of_transitions; i < number_of_transitions; i++) { for (int i = new_number_of_transitions; i < number_of_transitions; i++) {
array->set_undefined(header + i); array->Set(header + i, undefined);
} }
if (number_of_transitions != new_number_of_transitions) { if (number_of_transitions != new_number_of_transitions) {
SetNumberOfPrototypeTransitions(array, new_number_of_transitions); SetNumberOfPrototypeTransitions(array, new_number_of_transitions);
...@@ -338,14 +342,15 @@ bool TransitionArray::CompactPrototypeTransitionArray(FixedArray* array) { ...@@ -338,14 +342,15 @@ bool TransitionArray::CompactPrototypeTransitionArray(FixedArray* array) {
// static // static
Handle<FixedArray> TransitionArray::GrowPrototypeTransitionArray( Handle<WeakFixedArray> TransitionArray::GrowPrototypeTransitionArray(
Handle<FixedArray> array, int new_capacity, Isolate* isolate) { Handle<WeakFixedArray> array, int new_capacity, Isolate* isolate) {
// Grow array by factor 2 up to MaxCachedPrototypeTransitions. // Grow array by factor 2 up to MaxCachedPrototypeTransitions.
int capacity = array->length() - kProtoTransitionHeaderSize; int capacity = array->length() - kProtoTransitionHeaderSize;
new_capacity = Min(kMaxCachedPrototypeTransitions, new_capacity); new_capacity = Min(kMaxCachedPrototypeTransitions, new_capacity);
DCHECK_GT(new_capacity, capacity); DCHECK_GT(new_capacity, capacity);
int grow_by = new_capacity - capacity; int grow_by = new_capacity - capacity;
array = isolate->factory()->CopyFixedArrayAndGrow(array, grow_by, TENURED); array =
isolate->factory()->CopyWeakFixedArrayAndGrow(array, grow_by, TENURED);
if (capacity < 0) { if (capacity < 0) {
// There was no prototype transitions array before, so the size // There was no prototype transitions array before, so the size
// couldn't be copied. Initialize it explicitly. // couldn't be copied. Initialize it explicitly.
...@@ -364,7 +369,7 @@ void TransitionsAccessor::PutPrototypeTransition(Handle<Object> prototype, ...@@ -364,7 +369,7 @@ void TransitionsAccessor::PutPrototypeTransition(Handle<Object> prototype,
const int header = TransitionArray::kProtoTransitionHeaderSize; const int header = TransitionArray::kProtoTransitionHeaderSize;
Handle<FixedArray> cache(GetPrototypeTransitions()); Handle<WeakFixedArray> cache(GetPrototypeTransitions());
int capacity = cache->length() - header; int capacity = cache->length() - header;
int transitions = TransitionArray::NumberOfPrototypeTransitions(*cache) + 1; int transitions = TransitionArray::NumberOfPrototypeTransitions(*cache) + 1;
...@@ -383,42 +388,43 @@ void TransitionsAccessor::PutPrototypeTransition(Handle<Object> prototype, ...@@ -383,42 +388,43 @@ void TransitionsAccessor::PutPrototypeTransition(Handle<Object> prototype,
int last = TransitionArray::NumberOfPrototypeTransitions(*cache); int last = TransitionArray::NumberOfPrototypeTransitions(*cache);
int entry = header + last; int entry = header + last;
Handle<WeakCell> target_cell = Map::WeakCellForMap(target_map); cache->Set(entry, HeapObjectReference::Weak(*target_map));
Reload(); // Reload after possible GC.
cache->set(entry, *target_cell);
TransitionArray::SetNumberOfPrototypeTransitions(*cache, last + 1); TransitionArray::SetNumberOfPrototypeTransitions(*cache, last + 1);
} }
Handle<Map> TransitionsAccessor::GetPrototypeTransition( Handle<Map> TransitionsAccessor::GetPrototypeTransition(
Handle<Object> prototype) { Handle<Object> prototype) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
FixedArray* cache = GetPrototypeTransitions(); WeakFixedArray* cache = GetPrototypeTransitions();
int length = TransitionArray::NumberOfPrototypeTransitions(cache); int length = TransitionArray::NumberOfPrototypeTransitions(cache);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
WeakCell* target_cell = WeakCell::cast( MaybeObject* target =
cache->get(TransitionArray::kProtoTransitionHeaderSize + i)); cache->Get(TransitionArray::kProtoTransitionHeaderSize + i);
if (!target_cell->cleared() && DCHECK(target->IsClearedWeakHeapObject() || target->IsWeakHeapObject());
Map::cast(target_cell->value())->prototype() == *prototype) { if (!target->IsClearedWeakHeapObject()) {
return handle(Map::cast(target_cell->value())); Map* map = Map::cast(target->ToWeakHeapObject());
if (map->prototype() == *prototype) {
return handle(map);
}
} }
} }
return Handle<Map>(); return Handle<Map>();
} }
FixedArray* TransitionsAccessor::GetPrototypeTransitions() { WeakFixedArray* TransitionsAccessor::GetPrototypeTransitions() {
if (encoding() != kFullTransitionArray || if (encoding() != kFullTransitionArray ||
!transitions()->HasPrototypeTransitions()) { !transitions()->HasPrototypeTransitions()) {
return map_->GetHeap()->empty_fixed_array(); return map_->GetHeap()->empty_weak_fixed_array();
} }
return transitions()->GetPrototypeTransitions(); return transitions()->GetPrototypeTransitions();
} }
// static // static
void TransitionArray::SetNumberOfPrototypeTransitions( void TransitionArray::SetNumberOfPrototypeTransitions(
FixedArray* proto_transitions, int value) { WeakFixedArray* proto_transitions, int value) {
DCHECK_NE(proto_transitions->length(), 0); DCHECK_NE(proto_transitions->length(), 0);
proto_transitions->set(kProtoTransitionNumberOfEntriesOffset, proto_transitions->Set(kProtoTransitionNumberOfEntriesOffset,
Smi::FromInt(value)); MaybeObject::FromSmi(Smi::FromInt(value)));
} }
int TransitionsAccessor::NumberOfTransitions() { int TransitionsAccessor::NumberOfTransitions() {
...@@ -461,7 +467,7 @@ void TransitionsAccessor::ReplaceTransitions(MaybeObject* new_transitions) { ...@@ -461,7 +467,7 @@ void TransitionsAccessor::ReplaceTransitions(MaybeObject* new_transitions) {
} }
void TransitionsAccessor::SetPrototypeTransitions( void TransitionsAccessor::SetPrototypeTransitions(
Handle<FixedArray> proto_transitions) { Handle<WeakFixedArray> proto_transitions) {
EnsureHasFullTransitionArray(); EnsureHasFullTransitionArray();
transitions()->SetPrototypeTransitions(*proto_transitions); transitions()->SetPrototypeTransitions(*proto_transitions);
} }
...@@ -502,13 +508,15 @@ void TransitionsAccessor::TraverseTransitionTreeInternal( ...@@ -502,13 +508,15 @@ void TransitionsAccessor::TraverseTransitionTreeInternal(
} }
case kFullTransitionArray: { case kFullTransitionArray: {
if (transitions()->HasPrototypeTransitions()) { if (transitions()->HasPrototypeTransitions()) {
FixedArray* proto_trans = transitions()->GetPrototypeTransitions(); WeakFixedArray* proto_trans = transitions()->GetPrototypeTransitions();
int length = TransitionArray::NumberOfPrototypeTransitions(proto_trans); int length = TransitionArray::NumberOfPrototypeTransitions(proto_trans);
for (int i = 0; i < length; ++i) { for (int i = 0; i < length; ++i) {
int index = TransitionArray::kProtoTransitionHeaderSize + i; int index = TransitionArray::kProtoTransitionHeaderSize + i;
WeakCell* cell = WeakCell::cast(proto_trans->get(index)); MaybeObject* target = proto_trans->Get(index);
if (cell->cleared()) continue; DCHECK(target->IsClearedWeakHeapObject() ||
TransitionsAccessor(Map::cast(cell->value()), no_gc) target->IsWeakHeapObject());
if (target->IsClearedWeakHeapObject()) continue;
TransitionsAccessor(Map::cast(target->ToWeakHeapObject()), no_gc)
.TraverseTransitionTreeInternal(callback, data, no_gc); .TraverseTransitionTreeInternal(callback, data, no_gc);
} }
} }
......
...@@ -169,8 +169,8 @@ class TransitionsAccessor { ...@@ -169,8 +169,8 @@ class TransitionsAccessor {
inline Map* GetTargetMapFromWeakRef(); inline Map* GetTargetMapFromWeakRef();
void EnsureHasFullTransitionArray(); void EnsureHasFullTransitionArray();
void SetPrototypeTransitions(Handle<FixedArray> proto_transitions); void SetPrototypeTransitions(Handle<WeakFixedArray> proto_transitions);
FixedArray* GetPrototypeTransitions(); WeakFixedArray* GetPrototypeTransitions();
void TraverseTransitionTreeInternal(TraverseCallback callback, void* data, void TraverseTransitionTreeInternal(TraverseCallback callback, void* data,
DisallowHeapAllocation* no_gc); DisallowHeapAllocation* no_gc);
...@@ -194,7 +194,7 @@ class TransitionsAccessor { ...@@ -194,7 +194,7 @@ class TransitionsAccessor {
// should use TransitionsAccessors. // should use TransitionsAccessors.
// TransitionArrays have the following format: // TransitionArrays have the following format:
// [0] Link to next TransitionArray (for weak handling support) (strong ref) // [0] Link to next TransitionArray (for weak handling support) (strong ref)
// [1] Smi(0) or fixed array of prototype transitions (strong ref) // [1] Smi(0) or WeakFixedArray of prototype transitions (strong ref)
// [2] Number of transitions (can be zero after trimming) // [2] Number of transitions (can be zero after trimming)
// [3] First transition key (strong ref) // [3] First transition key (strong ref)
// [4] First transition target (weak ref) // [4] First transition target (weak ref)
...@@ -204,7 +204,7 @@ class TransitionArray : public WeakFixedArray { ...@@ -204,7 +204,7 @@ class TransitionArray : public WeakFixedArray {
public: public:
DECL_CAST(TransitionArray) DECL_CAST(TransitionArray)
inline FixedArray* GetPrototypeTransitions(); inline WeakFixedArray* GetPrototypeTransitions();
inline bool HasPrototypeTransitions(); inline bool HasPrototypeTransitions();
// Accessors for fetching instance transition at transition number. // Accessors for fetching instance transition at transition number.
...@@ -281,14 +281,11 @@ class TransitionArray : public WeakFixedArray { ...@@ -281,14 +281,11 @@ class TransitionArray : public WeakFixedArray {
static const int kProtoTransitionHeaderSize = 1; static const int kProtoTransitionHeaderSize = 1;
static const int kMaxCachedPrototypeTransitions = 256; static const int kMaxCachedPrototypeTransitions = 256;
inline void SetPrototypeTransitions(FixedArray* prototype_transitions); inline void SetPrototypeTransitions(WeakFixedArray* prototype_transitions);
static int NumberOfPrototypeTransitions(FixedArray* proto_transitions) { static inline int NumberOfPrototypeTransitions(
if (proto_transitions->length() == 0) return 0; WeakFixedArray* proto_transitions);
Object* raw = proto_transitions->get(kProtoTransitionNumberOfEntriesOffset); static void SetNumberOfPrototypeTransitions(WeakFixedArray* proto_transitions,
return Smi::ToInt(raw);
}
static void SetNumberOfPrototypeTransitions(FixedArray* proto_transitions,
int value); int value);
static const int kProtoTransitionNumberOfEntriesOffset = 0; static const int kProtoTransitionNumberOfEntriesOffset = 0;
...@@ -316,10 +313,10 @@ class TransitionArray : public WeakFixedArray { ...@@ -316,10 +313,10 @@ class TransitionArray : public WeakFixedArray {
inline int number_of_transitions() const; inline int number_of_transitions() const;
static bool CompactPrototypeTransitionArray(FixedArray* array); static bool CompactPrototypeTransitionArray(WeakFixedArray* array);
static Handle<FixedArray> GrowPrototypeTransitionArray( static Handle<WeakFixedArray> GrowPrototypeTransitionArray(
Handle<FixedArray> array, int new_capacity, Isolate* isolate); Handle<WeakFixedArray> array, int new_capacity, Isolate* isolate);
// Compares two tuples <key, kind, attributes>, returns -1 if // Compares two tuples <key, kind, attributes>, returns -1 if
// tuple1 is "less" than tuple2, 0 if tuple1 equal to tuple2 and 1 otherwise. // tuple1 is "less" than tuple2, 0 if tuple1 equal to tuple2 and 1 otherwise.
......
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