Revert r11556 and r11558 to allow roll.

R=yangguo@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11564 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1016c4a2
// Copyright 2012 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -118,29 +118,13 @@ void IncrementalMarking::BlackToGreyAndUnshift(HeapObject* obj, ...@@ -118,29 +118,13 @@ void IncrementalMarking::BlackToGreyAndUnshift(HeapObject* obj,
void IncrementalMarking::WhiteToGreyAndPush(HeapObject* obj, MarkBit mark_bit) { void IncrementalMarking::WhiteToGreyAndPush(HeapObject* obj, MarkBit mark_bit) {
Marking::WhiteToGrey(mark_bit); WhiteToGrey(obj, mark_bit);
marking_deque_.PushGrey(obj); marking_deque_.PushGrey(obj);
} }
bool IncrementalMarking::MarkObjectAndPush(HeapObject* obj) { void IncrementalMarking::WhiteToGrey(HeapObject* obj, MarkBit mark_bit) {
MarkBit mark_bit = Marking::MarkBitFrom(obj); Marking::WhiteToGrey(mark_bit);
if (!mark_bit.Get()) {
WhiteToGreyAndPush(obj, mark_bit);
return true;
}
return false;
}
bool IncrementalMarking::MarkObjectWithoutPush(HeapObject* obj) {
MarkBit mark_bit = Marking::MarkBitFrom(obj);
if (!mark_bit.Get()) {
mark_bit.Set();
MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size());
return true;
}
return false;
} }
......
// Copyright 2012 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -42,7 +42,6 @@ IncrementalMarking::IncrementalMarking(Heap* heap) ...@@ -42,7 +42,6 @@ IncrementalMarking::IncrementalMarking(Heap* heap)
state_(STOPPED), state_(STOPPED),
marking_deque_memory_(NULL), marking_deque_memory_(NULL),
marking_deque_memory_committed_(false), marking_deque_memory_committed_(false),
marker_(this, heap->mark_compact_collector()),
steps_count_(0), steps_count_(0),
steps_took_(0), steps_took_(0),
longest_step_(0.0), longest_step_(0.0),
...@@ -664,22 +663,6 @@ void IncrementalMarking::Hurry() { ...@@ -664,22 +663,6 @@ void IncrementalMarking::Hurry() {
} else if (map == global_context_map) { } else if (map == global_context_map) {
// Global contexts have weak fields. // Global contexts have weak fields.
VisitGlobalContext(Context::cast(obj), &marking_visitor); VisitGlobalContext(Context::cast(obj), &marking_visitor);
} else if (map->instance_type() == MAP_TYPE) {
Map* map = Map::cast(obj);
heap_->ClearCacheOnMap(map);
// When map collection is enabled we have to mark through map's
// transitions and back pointers in a special way to make these links
// weak. Only maps for subclasses of JSReceiver can have transitions.
STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
if (FLAG_collect_maps &&
map->instance_type() >= FIRST_JS_RECEIVER_TYPE) {
marker_.MarkMapContents(map);
} else {
marking_visitor.VisitPointers(
HeapObject::RawField(map, Map::kPointerFieldsBeginOffset),
HeapObject::RawField(map, Map::kPointerFieldsEndOffset));
}
} else { } else {
obj->Iterate(&marking_visitor); obj->Iterate(&marking_visitor);
} }
...@@ -824,6 +807,12 @@ void IncrementalMarking::Step(intptr_t allocated_bytes, ...@@ -824,6 +807,12 @@ void IncrementalMarking::Step(intptr_t allocated_bytes,
Map* map = obj->map(); Map* map = obj->map();
if (map == filler_map) continue; if (map == filler_map) continue;
if (obj->IsMap()) {
Map* map = Map::cast(obj);
heap_->ClearCacheOnMap(map);
}
int size = obj->SizeFromMap(map); int size = obj->SizeFromMap(map);
bytes_to_process -= size; bytes_to_process -= size;
MarkBit map_mark_bit = Marking::MarkBitFrom(map); MarkBit map_mark_bit = Marking::MarkBitFrom(map);
...@@ -841,22 +830,6 @@ void IncrementalMarking::Step(intptr_t allocated_bytes, ...@@ -841,22 +830,6 @@ void IncrementalMarking::Step(intptr_t allocated_bytes,
MarkObjectGreyDoNotEnqueue(ctx->normalized_map_cache()); MarkObjectGreyDoNotEnqueue(ctx->normalized_map_cache());
VisitGlobalContext(ctx, &marking_visitor); VisitGlobalContext(ctx, &marking_visitor);
} else if (map->instance_type() == MAP_TYPE) {
Map* map = Map::cast(obj);
heap_->ClearCacheOnMap(map);
// When map collection is enabled we have to mark through map's
// transitions and back pointers in a special way to make these links
// weak. Only maps for subclasses of JSReceiver can have transitions.
STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
if (FLAG_collect_maps &&
map->instance_type() >= FIRST_JS_RECEIVER_TYPE) {
marker_.MarkMapContents(map);
} else {
marking_visitor.VisitPointers(
HeapObject::RawField(map, Map::kPointerFieldsBeginOffset),
HeapObject::RawField(map, Map::kPointerFieldsEndOffset));
}
} else if (map->instance_type() == JS_FUNCTION_TYPE) { } else if (map->instance_type() == JS_FUNCTION_TYPE) {
marking_visitor.VisitPointers( marking_visitor.VisitPointers(
HeapObject::RawField(obj, JSFunction::kPropertiesOffset), HeapObject::RawField(obj, JSFunction::kPropertiesOffset),
......
// Copyright 2012 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -154,6 +154,8 @@ class IncrementalMarking { ...@@ -154,6 +154,8 @@ class IncrementalMarking {
inline void WhiteToGreyAndPush(HeapObject* obj, MarkBit mark_bit); inline void WhiteToGreyAndPush(HeapObject* obj, MarkBit mark_bit);
inline void WhiteToGrey(HeapObject* obj, MarkBit mark_bit);
// Does white->black or keeps gray or black color. Returns true if converting // Does white->black or keeps gray or black color. Returns true if converting
// white to black. // white to black.
inline bool MarkBlackOrKeepGrey(MarkBit mark_bit) { inline bool MarkBlackOrKeepGrey(MarkBit mark_bit) {
...@@ -167,16 +169,6 @@ class IncrementalMarking { ...@@ -167,16 +169,6 @@ class IncrementalMarking {
return true; return true;
} }
// Marks the object grey and pushes it on the marking stack.
// Returns true if object needed marking and false otherwise.
// This is for incremental marking only.
INLINE(bool MarkObjectAndPush(HeapObject* obj));
// Marks the object black without pushing it on the marking stack.
// Returns true if object needed marking and false otherwise.
// This is for incremental marking only.
INLINE(bool MarkObjectWithoutPush(HeapObject* obj));
inline int steps_count() { inline int steps_count() {
return steps_count_; return steps_count_;
} }
...@@ -268,7 +260,6 @@ class IncrementalMarking { ...@@ -268,7 +260,6 @@ class IncrementalMarking {
VirtualMemory* marking_deque_memory_; VirtualMemory* marking_deque_memory_;
bool marking_deque_memory_committed_; bool marking_deque_memory_committed_;
MarkingDeque marking_deque_; MarkingDeque marking_deque_;
Marker<IncrementalMarking> marker_;
int steps_count_; int steps_count_;
double steps_took_; double steps_took_;
......
// Copyright 2012 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -52,15 +52,6 @@ void MarkCompactCollector::SetFlags(int flags) { ...@@ -52,15 +52,6 @@ void MarkCompactCollector::SetFlags(int flags) {
} }
bool MarkCompactCollector::MarkObjectAndPush(HeapObject* obj) {
if (MarkObjectWithoutPush(obj)) {
marking_deque_.PushBlack(obj);
return true;
}
return false;
}
void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) { void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
ASSERT(Marking::MarkBitFrom(obj) == mark_bit); ASSERT(Marking::MarkBitFrom(obj) == mark_bit);
if (!mark_bit.Get()) { if (!mark_bit.Get()) {
...@@ -71,13 +62,16 @@ void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) { ...@@ -71,13 +62,16 @@ void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
} }
bool MarkCompactCollector::MarkObjectWithoutPush(HeapObject* obj) { bool MarkCompactCollector::MarkObjectWithoutPush(HeapObject* object) {
MarkBit mark_bit = Marking::MarkBitFrom(obj); MarkBit mark = Marking::MarkBitFrom(object);
if (!mark_bit.Get()) { bool old_mark = mark.Get();
SetMark(obj, mark_bit); if (!old_mark) SetMark(object, mark);
return true; return old_mark;
} }
return false;
void MarkCompactCollector::MarkObjectAndPush(HeapObject* object) {
if (!MarkObjectWithoutPush(object)) marking_deque_.PushBlack(object);
} }
......
...@@ -64,13 +64,13 @@ MarkCompactCollector::MarkCompactCollector() : // NOLINT ...@@ -64,13 +64,13 @@ MarkCompactCollector::MarkCompactCollector() : // NOLINT
abort_incremental_marking_(false), abort_incremental_marking_(false),
compacting_(false), compacting_(false),
was_marked_incrementally_(false), was_marked_incrementally_(false),
collect_maps_(FLAG_collect_maps),
flush_monomorphic_ics_(false), flush_monomorphic_ics_(false),
tracer_(NULL), tracer_(NULL),
migration_slots_buffer_(NULL), migration_slots_buffer_(NULL),
heap_(NULL), heap_(NULL),
code_flusher_(NULL), code_flusher_(NULL),
encountered_weak_maps_(NULL), encountered_weak_maps_(NULL) { }
marker_(this, this) { }
#ifdef DEBUG #ifdef DEBUG
...@@ -282,7 +282,7 @@ void MarkCompactCollector::CollectGarbage() { ...@@ -282,7 +282,7 @@ void MarkCompactCollector::CollectGarbage() {
MarkLiveObjects(); MarkLiveObjects();
ASSERT(heap_->incremental_marking()->IsStopped()); ASSERT(heap_->incremental_marking()->IsStopped());
if (FLAG_collect_maps) ClearNonLiveTransitions(); if (collect_maps_) ClearNonLiveTransitions();
ClearWeakMaps(); ClearWeakMaps();
...@@ -294,7 +294,7 @@ void MarkCompactCollector::CollectGarbage() { ...@@ -294,7 +294,7 @@ void MarkCompactCollector::CollectGarbage() {
SweepSpaces(); SweepSpaces();
if (!FLAG_collect_maps) ReattachInitialMaps(); if (!collect_maps_) ReattachInitialMaps();
Finish(); Finish();
...@@ -658,6 +658,11 @@ void MarkCompactCollector::AbortCompaction() { ...@@ -658,6 +658,11 @@ void MarkCompactCollector::AbortCompaction() {
void MarkCompactCollector::Prepare(GCTracer* tracer) { void MarkCompactCollector::Prepare(GCTracer* tracer) {
was_marked_incrementally_ = heap()->incremental_marking()->IsMarking(); was_marked_incrementally_ = heap()->incremental_marking()->IsMarking();
// Disable collection of maps if incremental marking is enabled.
// Map collection algorithm relies on a special map transition tree traversal
// order which is not implemented for incremental marking.
collect_maps_ = FLAG_collect_maps && !was_marked_incrementally_;
// Monomorphic ICs are preserved when possible, but need to be flushed // Monomorphic ICs are preserved when possible, but need to be flushed
// when they might be keeping a Context alive, or when the heap is about // when they might be keeping a Context alive, or when the heap is about
// to be serialized. // to be serialized.
...@@ -1793,11 +1798,11 @@ void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) { ...@@ -1793,11 +1798,11 @@ void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) {
heap_->ClearCacheOnMap(map); heap_->ClearCacheOnMap(map);
// When map collection is enabled we have to mark through map's transitions // When map collection is enabled we have to mark through map's transitions
// in a special way to make transition links weak. Only maps for subclasses // in a special way to make transition links weak.
// of JSReceiver can have transitions. // Only maps for subclasses of JSReceiver can have transitions.
STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
if (FLAG_collect_maps && map->instance_type() >= FIRST_JS_RECEIVER_TYPE) { if (collect_maps_ && map->instance_type() >= FIRST_JS_RECEIVER_TYPE) {
marker_.MarkMapContents(map); MarkMapContents(map);
} else { } else {
marking_deque_.PushBlack(map); marking_deque_.PushBlack(map);
} }
...@@ -1807,86 +1812,85 @@ void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) { ...@@ -1807,86 +1812,85 @@ void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) {
} }
// Force instantiation of template instances. void MarkCompactCollector::MarkMapContents(Map* map) {
template void Marker<IncrementalMarking>::MarkMapContents(Map* map);
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. // Mark prototype transitions array but don't push it into marking stack.
// This will make references from it weak. We will clean dead prototype // This will make references from it weak. We will clean dead prototype
// transitions in ClearNonLiveTransitions. // transitions in ClearNonLiveTransitions. But make sure that back pointers
Object** proto_trans_slot = // stored inside prototype transitions arrays are marked.
HeapObject::RawField(map, Map::kPrototypeTransitionsOrBackPointerOffset); Object* raw_proto_transitions = map->unchecked_prototype_transitions();
HeapObject* prototype_transitions = HeapObject::cast(*proto_trans_slot); if (raw_proto_transitions->IsFixedArray()) {
if (prototype_transitions->IsFixedArray()) { FixedArray* prototype_transitions = FixedArray::cast(raw_proto_transitions);
mark_compact_collector()->RecordSlot(proto_trans_slot,
proto_trans_slot,
prototype_transitions);
MarkBit mark = Marking::MarkBitFrom(prototype_transitions); MarkBit mark = Marking::MarkBitFrom(prototype_transitions);
if (!mark.Get()) { if (!mark.Get()) {
mark.Set(); mark.Set();
MemoryChunk::IncrementLiveBytesFromGC(prototype_transitions->address(), MemoryChunk::IncrementLiveBytesFromGC(prototype_transitions->address(),
prototype_transitions->Size()); prototype_transitions->Size());
MarkObjectAndPush(HeapObject::cast(
prototype_transitions->get(Map::kProtoTransitionBackPointerOffset)));
} }
} }
// Make sure that the back pointer stored either in the map itself or inside Object** raw_descriptor_array_slot =
// its prototype transitions array is marked. Treat pointers in the descriptor
// array as weak and also mark that array to prevent visiting it later.
base_marker()->MarkObjectAndPush(HeapObject::cast(map->GetBackPointer()));
Object** descriptor_array_slot =
HeapObject::RawField(map, Map::kInstanceDescriptorsOrBitField3Offset); HeapObject::RawField(map, Map::kInstanceDescriptorsOrBitField3Offset);
Object* descriptor_array = *descriptor_array_slot; Object* raw_descriptor_array = *raw_descriptor_array_slot;
if (!descriptor_array->IsSmi()) { if (!raw_descriptor_array->IsSmi()) {
MarkDescriptorArray(reinterpret_cast<DescriptorArray*>(descriptor_array)); MarkDescriptorArray(
} reinterpret_cast<DescriptorArray*>(raw_descriptor_array));
// 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.
STATIC_ASSERT(Map::kPointerFieldsEndOffset ==
Map::kPrototypeTransitionsOrBackPointerOffset + kPointerSize);
Object** start_slot = HeapObject::RawField(
map, Map::kPointerFieldsBeginOffset);
Object** end_slot = HeapObject::RawField(
map, Map::kPrototypeTransitionsOrBackPointerOffset);
for (Object** slot = start_slot; slot < end_slot; slot++) {
Object* obj = *slot;
if (!obj->NonFailureIsHeapObject()) continue;
mark_compact_collector()->RecordSlot(start_slot, slot, obj);
base_marker()->MarkObjectAndPush(reinterpret_cast<HeapObject*>(obj));
} }
// 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.
Object** start_slot = HeapObject::RawField(map,
Map::kPointerFieldsBeginOffset);
Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset);
StaticMarkingVisitor::VisitPointers(map->GetHeap(), start_slot, end_slot);
} }
template <class T> void MarkCompactCollector::MarkAccessorPairSlot(HeapObject* accessors,
void Marker<T>::MarkDescriptorArray(DescriptorArray* descriptors) { int offset) {
Object** slot = HeapObject::RawField(accessors, offset);
HeapObject* accessor = HeapObject::cast(*slot);
if (accessor->IsMap()) return;
RecordSlot(slot, slot, accessor);
MarkObjectAndPush(accessor);
}
void MarkCompactCollector::MarkDescriptorArray(
DescriptorArray* descriptors) {
MarkBit descriptors_mark = Marking::MarkBitFrom(descriptors);
if (descriptors_mark.Get()) return;
// Empty descriptor array is marked as a root before any maps are marked. // Empty descriptor array is marked as a root before any maps are marked.
ASSERT(descriptors != descriptors->GetHeap()->empty_descriptor_array()); ASSERT(descriptors != heap()->empty_descriptor_array());
SetMark(descriptors, descriptors_mark);
// The DescriptorArray contains a pointer to its contents array, but the FixedArray* contents = reinterpret_cast<FixedArray*>(
// contents array will be marked black and hence not be visited again.
if (!base_marker()->MarkObjectAndPush(descriptors)) return;
FixedArray* contents = FixedArray::cast(
descriptors->get(DescriptorArray::kContentArrayIndex)); descriptors->get(DescriptorArray::kContentArrayIndex));
ASSERT(contents->IsHeapObject());
ASSERT(!IsMarked(contents));
ASSERT(contents->IsFixedArray());
ASSERT(contents->length() >= 2); ASSERT(contents->length() >= 2);
ASSERT(Marking::IsWhite(Marking::MarkBitFrom(contents))); MarkBit contents_mark = Marking::MarkBitFrom(contents);
base_marker()->MarkObjectWithoutPush(contents); SetMark(contents, contents_mark);
// Contents contains (value, details) pairs. If the details say that the type
// Contents contains (value, details) pairs. If the descriptor contains a // of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION,
// transition (value is a Map), we don't mark the value as live. It might // EXTERNAL_ARRAY_TRANSITION or NULL_DESCRIPTOR, we don't mark the value as
// be set to the NULL_DESCRIPTOR in ClearNonLiveTransitions later. // live. Only for MAP_TRANSITION, EXTERNAL_ARRAY_TRANSITION and
// CONSTANT_TRANSITION is the value an Object* (a Map*).
for (int i = 0; i < contents->length(); i += 2) { for (int i = 0; i < contents->length(); i += 2) {
// If the pair (value, details) at index i, i+1 is not
// a transition or null descriptor, mark the value.
PropertyDetails details(Smi::cast(contents->get(i + 1))); PropertyDetails details(Smi::cast(contents->get(i + 1)));
Object** slot = contents->data_start() + i; Object** slot = contents->data_start() + i;
if (!(*slot)->IsHeapObject()) continue; if (!(*slot)->IsHeapObject()) continue;
HeapObject* value = HeapObject::cast(*slot); HeapObject* value = HeapObject::cast(*slot);
mark_compact_collector()->RecordSlot(slot, slot, *slot); RecordSlot(slot, slot, *slot);
switch (details.type()) { switch (details.type()) {
case NORMAL: case NORMAL:
...@@ -1894,22 +1898,21 @@ void Marker<T>::MarkDescriptorArray(DescriptorArray* descriptors) { ...@@ -1894,22 +1898,21 @@ void Marker<T>::MarkDescriptorArray(DescriptorArray* descriptors) {
case CONSTANT_FUNCTION: case CONSTANT_FUNCTION:
case HANDLER: case HANDLER:
case INTERCEPTOR: case INTERCEPTOR:
base_marker()->MarkObjectAndPush(value); MarkObjectAndPush(value);
break; break;
case CALLBACKS: case CALLBACKS:
if (!value->IsAccessorPair()) { if (!value->IsAccessorPair()) {
base_marker()->MarkObjectAndPush(value); MarkObjectAndPush(value);
} else if (base_marker()->MarkObjectWithoutPush(value)) { } else if (!MarkObjectWithoutPush(value)) {
AccessorPair* accessors = AccessorPair::cast(value); MarkAccessorPairSlot(value, AccessorPair::kGetterOffset);
MarkAccessorPairSlot(accessors, AccessorPair::kGetterOffset); MarkAccessorPairSlot(value, AccessorPair::kSetterOffset);
MarkAccessorPairSlot(accessors, AccessorPair::kSetterOffset);
} }
break; break;
case ELEMENTS_TRANSITION: case ELEMENTS_TRANSITION:
// For maps with multiple elements transitions, the transition maps are // For maps with multiple elements transitions, the transition maps are
// stored in a FixedArray. Keep the fixed array alive but not the maps // stored in a FixedArray. Keep the fixed array alive but not the maps
// that it refers to. // that it refers to.
if (value->IsFixedArray()) base_marker()->MarkObjectWithoutPush(value); if (value->IsFixedArray()) MarkObjectWithoutPush(value);
break; break;
case MAP_TRANSITION: case MAP_TRANSITION:
case CONSTANT_TRANSITION: case CONSTANT_TRANSITION:
...@@ -1917,16 +1920,9 @@ void Marker<T>::MarkDescriptorArray(DescriptorArray* descriptors) { ...@@ -1917,16 +1920,9 @@ void Marker<T>::MarkDescriptorArray(DescriptorArray* descriptors) {
break; break;
} }
} }
} // The DescriptorArray descriptors contains a pointer to its contents array,
// but the contents array is already marked.
marking_deque_.PushBlack(descriptors);
template <class T>
void Marker<T>::MarkAccessorPairSlot(AccessorPair* accessors, int offset) {
Object** slot = HeapObject::RawField(accessors, offset);
HeapObject* accessor = HeapObject::cast(*slot);
if (accessor->IsMap()) return;
mark_compact_collector()->RecordSlot(slot, slot, accessor);
base_marker()->MarkObjectAndPush(accessor);
} }
......
...@@ -42,7 +42,6 @@ typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset); ...@@ -42,7 +42,6 @@ typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset);
// Forward declarations. // Forward declarations.
class CodeFlusher; class CodeFlusher;
class GCTracer; class GCTracer;
class MarkCompactCollector;
class MarkingVisitor; class MarkingVisitor;
class RootMarkingVisitor; class RootMarkingVisitor;
...@@ -167,6 +166,7 @@ class Marking { ...@@ -167,6 +166,7 @@ class Marking {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Marking deque for tracing live objects. // Marking deque for tracing live objects.
class MarkingDeque { class MarkingDeque {
public: public:
MarkingDeque() MarkingDeque()
...@@ -383,34 +383,6 @@ class SlotsBuffer { ...@@ -383,34 +383,6 @@ class SlotsBuffer {
}; };
// -------------------------------------------------------------------------
// Marker shared between incremental and non-incremental marking
template<class BaseMarker> class Marker {
public:
Marker(BaseMarker* base_marker, MarkCompactCollector* mark_compact_collector)
: base_marker_(base_marker),
mark_compact_collector_(mark_compact_collector) {}
// Mark pointers in a Map and its DescriptorArray together, possibly
// treating transitions or back pointers weak.
void MarkMapContents(Map* map);
void MarkDescriptorArray(DescriptorArray* descriptors);
void MarkAccessorPairSlot(AccessorPair* accessors, int offset);
private:
BaseMarker* base_marker() {
return base_marker_;
}
MarkCompactCollector* mark_compact_collector() {
return mark_compact_collector_;
}
BaseMarker* base_marker_;
MarkCompactCollector* mark_compact_collector_;
};
// Defined in isolate.h. // Defined in isolate.h.
class ThreadLocalTop; class ThreadLocalTop;
...@@ -612,6 +584,8 @@ class MarkCompactCollector { ...@@ -612,6 +584,8 @@ class MarkCompactCollector {
bool was_marked_incrementally_; bool was_marked_incrementally_;
bool collect_maps_;
bool flush_monomorphic_ics_; bool flush_monomorphic_ics_;
// A pointer to the current stack-allocated GC tracer object during a full // A pointer to the current stack-allocated GC tracer object during a full
...@@ -634,13 +608,12 @@ class MarkCompactCollector { ...@@ -634,13 +608,12 @@ class MarkCompactCollector {
// //
// After: Live objects are marked and non-live objects are unmarked. // After: Live objects are marked and non-live objects are unmarked.
friend class RootMarkingVisitor; friend class RootMarkingVisitor;
friend class MarkingVisitor; friend class MarkingVisitor;
friend class StaticMarkingVisitor; friend class StaticMarkingVisitor;
friend class CodeMarkingVisitor; friend class CodeMarkingVisitor;
friend class SharedFunctionInfoMarkingVisitor; friend class SharedFunctionInfoMarkingVisitor;
friend class Marker<IncrementalMarking>;
friend class Marker<MarkCompactCollector>;
// Mark non-optimize code for functions inlined into the given optimized // Mark non-optimize code for functions inlined into the given optimized
// code. This will prevent it from being flushed. // code. This will prevent it from being flushed.
...@@ -658,25 +631,22 @@ class MarkCompactCollector { ...@@ -658,25 +631,22 @@ class MarkCompactCollector {
void AfterMarking(); void AfterMarking();
// Marks the object black and pushes it on the marking stack. // Marks the object black and pushes it on the marking stack.
// Returns true if object needed marking and false otherwise. // This is for non-incremental marking.
// This is for non-incremental marking only.
INLINE(bool MarkObjectAndPush(HeapObject* obj));
// Marks the object black and pushes it on the marking stack.
// This is for non-incremental marking only.
INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit)); INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit));
// Marks the object black without pushing it on the marking stack. INLINE(bool MarkObjectWithoutPush(HeapObject* object));
// Returns true if object needed marking and false otherwise. INLINE(void MarkObjectAndPush(HeapObject* value));
// This is for non-incremental marking only.
INLINE(bool MarkObjectWithoutPush(HeapObject* obj));
// Marks the object black assuming that it is not yet marked. // Marks the object black. This is for non-incremental marking.
// This is for non-incremental marking only.
INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit)); INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit));
void ProcessNewlyMarkedObject(HeapObject* obj); void ProcessNewlyMarkedObject(HeapObject* obj);
// Mark a Map and its DescriptorArray together, skipping transitions.
void MarkMapContents(Map* map);
void MarkAccessorPairSlot(HeapObject* accessors, int offset);
void MarkDescriptorArray(DescriptorArray* descriptors);
// Mark the heap roots and all objects reachable from them. // Mark the heap roots and all objects reachable from them.
void MarkRoots(RootMarkingVisitor* visitor); void MarkRoots(RootMarkingVisitor* visitor);
...@@ -779,7 +749,6 @@ class MarkCompactCollector { ...@@ -779,7 +749,6 @@ class MarkCompactCollector {
MarkingDeque marking_deque_; MarkingDeque marking_deque_;
CodeFlusher* code_flusher_; CodeFlusher* code_flusher_;
Object* encountered_weak_maps_; Object* encountered_weak_maps_;
Marker<MarkCompactCollector> marker_;
List<Page*> evacuation_candidates_; List<Page*> evacuation_candidates_;
List<Code*> invalidated_code_; List<Code*> invalidated_code_;
......
...@@ -1735,60 +1735,3 @@ TEST(OptimizedAllocationAlwaysInNewSpace) { ...@@ -1735,60 +1735,3 @@ TEST(OptimizedAllocationAlwaysInNewSpace) {
CHECK(HEAP->InNewSpace(*o)); CHECK(HEAP->InNewSpace(*o));
} }
static int CountMapTransitions(Map* map) {
int result = 0;
DescriptorArray* descs = map->instance_descriptors();
for (int i = 0; i < descs->number_of_descriptors(); i++) {
if (descs->IsTransitionOnly(i)) {
result++;
}
}
return result;
}
// Test that map transitions are cleared and maps are collected with
// incremental marking as well.
TEST(Regress1465) {
i::FLAG_allow_natives_syntax = true;
i::FLAG_trace_incremental_marking = true;
InitializeVM();
v8::HandleScope scope;
#define TRANSITION_COUNT 256
for (int i = 0; i < TRANSITION_COUNT; i++) {
EmbeddedVector<char, 64> buffer;
OS::SNPrintF(buffer, "var o = new Object; o.prop%d = %d;", i, i);
CompileRun(buffer.start());
}
CompileRun("var root = new Object;");
Handle<JSObject> root =
v8::Utils::OpenHandle(
*v8::Handle<v8::Object>::Cast(
v8::Context::GetCurrent()->Global()->Get(v8_str("root"))));
// Count number of live transitions before marking.
int transitions_before = CountMapTransitions(root->map());
CompileRun("%DebugPrint(root);");
CHECK_EQ(TRANSITION_COUNT, transitions_before);
// Go through all incremental marking steps in one swoop.
IncrementalMarking* marking = HEAP->incremental_marking();
CHECK(marking->IsStopped());
marking->Start();
CHECK(marking->IsMarking());
while (!marking->IsComplete()) {
marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
}
CHECK(marking->IsComplete());
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
CHECK(marking->IsStopped());
// Count number of live transitions after marking. Note that one transition
// is left, because 'o' still holds an instance of one transition target.
int transitions_after = CountMapTransitions(root->map());
CompileRun("%DebugPrint(root);");
CHECK_EQ(1, transitions_after);
}
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