diff --git a/deps/v8/src/heap/heap-inl.h b/deps/v8/src/heap/heap-inl.h index e31d3d6859..3d2e059fae 100644 --- a/deps/v8/src/heap/heap-inl.h +++ b/deps/v8/src/heap/heap-inl.h @@ -449,6 +449,31 @@ void Heap::CopyBlock(Address dst, Address src, int byte_size) { static_cast(byte_size / kPointerSize)); } +bool Heap::PurgeLeftTrimmedObject(Object** object) { + HeapObject* current = reinterpret_cast(*object); + const MapWord map_word = current->map_word(); + if (current->IsFiller() && !map_word.IsForwardingAddress()) { +#ifdef DEBUG + // We need to find a FixedArrayBase map after walking the fillers. + while (current->IsFiller()) { + Address next = reinterpret_cast
(current); + if (current->map() == one_pointer_filler_map()) { + next += kPointerSize; + } else if (current->map() == two_pointer_filler_map()) { + next += 2 * kPointerSize; + } else { + next += current->Size(); + } + current = reinterpret_cast(next); + } + DCHECK(current->IsFixedArrayBase()); +#endif // DEBUG + *object = nullptr; + return true; + } + return false; +} + template AllocationMemento* Heap::FindAllocationMemento(HeapObject* object) { // Check if there is potentially a memento behind the object. If diff --git a/deps/v8/src/heap/heap.h b/deps/v8/src/heap/heap.h index 2d2029912c..2ce326a64e 100644 --- a/deps/v8/src/heap/heap.h +++ b/deps/v8/src/heap/heap.h @@ -602,6 +602,12 @@ class Heap { // stored on the map to facilitate fast dispatch for {StaticVisitorBase}. static int GetStaticVisitorIdForMap(Map* map); + // We cannot avoid stale handles to left-trimmed objects, but can only make + // sure all handles still needed are updated. Filter out a stale pointer + // and clear the slot to allow post processing of handles (needed because + // the sweeper might actually free the underlying page). + inline bool PurgeLeftTrimmedObject(Object** object); + // Notifies the heap that is ok to start marking or other activities that // should not happen during deserialization. void NotifyDeserializationComplete(); diff --git a/deps/v8/src/heap/mark-compact.cc b/deps/v8/src/heap/mark-compact.cc index e3c56b04ee..31b12f1d1b 100644 --- a/deps/v8/src/heap/mark-compact.cc +++ b/deps/v8/src/heap/mark-compact.cc @@ -1376,31 +1376,7 @@ class RootMarkingVisitor : public ObjectVisitor { HeapObject* object = HeapObject::cast(*p); - // We cannot avoid stale handles to left-trimmed objects, but can only make - // sure all handles still needed are updated. Filter out any stale pointers - // and clear the slot to allow post processing of handles (needed because - // the sweeper might actually free the underlying page). - if (object->IsFiller()) { -#ifdef DEBUG - // We need to find a FixedArrayBase map after walking the fillers. - Heap* heap = collector_->heap(); - HeapObject* current = object; - while (current->IsFiller()) { - Address next = reinterpret_cast
(current); - if (current->map() == heap->one_pointer_filler_map()) { - next += kPointerSize; - } else if (current->map() == heap->two_pointer_filler_map()) { - next += 2 * kPointerSize; - } else { - next += current->Size(); - } - current = reinterpret_cast(next); - } - DCHECK(current->IsFixedArrayBase()); -#endif // DEBUG - *p = nullptr; - return; - } + if (collector_->heap()->PurgeLeftTrimmedObject(p)) return; MarkBit mark_bit = Marking::MarkBitFrom(object); if (Marking::IsBlackOrGrey(mark_bit)) return; diff --git a/deps/v8/src/heap/scavenger.cc b/deps/v8/src/heap/scavenger.cc index 3f532ead62..18735bd201 100644 --- a/deps/v8/src/heap/scavenger.cc +++ b/deps/v8/src/heap/scavenger.cc @@ -462,6 +462,9 @@ void ScavengeVisitor::VisitPointers(Object** start, Object** end) { void ScavengeVisitor::ScavengePointer(Object** p) { Object* object = *p; if (!heap_->InNewSpace(object)) return; + + if (heap_->PurgeLeftTrimmedObject(p)) return; + Scavenger::ScavengeObject(reinterpret_cast(p), reinterpret_cast(object)); } diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index b75dd1c969..11f4d7498d 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -1261,8 +1261,7 @@ Map* MapWord::ToMap() { return reinterpret_cast(value_); } - -bool MapWord::IsForwardingAddress() { +bool MapWord::IsForwardingAddress() const { return HAS_SMI_TAG(reinterpret_cast(value_)); } diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index abced2d4ba..d1632c9deb 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -1476,7 +1476,7 @@ class MapWord BASE_EMBEDDED { // True if this map word is a forwarding address for a scavenge // collection. Only valid during a scavenge collection (specifically, // when all map words are heap object pointers, i.e. not during a full GC). - inline bool IsForwardingAddress(); + inline bool IsForwardingAddress() const; // Create a map word from a forwarding address. static inline MapWord FromForwardingAddress(HeapObject* object); diff --git a/deps/v8/test/mjsunit/regress/regress-621869.js b/deps/v8/test/mjsunit/regress/regress-621869.js new file mode 100644 index 0000000000..db34064457 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-621869.js @@ -0,0 +1,18 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-gc + +var o0 = []; +var o1 = []; +var cnt = 0; +var only_scavenge = true; +o1.__defineGetter__(0, function() { + if (cnt++ > 2) return; + o0.shift(); + gc(only_scavenge); + o0.push((64)); + o0.concat(o1); +}); +o1[0];