| 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;
|
|
|