Index: src/profile-generator.cc |
diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
index 099b9dfa21e93073b280addfc9deb5c8019c9a95..5568d519871f037b71adb8b209c58b1c95d69757 100644 |
--- a/src/profile-generator.cc |
+++ b/src/profile-generator.cc |
@@ -1826,25 +1826,41 @@ class IndexedReferencesExtractor : public ObjectVisitor { |
IndexedReferencesExtractor(V8HeapExplorer* generator, |
HeapObject* parent_obj, |
HeapEntry* parent_entry, |
- HeapObjectsSet* known_references = NULL) |
+ bool process_field_marks = false) |
: generator_(generator), |
parent_obj_(parent_obj), |
parent_(parent_entry), |
- known_references_(known_references), |
+ process_field_marks_(process_field_marks), |
next_index_(1) { |
} |
void VisitPointers(Object** start, Object** end) { |
for (Object** p = start; p < end; p++) { |
- if (!known_references_ || !known_references_->Contains(*p)) { |
- generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
- } |
+ if (CheckVisitedAndUnmark(p)) continue; |
+ generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
} |
} |
+ static void MarkVisitedField(HeapObject* obj, int offset) { |
+ if (offset < 0) return; |
+ Address field = obj->address() + offset; |
+ ASSERT(!Memory::Object_at(field)->IsFailure()); |
+ ASSERT(Memory::Object_at(field)->IsHeapObject()); |
+ *field |= kFailureTag; |
+ } |
private: |
+ bool CheckVisitedAndUnmark(Object** field) { |
+ if (process_field_marks_ && (*field)->IsFailure()) { |
+ const int unmark_tag = ~kFailureTagMask | kHeapObjectTag; |
+ *field = reinterpret_cast<Object*>( |
+ reinterpret_cast<intptr_t>(*field) & unmark_tag); |
Vitaly Repeshko
2011/03/18 12:16:36
Hmm, I think the correct way is:
(reinterpret_cast
mnaganov (inactive)
2011/03/18 12:31:01
Done.
|
+ ASSERT((*field)->IsHeapObject()); |
+ return true; |
+ } |
+ return false; |
+ } |
V8HeapExplorer* generator_; |
HeapObject* parent_obj_; |
HeapEntry* parent_; |
- HeapObjectsSet* known_references_; |
+ bool process_field_marks_; |
int next_index_; |
}; |
@@ -1853,7 +1869,6 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) { |
HeapEntry* entry = GetEntry(obj); |
if (entry == NULL) return; // No interest in this object. |
- known_references_.Clear(); |
if (obj->IsJSGlobalProxy()) { |
// We need to reference JS global objects from snapshot's root. |
// We use JSGlobalProxy because this is what embedder (e.g. browser) |
@@ -1868,17 +1883,29 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) { |
ExtractPropertyReferences(js_obj, entry); |
ExtractElementReferences(js_obj, entry); |
ExtractInternalReferences(js_obj, entry); |
- SetPropertyReference( |
- obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype()); |
+ SetPropertyReference(obj, entry, |
+ Heap::Proto_symbol(), js_obj->GetPrototype()); |
if (obj->IsJSFunction()) { |
- JSFunction* js_fun = JSFunction::cast(obj); |
- if (js_fun->has_prototype()) { |
- SetPropertyReference( |
- obj, entry, Heap::prototype_symbol(), js_fun->prototype()); |
+ JSFunction* js_fun = JSFunction::cast(js_obj); |
+ SetInternalReference( |
+ js_fun, entry, |
+ "code", js_fun->shared(), |
+ JSFunction::kSharedFunctionInfoOffset); |
+ Object* proto_or_map = js_fun->prototype_or_initial_map(); |
+ if (!proto_or_map->IsTheHole()) { |
+ if (!proto_or_map->IsMap()) { |
+ SetPropertyReference( |
+ obj, entry, |
+ Heap::prototype_symbol(), proto_or_map, |
+ JSFunction::kPrototypeOrInitialMapOffset); |
+ } else { |
+ SetPropertyReference( |
+ obj, entry, |
+ Heap::prototype_symbol(), js_fun->prototype()); |
+ } |
} |
} |
- IndexedReferencesExtractor refs_extractor( |
- this, obj, entry, &known_references_); |
+ IndexedReferencesExtractor refs_extractor(this, obj, entry, true); |
obj->Iterate(&refs_extractor); |
} else if (obj->IsString()) { |
if (obj->IsConsString()) { |
@@ -1911,7 +1938,6 @@ void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, |
SetClosureReference(js_obj, entry, local_name, context->get(idx)); |
} |
} |
- SetInternalReference(js_obj, entry, "code", func->shared()); |
} |
} |
@@ -1925,12 +1951,15 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, |
case FIELD: { |
int index = descs->GetFieldIndex(i); |
SetPropertyReference( |
- js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index)); |
+ js_obj, entry, |
+ descs->GetKey(i), js_obj->FastPropertyAt(index), |
+ js_obj->GetFastPropertyOffset(index)); |
break; |
} |
case CONSTANT_FUNCTION: |
SetPropertyReference( |
- js_obj, entry, descs->GetKey(i), descs->GetConstantFunction(i)); |
+ js_obj, entry, |
+ descs->GetKey(i), descs->GetConstantFunction(i)); |
break; |
default: ; |
} |
@@ -1990,7 +2019,8 @@ void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, |
int length = js_obj->GetInternalFieldCount(); |
for (int i = 0; i < length; ++i) { |
Object* o = js_obj->GetInternalField(i); |
- SetInternalReference(js_obj, entry, i, o); |
+ SetInternalReference( |
+ js_obj, entry, i, o, js_obj->GetInternalFieldOffset(i)); |
} |
} |
@@ -2052,7 +2082,6 @@ void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
collection_->names()->GetName(reference_name), |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
} |
} |
@@ -2069,7 +2098,6 @@ void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, |
index, |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
} |
} |
@@ -2077,7 +2105,8 @@ void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, |
void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
HeapEntry* parent_entry, |
const char* reference_name, |
- Object* child_obj) { |
+ Object* child_obj, |
+ int field_offset) { |
HeapEntry* child_entry = GetEntry(child_obj); |
if (child_entry != NULL) { |
filler_->SetNamedReference(HeapGraphEdge::kInternal, |
@@ -2086,7 +2115,7 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
reference_name, |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
+ IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
} |
} |
@@ -2094,7 +2123,8 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
HeapEntry* parent_entry, |
int index, |
- Object* child_obj) { |
+ Object* child_obj, |
+ int field_offset) { |
HeapEntry* child_entry = GetEntry(child_obj); |
if (child_entry != NULL) { |
filler_->SetNamedReference(HeapGraphEdge::kInternal, |
@@ -2103,7 +2133,7 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
collection_->names()->GetName(index), |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
+ IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
} |
} |
@@ -2127,7 +2157,8 @@ void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, |
void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, |
HeapEntry* parent_entry, |
String* reference_name, |
- Object* child_obj) { |
+ Object* child_obj, |
+ int field_offset) { |
HeapEntry* child_entry = GetEntry(child_obj); |
if (child_entry != NULL) { |
HeapGraphEdge::Type type = reference_name->length() > 0 ? |
@@ -2138,16 +2169,15 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, |
collection_->names()->GetName(reference_name), |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
+ IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); |
} |
} |
-void V8HeapExplorer::SetPropertyShortcutReference( |
- HeapObject* parent_obj, |
- HeapEntry* parent_entry, |
- String* reference_name, |
- Object* child_obj) { |
+void V8HeapExplorer::SetPropertyShortcutReference(HeapObject* parent_obj, |
+ HeapEntry* parent_entry, |
+ String* reference_name, |
+ Object* child_obj) { |
HeapEntry* child_entry = GetEntry(child_obj); |
if (child_entry != NULL) { |
filler_->SetNamedReference(HeapGraphEdge::kShortcut, |