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

Unified Diff: src/heap.cc

Issue 3066044: Generalize virtually dispatched scavenger to virtually dispatched specialized visitors. (Closed)
Patch Set: cleanup Created 10 years, 4 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/ia32/assembler-ia32-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap.cc
diff --git a/src/heap.cc b/src/heap.cc
index c4d0439e0d0b5dc940dca636b49635d7929757c7..dcc0cc6a9ba4a89389a5686d583f6a35bf18cd5d 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -37,6 +37,7 @@
#include "global-handles.h"
#include "mark-compact.h"
#include "natives.h"
+#include "objects-visiting.h"
#include "scanner.h"
#include "scopeinfo.h"
#include "snapshot.h"
@@ -1032,6 +1033,17 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable(
}
+class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> {
+ public:
+ static inline void VisitPointer(Object** p) {
+ Object* object = *p;
+ if (!Heap::InNewSpace(object)) return;
+ Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
+ reinterpret_cast<HeapObject*>(object));
+ }
+};
+
+
Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
Address new_space_front) {
do {
@@ -1042,10 +1054,7 @@ Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
// 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;
+ new_space_front += NewSpaceScavenger::IterateBody(object->map(), object);
}
// Promote and process all the to-be-promoted objects.
@@ -1072,315 +1081,231 @@ Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
}
-#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
-static void RecordCopiedObject(HeapObject* obj) {
- bool should_record = false;
-#ifdef DEBUG
- should_record = FLAG_heap_stats;
-#endif
-#ifdef ENABLE_LOGGING_AND_PROFILING
- should_record = should_record || FLAG_log_gc;
-#endif
- if (should_record) {
- if (Heap::new_space()->Contains(obj)) {
- Heap::new_space()->RecordAllocation(obj);
- } else {
- Heap::new_space()->RecordPromotion(obj);
- }
- }
-}
-#endif // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+class ScavengingVisitor : public StaticVisitorBase {
+ public:
+ static void Initialize() {
+ table_.Register(kVisitSeqAsciiString, &EvacuateSeqAsciiString);
+ table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString);
+ table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate);
+ table_.Register(kVisitByteArray, &EvacuateByteArray);
+ table_.Register(kVisitFixedArray, &EvacuateFixedArray);
+ typedef ObjectEvacuationStrategy<POINTER_OBJECT> PointerObject;
-// 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) {
- // Copy the content of source to target.
- Heap::CopyBlock(target->address(), source->address(), size);
+ table_.Register(kVisitConsString,
+ &ObjectEvacuationStrategy<POINTER_OBJECT>::
+ VisitSpecialized<ConsString::kSize>);
- // Set the forwarding address.
- source->set_map_word(MapWord::FromForwardingAddress(target));
+ table_.Register(kVisitSharedFunctionInfo,
+ &ObjectEvacuationStrategy<POINTER_OBJECT>::
+ VisitSpecialized<SharedFunctionInfo::kSize>);
-#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
- // Update NewSpace stats if necessary.
- RecordCopiedObject(target);
-#endif
- HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address()));
+ table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>,
+ kVisitDataObject,
+ kVisitDataObjectGeneric>();
- return target;
-}
+ table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
+ kVisitJSObject,
+ kVisitJSObjectGeneric>();
+ table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
+ kVisitStruct,
+ kVisitStructGeneric>();
+ }
-enum ObjectContents { DATA_OBJECT, POINTER_OBJECT };
-enum SizeRestriction { SMALL, UNKNOWN_SIZE };
+ static inline void Scavenge(Map* map, HeapObject** slot, HeapObject* obj) {
+ table_.GetVisitor(map)(map, slot, obj);
+ }
-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);
- if (Heap::ShouldBePromoted(object->address(), object_size)) {
- Object* result;
+ private:
+ enum ObjectContents { DATA_OBJECT, POINTER_OBJECT };
+ enum SizeRestriction { SMALL, UNKNOWN_SIZE };
- 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);
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+ static void RecordCopiedObject(HeapObject* obj) {
+ bool should_record = false;
+#ifdef DEBUG
+ should_record = FLAG_heap_stats;
+#endif
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ should_record = should_record || FLAG_log_gc;
+#endif
+ if (should_record) {
+ if (Heap::new_space()->Contains(obj)) {
+ Heap::new_space()->RecordAllocation(obj);
} else {
- result = Heap::old_pointer_space()->AllocateRaw(object_size);
+ Heap::new_space()->RecordPromotion(obj);
}
}
-
- 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);
- return;
- }
}
- Object* result = Heap::new_space()->AllocateRaw(object_size);
- ASSERT(!result->IsFailure());
- *slot = MigrateObject(object, HeapObject::cast(result), object_size);
- return;
-}
+#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)) {
+ // Copy the content of source to target.
+ Heap::CopyBlock(target->address(), source->address(), size);
-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);
-}
+ // Set the forwarding address.
+ source->set_map_word(MapWord::FromForwardingAddress(target));
+#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
+ // Update NewSpace stats if necessary.
+ RecordCopiedObject(target);
+#endif
+ HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address()));
-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);
-}
+ return target;
+ }
-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);
-}
+ 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);
+ if (Heap::ShouldBePromoted(object->address(), object_size)) {
+ Object* result;
-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);
-}
+ 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);
-static Scavenger GetScavengerForSize(int object_size,
- ObjectContents object_contents) {
- ASSERT(IsAligned(object_size, kPointerSize));
- ASSERT(object_size < Page::kMaxHeapObjectSize);
+ if (object_contents == POINTER_OBJECT) {
+ promotion_queue.insert(target, object_size);
+ }
- 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>); \
+ Heap::tracer()->increment_promoted_objects_size(object_size);
+ return;
}
+ }
+ Object* result = Heap::new_space()->AllocateRaw(object_size);
+ ASSERT(!result->IsFailure());
+ *slot = MigrateObject(object, HeapObject::cast(result), object_size);
+ return;
+ }
- 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>);
- }
-#undef CASE
+ static inline void EvacuateFixedArray(Map* map,
+ HeapObject** slot,
+ HeapObject* object) {
+ int object_size = FixedArray::BodyDescriptor::SizeOf(map, object);
+ EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map,
+ slot,
+ object,
+ object_size);
}
-}
-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 EvacuateByteArray(Map* map,
+ HeapObject** slot,
+ HeapObject* object) {
+ int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize();
+ EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
+ }
-static inline void EvacuateSeqTwoByteString(Map* map,
+ static inline void EvacuateSeqAsciiString(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);
-}
+ int object_size = SeqAsciiString::cast(object)->
+ SeqAsciiStringSize(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 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 void EvacuateShortcutCandidate(Map* map,
- HeapObject** slot,
- HeapObject* object) {
- ASSERT(IsShortcutCandidate(map->instance_type()));
+ static inline bool IsShortcutCandidate(int type) {
+ return ((type & kShortcutTypeMask) == kShortcutTypeTag);
+ }
- if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) {
- HeapObject* first =
- HeapObject::cast(ConsString::cast(object)->unchecked_first());
+ static inline void EvacuateShortcutCandidate(Map* map,
+ HeapObject** slot,
+ HeapObject* object) {
+ ASSERT(IsShortcutCandidate(map->instance_type()));
- *slot = first;
+ if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) {
+ HeapObject* first =
+ HeapObject::cast(ConsString::cast(object)->unchecked_first());
- if (!Heap::InNewSpace(first)) {
- object->set_map_word(MapWord::FromForwardingAddress(first));
- return;
- }
+ *slot = first;
- MapWord first_word = first->map_word();
- if (first_word.IsForwardingAddress()) {
- HeapObject* target = first_word.ToForwardingAddress();
+ if (!Heap::InNewSpace(first)) {
+ object->set_map_word(MapWord::FromForwardingAddress(first));
+ return;
+ }
- *slot = target;
- object->set_map_word(MapWord::FromForwardingAddress(target));
+ 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;
+ }
+
+ Scavenge(first->map(), slot, first);
+ object->set_map_word(MapWord::FromForwardingAddress(*slot));
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);
}
- 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;
- } else {
- return &EvacuateSeqTwoByteString;
- }
-
- 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);
+ template<ObjectContents object_contents>
+ class ObjectEvacuationStrategy {
+ public:
+ template<int object_size>
+ static inline void VisitSpecialized(Map* map,
+ HeapObject** slot,
+ HeapObject* object) {
+ EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
}
- 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);
+ static inline void Visit(Map* map,
+ HeapObject** slot,
+ HeapObject* object) {
+ int object_size = map->instance_size();
+ EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
+ }
+ };
- case MAP_TYPE:
- return NULL;
+ typedef void (*Callback)(Map* map, HeapObject** slot, HeapObject* object);
- case CODE_TYPE:
- return NULL;
+ static VisitorDispatchTable<Callback> table_;
+};
- 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;
- }
-}
+VisitorDispatchTable<ScavengingVisitor::Callback> ScavengingVisitor::table_;
void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
@@ -1388,7 +1313,7 @@ void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
MapWord first_word = object->map_word();
ASSERT(!first_word.IsForwardingAddress());
Map* map = first_word.ToMap();
- map->Scavenge(p, object);
+ ScavengingVisitor::Scavenge(map, p, object);
}
@@ -1407,7 +1332,8 @@ Object* Heap::AllocatePartialMap(InstanceType instance_type,
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));
+ set_visitor_id(
+ StaticVisitorBase::GetVisitorId(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);
@@ -1424,7 +1350,8 @@ Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) {
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_visitor_id(
+ StaticVisitorBase::GetVisitorId(instance_type, instance_size));
map->set_prototype(null_value());
map->set_constructor(null_value());
map->set_instance_size(instance_size);
@@ -4174,6 +4101,10 @@ bool Heap::Setup(bool create_heap_objects) {
if (!ConfigureHeapDefault()) return false;
}
+ ScavengingVisitor::Initialize();
+ NewSpaceScavenger::Initialize();
+ MarkCompactCollector::Initialize();
+
// Setup memory allocator and reserve a chunk of memory for new
// space. The chunk is double the size of the requested reserved
// new space size to ensure that we can find a pair of semispaces that
@@ -4858,6 +4789,7 @@ GCTracer::~GCTracer() {
PrintF("external=%d ", static_cast<int>(scopes_[Scope::EXTERNAL]));
PrintF("mark=%d ", static_cast<int>(scopes_[Scope::MC_MARK]));
PrintF("sweep=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP]));
+ PrintF("sweepns=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP_NEWSPACE]));
PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT]));
PrintF("flushcode=%d ", static_cast<int>(scopes_[Scope::MC_FLUSH_CODE]));
« no previous file with comments | « src/heap.h ('k') | src/ia32/assembler-ia32-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698