Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Unified Diff: src/heap.cc

Issue 2983001: Revert revisions 5041 and 5042 introducing virtual scavenge... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap.h ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap.cc
===================================================================
--- src/heap.cc (revision 5045)
+++ src/heap.cc (working copy)
@@ -799,34 +799,34 @@
};
-// A queue of objects promoted during scavenge. Each object is accompanied
-// by it's size to avoid dereferencing a map pointer for scanning.
+// A queue of pointers and maps of to-be-promoted objects during a
+// scavenge collection.
class PromotionQueue {
public:
void Initialize(Address start_address) {
- front_ = rear_ = reinterpret_cast<intptr_t*>(start_address);
+ front_ = rear_ = reinterpret_cast<HeapObject**>(start_address);
}
bool is_empty() { return front_ <= rear_; }
- void insert(HeapObject* target, int size) {
- *(--rear_) = reinterpret_cast<intptr_t>(target);
- *(--rear_) = size;
+ void insert(HeapObject* object, Map* map) {
+ *(--rear_) = object;
+ *(--rear_) = map;
// Assert no overflow into live objects.
ASSERT(reinterpret_cast<Address>(rear_) >= Heap::new_space()->top());
}
- void remove(HeapObject** target, int* size) {
- *target = reinterpret_cast<HeapObject*>(*(--front_));
- *size = static_cast<int>(*(--front_));
+ void remove(HeapObject** object, Map** map) {
+ *object = *(--front_);
+ *map = Map::cast(*(--front_));
// Assert no underflow.
ASSERT(front_ >= rear_);
}
private:
// The front of the queue is higher in memory than the rear.
- intptr_t* front_;
- intptr_t* rear_;
+ HeapObject** front_;
+ HeapObject** rear_;
};
@@ -1041,26 +1041,31 @@
// queue is empty.
while (new_space_front < new_space_.top()) {
HeapObject* object = HeapObject::FromAddress(new_space_front);
- Map* map = object->map();
- int size = object->SizeFromMap(map);
- object->IterateBody(map->instance_type(), size, scavenge_visitor);
- new_space_front += size;
+ object->Iterate(scavenge_visitor);
+ new_space_front += object->Size();
}
// Promote and process all the to-be-promoted objects.
while (!promotion_queue.is_empty()) {
- HeapObject* target;
- int size;
- promotion_queue.remove(&target, &size);
+ HeapObject* source;
+ Map* map;
+ promotion_queue.remove(&source, &map);
+ // Copy the from-space object to its new location (given by the
+ // forwarding address) and fix its map.
+ HeapObject* target = source->map_word().ToForwardingAddress();
+ int size = source->SizeFromMap(map);
+ CopyBlock(target->address(), source->address(), size);
+ target->set_map(map);
- // Promoted object might be already partially visited
- // during dirty regions iteration. Thus we search specificly
- // for pointers to from semispace instead of looking for pointers
- // to new space.
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+ // Update NewSpace stats if necessary.
+ RecordCopiedObject(target);
+#endif
+ // Visit the newly copied object for pointers to new space.
ASSERT(!target->IsMap());
- IterateAndMarkPointersToFromSpace(target->address(),
- target->address() + size,
- &ScavengePointer);
+ IterateAndMarkPointersToNewSpace(target->address(),
+ target->address() + size,
+ &ScavengePointer);
}
// Take another spin if there are now unswept objects in new space
@@ -1072,7 +1077,7 @@
#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
-static void RecordCopiedObject(HeapObject* obj) {
+void Heap::RecordCopiedObject(HeapObject* obj) {
bool should_record = false;
#ifdef DEBUG
should_record = FLAG_heap_stats;
@@ -1081,24 +1086,22 @@
should_record = should_record || FLAG_log_gc;
#endif
if (should_record) {
- if (Heap::new_space()->Contains(obj)) {
- Heap::new_space()->RecordAllocation(obj);
+ if (new_space_.Contains(obj)) {
+ new_space_.RecordAllocation(obj);
} else {
- Heap::new_space()->RecordPromotion(obj);
+ new_space_.RecordPromotion(obj);
}
}
}
#endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
-// Helper function used by CopyObject to copy a source object to an
-// allocated target object and update the forwarding pointer in the source
-// object. Returns the target object.
-inline static HeapObject* MigrateObject(HeapObject* source,
- HeapObject* target,
- int size) {
+
+HeapObject* Heap::MigrateObject(HeapObject* source,
+ HeapObject* target,
+ int size) {
// Copy the content of source to target.
- Heap::CopyBlock(target->address(), source->address(), size);
+ CopyBlock(target->address(), source->address(), size);
// Set the forwarding address.
source->set_map_word(MapWord::FromForwardingAddress(target));
@@ -1112,284 +1115,120 @@
}
-enum ObjectContents { DATA_OBJECT, POINTER_OBJECT };
-enum SizeRestriction { SMALL, UNKNOWN_SIZE };
+static inline bool IsShortcutCandidate(HeapObject* object, Map* map) {
+ STATIC_ASSERT(kNotStringTag != 0 && kSymbolTag != 0);
+ ASSERT(object->map() == map);
+ InstanceType type = map->instance_type();
+ if ((type & kShortcutTypeMask) != kShortcutTypeTag) return false;
+ ASSERT(object->IsString() && !object->IsSymbol());
+ return ConsString::cast(object)->unchecked_second() == Heap::empty_string();
+}
-template<ObjectContents object_contents, SizeRestriction size_restriction>
-static inline void EvacuateObject(Map* map,
- HeapObject** slot,
- HeapObject* object,
- int object_size) {
- ASSERT((size_restriction != SMALL) ||
- (object_size <= Page::kMaxHeapObjectSize));
- ASSERT(object->Size() == object_size);
+void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
+ ASSERT(InFromSpace(object));
+ MapWord first_word = object->map_word();
+ ASSERT(!first_word.IsForwardingAddress());
- if (Heap::ShouldBePromoted(object->address(), object_size)) {
- Object* result;
-
- if ((size_restriction != SMALL) &&
- (object_size > Page::kMaxHeapObjectSize)) {
- result = Heap::lo_space()->AllocateRawFixedArray(object_size);
- } else {
- if (object_contents == DATA_OBJECT) {
- result = Heap::old_data_space()->AllocateRaw(object_size);
- } else {
- result = Heap::old_pointer_space()->AllocateRaw(object_size);
- }
- }
-
- if (!result->IsFailure()) {
- HeapObject* target = HeapObject::cast(result);
- *slot = MigrateObject(object, target, object_size);
-
- if (object_contents == POINTER_OBJECT) {
- promotion_queue.insert(target, object_size);
- }
-
- Heap::tracer()->increment_promoted_objects_size(object_size);
+ // Optimization: Bypass flattened ConsString objects.
+ if (IsShortcutCandidate(object, first_word.ToMap())) {
+ object = HeapObject::cast(ConsString::cast(object)->unchecked_first());
+ *p = object;
+ // After patching *p we have to repeat the checks that object is in the
+ // active semispace of the young generation and not already copied.
+ if (!InNewSpace(object)) return;
+ first_word = object->map_word();
+ if (first_word.IsForwardingAddress()) {
+ *p = first_word.ToForwardingAddress();
return;
}
}
- Object* result = Heap::new_space()->AllocateRaw(object_size);
- ASSERT(!result->IsFailure());
- *slot = MigrateObject(object, HeapObject::cast(result), object_size);
- return;
-}
+ int object_size = object->SizeFromMap(first_word.ToMap());
+ // We rely on live objects in new space to be at least two pointers,
+ // so we can store the from-space address and map pointer of promoted
+ // objects in the to space.
+ ASSERT(object_size >= 2 * kPointerSize);
-template<int object_size_in_words, ObjectContents object_contents>
-static inline void EvacuateObjectOfFixedSize(Map* map,
- HeapObject** slot,
- HeapObject* object) {
- const int object_size = object_size_in_words << kPointerSizeLog2;
- EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
-}
+ // If the object should be promoted, we try to copy it to old space.
+ if (ShouldBePromoted(object->address(), object_size)) {
+ Object* result;
+ if (object_size > MaxObjectSizeInPagedSpace()) {
+ result = lo_space_->AllocateRawFixedArray(object_size);
+ if (!result->IsFailure()) {
+ HeapObject* target = HeapObject::cast(result);
+ if (object->IsFixedArray()) {
+ // Save the from-space object pointer and its map pointer at the
+ // top of the to space to be swept and copied later. Write the
+ // forwarding address over the map word of the from-space
+ // object.
+ promotion_queue.insert(object, first_word.ToMap());
+ object->set_map_word(MapWord::FromForwardingAddress(target));
-template<ObjectContents object_contents>
-static inline void EvacuateObjectOfFixedSize(Map* map,
- HeapObject** slot,
- HeapObject* object) {
- int object_size = map->instance_size();
- EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
-}
+ // Give the space allocated for the result a proper map by
+ // treating it as a free list node (not linked into the free
+ // list).
+ FreeListNode* node = FreeListNode::FromAddress(target->address());
+ node->set_size(object_size);
+ *p = target;
+ } else {
+ // In large object space only fixed arrays might possibly contain
+ // intergenerational references.
+ // All other objects can be copied immediately and not revisited.
+ *p = MigrateObject(object, target, object_size);
+ }
-static inline void EvacuateFixedArray(Map* map,
- HeapObject** slot,
- HeapObject* object) {
- int object_size = FixedArray::cast(object)->FixedArraySize();
- EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
-}
-
-
-static inline void EvacuateByteArray(Map* map,
- HeapObject** slot,
- HeapObject* object) {
- int object_size = ByteArray::cast(object)->ByteArraySize();
- EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
-}
-
-
-static Scavenger GetScavengerForSize(int object_size,
- ObjectContents object_contents) {
- ASSERT(IsAligned(object_size, kPointerSize));
- ASSERT(object_size < Page::kMaxHeapObjectSize);
-
- switch (object_size >> kPointerSizeLog2) {
-#define CASE(n) \
- case n: \
- if (object_contents == DATA_OBJECT) { \
- return static_cast<Scavenger>( \
- &EvacuateObjectOfFixedSize<n, DATA_OBJECT>); \
- } else { \
- return static_cast<Scavenger>( \
- &EvacuateObjectOfFixedSize<n, POINTER_OBJECT>); \
+ tracer()->increment_promoted_objects_size(object_size);
+ return;
}
+ } else {
+ OldSpace* target_space = Heap::TargetSpace(object);
+ ASSERT(target_space == Heap::old_pointer_space_ ||
+ target_space == Heap::old_data_space_);
+ result = target_space->AllocateRaw(object_size);
+ if (!result->IsFailure()) {
+ HeapObject* target = HeapObject::cast(result);
+ if (target_space == Heap::old_pointer_space_) {
+ // Save the from-space object pointer and its map pointer at the
+ // top of the to space to be swept and copied later. Write the
+ // forwarding address over the map word of the from-space
+ // object.
+ promotion_queue.insert(object, first_word.ToMap());
+ object->set_map_word(MapWord::FromForwardingAddress(target));
- CASE(1);
- CASE(2);
- CASE(3);
- CASE(4);
- CASE(5);
- CASE(6);
- CASE(7);
- CASE(8);
- CASE(9);
- CASE(10);
- CASE(11);
- CASE(12);
- CASE(13);
- CASE(14);
- CASE(15);
- CASE(16);
- default:
- if (object_contents == DATA_OBJECT) {
- return static_cast<Scavenger>(&EvacuateObjectOfFixedSize<DATA_OBJECT>);
- } else {
- return static_cast<Scavenger>(
- &EvacuateObjectOfFixedSize<POINTER_OBJECT>);
- }
+ // Give the space allocated for the result a proper map by
+ // treating it as a free list node (not linked into the free
+ // list).
+ FreeListNode* node = FreeListNode::FromAddress(target->address());
+ node->set_size(object_size);
-#undef CASE
- }
-}
-
-
-static inline void EvacuateSeqAsciiString(Map* map,
- HeapObject** slot,
- HeapObject* object) {
- int object_size = SeqAsciiString::cast(object)->
- SeqAsciiStringSize(map->instance_type());
- EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
-}
-
-
-static inline void EvacuateSeqTwoByteString(Map* map,
- HeapObject** slot,
- HeapObject* object) {
- int object_size = SeqTwoByteString::cast(object)->
- SeqTwoByteStringSize(map->instance_type());
- EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
-}
-
-
-static inline bool IsShortcutCandidate(int type) {
- return ((type & kShortcutTypeMask) == kShortcutTypeTag);
-}
-
-
-static inline void EvacuateShortcutCandidate(Map* map,
- HeapObject** slot,
- HeapObject* object) {
- ASSERT(IsShortcutCandidate(map->instance_type()));
-
- if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) {
- HeapObject* first =
- HeapObject::cast(ConsString::cast(object)->unchecked_first());
-
- *slot = first;
-
- if (!Heap::InNewSpace(first)) {
- object->set_map_word(MapWord::FromForwardingAddress(first));
- return;
- }
-
- MapWord first_word = first->map_word();
- if (first_word.IsForwardingAddress()) {
- HeapObject* target = first_word.ToForwardingAddress();
-
- *slot = target;
- object->set_map_word(MapWord::FromForwardingAddress(target));
- return;
- }
-
- first->map()->Scavenge(slot, first);
- object->set_map_word(MapWord::FromForwardingAddress(*slot));
- return;
- }
-
- int object_size = ConsString::kSize;
- EvacuateObject<POINTER_OBJECT, SMALL>(map, slot, object, object_size);
-}
-
-
-Scavenger Heap::GetScavenger(int instance_type, int instance_size) {
- if (instance_type < FIRST_NONSTRING_TYPE) {
- switch (instance_type & kStringRepresentationMask) {
- case kSeqStringTag:
- if ((instance_type & kStringEncodingMask) == kAsciiStringTag) {
- return &EvacuateSeqAsciiString;
+ *p = target;
} else {
- return &EvacuateSeqTwoByteString;
+ // Objects promoted to the data space can be copied immediately
+ // and not revisited---we will never sweep that space for
+ // pointers and the copied objects do not contain pointers to
+ // new space objects.
+ *p = MigrateObject(object, target, object_size);
+#ifdef DEBUG
+ VerifyNonPointerSpacePointersVisitor v;
+ (*p)->Iterate(&v);
+#endif
}
-
- case kConsStringTag:
- if (IsShortcutCandidate(instance_type)) {
- return &EvacuateShortcutCandidate;
- } else {
- ASSERT(instance_size == ConsString::kSize);
- return GetScavengerForSize(ConsString::kSize, POINTER_OBJECT);
- }
-
- case kExternalStringTag:
- ASSERT(instance_size == ExternalString::kSize);
- return GetScavengerForSize(ExternalString::kSize, DATA_OBJECT);
+ tracer()->increment_promoted_objects_size(object_size);
+ return;
+ }
}
- UNREACHABLE();
}
-
- switch (instance_type) {
- case BYTE_ARRAY_TYPE:
- return reinterpret_cast<Scavenger>(&EvacuateByteArray);
-
- case FIXED_ARRAY_TYPE:
- return reinterpret_cast<Scavenger>(&EvacuateFixedArray);
-
- case JS_OBJECT_TYPE:
- case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
- case JS_VALUE_TYPE:
- case JS_ARRAY_TYPE:
- case JS_REGEXP_TYPE:
- case JS_FUNCTION_TYPE:
- case JS_GLOBAL_PROXY_TYPE:
- case JS_GLOBAL_OBJECT_TYPE:
- case JS_BUILTINS_OBJECT_TYPE:
- return GetScavengerForSize(instance_size, POINTER_OBJECT);
-
- case ODDBALL_TYPE:
- return NULL;
-
- case PROXY_TYPE:
- return GetScavengerForSize(Proxy::kSize, DATA_OBJECT);
-
- case MAP_TYPE:
- return NULL;
-
- case CODE_TYPE:
- return NULL;
-
- case JS_GLOBAL_PROPERTY_CELL_TYPE:
- return NULL;
-
- case HEAP_NUMBER_TYPE:
- case FILLER_TYPE:
- case PIXEL_ARRAY_TYPE:
- case EXTERNAL_BYTE_ARRAY_TYPE:
- case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
- case EXTERNAL_SHORT_ARRAY_TYPE:
- case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
- case EXTERNAL_INT_ARRAY_TYPE:
- case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
- case EXTERNAL_FLOAT_ARRAY_TYPE:
- return GetScavengerForSize(instance_size, DATA_OBJECT);
-
- case SHARED_FUNCTION_INFO_TYPE:
- return GetScavengerForSize(SharedFunctionInfo::kAlignedSize,
- POINTER_OBJECT);
-
-#define MAKE_STRUCT_CASE(NAME, Name, name) \
- case NAME##_TYPE:
- STRUCT_LIST(MAKE_STRUCT_CASE)
-#undef MAKE_STRUCT_CASE
- return GetScavengerForSize(instance_size, POINTER_OBJECT);
- default:
- UNREACHABLE();
- return NULL;
- }
+ // The object should remain in new space or the old space allocation failed.
+ Object* result = new_space_.AllocateRaw(object_size);
+ // Failed allocation at this point is utterly unexpected.
+ ASSERT(!result->IsFailure());
+ *p = MigrateObject(object, HeapObject::cast(result), object_size);
}
-void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
- ASSERT(InFromSpace(object));
- MapWord first_word = object->map_word();
- ASSERT(!first_word.IsForwardingAddress());
- Map* map = first_word.ToMap();
- map->Scavenge(p, object);
-}
-
-
void Heap::ScavengePointer(HeapObject** p) {
ScavengeObject(p, *p);
}
@@ -1404,8 +1243,6 @@
reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map());
reinterpret_cast<Map*>(result)->set_instance_type(instance_type);
reinterpret_cast<Map*>(result)->set_instance_size(instance_size);
- reinterpret_cast<Map*>(result)->
- set_scavenger(GetScavenger(instance_type, instance_size));
reinterpret_cast<Map*>(result)->set_inobject_properties(0);
reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0);
reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
@@ -1422,7 +1259,6 @@
Map* map = reinterpret_cast<Map*>(result);
map->set_map(meta_map());
map->set_instance_type(instance_type);
- map->set_scavenger(GetScavenger(instance_type, instance_size));
map->set_prototype(null_value());
map->set_constructor(null_value());
map->set_instance_size(instance_size);
@@ -3855,9 +3691,9 @@
}
-void Heap::IterateAndMarkPointersToFromSpace(Address start,
- Address end,
- ObjectSlotCallback callback) {
+void Heap::IterateAndMarkPointersToNewSpace(Address start,
+ Address end,
+ ObjectSlotCallback callback) {
Address slot_address = start;
Page* page = Page::FromAddress(start);
@@ -3865,7 +3701,7 @@
while (slot_address < end) {
Object** slot = reinterpret_cast<Object**>(slot_address);
- if (Heap::InFromSpace(*slot)) {
+ if (Heap::InNewSpace(*slot)) {
ASSERT((*slot)->IsHeapObject());
callback(reinterpret_cast<HeapObject**>(slot));
if (Heap::InNewSpace(*slot)) {
« no previous file with comments | « src/heap.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698