Index: src/mark-compact.cc |
diff --git a/src/mark-compact.cc b/src/mark-compact.cc |
index 6c16f61d25f0f1c80f5a62af7121230698b5835c..b875d1519adac321df36cd3345bf64968333210c 100644 |
--- a/src/mark-compact.cc |
+++ b/src/mark-compact.cc |
@@ -223,6 +223,99 @@ static void VerifyEvacuation(Heap* heap) { |
VerifyEvacuationVisitor visitor; |
heap->IterateStrongRoots(&visitor, VISIT_ALL); |
} |
+ |
+ |
+class VerifyGlobalContextSeparationVisitor: public ObjectVisitor { |
+ public: |
+ VerifyGlobalContextSeparationVisitor() : current_global_context_(NULL) {} |
+ |
+ void VisitPointers(Object** start, Object** end) { |
+ for (Object** current = start; current < end; current++) { |
+ if ((*current)->IsHeapObject()) { |
+ HeapObject* object = HeapObject::cast(*current); |
+ if (object->IsString()) continue; |
+ switch (object->map()->instance_type()) { |
+ case JS_FUNCTION_TYPE: |
+ CheckContext(JSFunction::cast(object)->context()); |
+ break; |
+ case JS_GLOBAL_PROXY_TYPE: |
+ CheckContext(JSGlobalProxy::cast(object)->context()); |
+ break; |
+ case JS_GLOBAL_OBJECT_TYPE: |
+ case JS_BUILTINS_OBJECT_TYPE: |
+ CheckContext(GlobalObject::cast(object)->global_context()); |
+ break; |
+ case JS_ARRAY_TYPE: |
+ case JS_DATE_TYPE: |
+ case JS_OBJECT_TYPE: |
+ case JS_REGEXP_TYPE: |
+ VisitPointer(HeapObject::RawField(object, JSObject::kMapOffset)); |
+ break; |
+ case MAP_TYPE: |
+ VisitPointer(HeapObject::RawField(object, Map::kPrototypeOffset)); |
+ VisitPointer(HeapObject::RawField(object, Map::kConstructorOffset)); |
+ break; |
+ case FIXED_ARRAY_TYPE: |
+ if (object->IsContext()) { |
+ CheckContext(object); |
+ } else { |
+ FixedArray* array = FixedArray::cast(object); |
+ int length = array->length(); |
+ // Set array length to zero to prevent cycles while iterating |
+ // over array bodies, this is easier than intrusive marking. |
+ array->set_length(0); |
+ array->IterateBody( |
+ FIXED_ARRAY_TYPE, FixedArray::SizeFor(length), this); |
+ array->set_length(length); |
+ } |
+ break; |
+ case JS_GLOBAL_PROPERTY_CELL_TYPE: |
+ case JS_PROXY_TYPE: |
+ case JS_VALUE_TYPE: |
+ case TYPE_FEEDBACK_INFO_TYPE: |
+ object->Iterate(this); |
+ break; |
+ case ACCESSOR_INFO_TYPE: |
+ case BYTE_ARRAY_TYPE: |
+ case CALL_HANDLER_INFO_TYPE: |
+ case CODE_TYPE: |
+ case FIXED_DOUBLE_ARRAY_TYPE: |
+ case HEAP_NUMBER_TYPE: |
+ case INTERCEPTOR_INFO_TYPE: |
+ case ODDBALL_TYPE: |
+ case SCRIPT_TYPE: |
+ case SHARED_FUNCTION_INFO_TYPE: |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ } |
+ } |
+ } |
+ |
+ private: |
+ void CheckContext(Object* context) { |
+ if (!context->IsContext()) return; |
+ Context* global_context = Context::cast(context)->global_context(); |
+ if (current_global_context_ == NULL) { |
+ current_global_context_ = global_context; |
+ } else { |
+ CHECK_EQ(current_global_context_, global_context); |
+ } |
+ } |
+ |
+ Context* current_global_context_; |
+}; |
+ |
+ |
+static void VerifyGlobalContextSeparation(Heap* heap) { |
+ HeapObjectIterator it(heap->code_space()); |
+ |
+ for (Object* object = it.Next(); object != NULL; object = it.Next()) { |
+ VerifyGlobalContextSeparationVisitor visitor; |
+ Code::cast(object)->CodeIterateBody(&visitor); |
+ } |
+} |
#endif |
@@ -296,6 +389,12 @@ void MarkCompactCollector::CollectGarbage() { |
if (!FLAG_collect_maps) ReattachInitialMaps(); |
+#ifdef DEBUG |
+ if (FLAG_verify_global_context_separation) { |
+ VerifyGlobalContextSeparation(heap_); |
+ } |
+#endif |
+ |
Finish(); |
tracer_ = NULL; |