Index: src/profile-generator.cc |
diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
index 099b9dfa21e93073b280addfc9deb5c8019c9a95..a63901f1736e42a27dc623df81b96d056b8372ae 100644 |
--- a/src/profile-generator.cc |
+++ b/src/profile-generator.cc |
@@ -1826,25 +1826,40 @@ 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()) { |
+ intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask; |
+ *field = reinterpret_cast<Object*>(untagged | kHeapObjectTag); |
+ 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 +1868,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 +1882,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 +1937,6 @@ void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, |
SetClosureReference(js_obj, entry, local_name, context->get(idx)); |
} |
} |
- SetInternalReference(js_obj, entry, "code", func->shared()); |
} |
} |
@@ -1924,13 +1949,22 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, |
switch (descs->GetType(i)) { |
case FIELD: { |
int index = descs->GetFieldIndex(i); |
- SetPropertyReference( |
- js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index)); |
+ if (index - js_obj->map()->inobject_properties() < 0) { |
Vitaly Repeshko
2011/03/18 12:36:03
nit: It's probably more natural to write "index <
mnaganov (inactive)
2011/03/18 12:46:34
Sure. I also have noted this afterwards.
|
+ SetPropertyReference( |
+ js_obj, entry, |
+ descs->GetKey(i), js_obj->InObjectPropertyAt(index), |
+ js_obj->GetInObjectPropertyOffset(index)); |
+ } else { |
+ SetPropertyReference( |
+ js_obj, entry, |
+ descs->GetKey(i), js_obj->FastPropertyAt(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 +2024,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 +2087,6 @@ void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
collection_->names()->GetName(reference_name), |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
} |
} |
@@ -2069,7 +2103,6 @@ void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, |
index, |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
} |
} |
@@ -2077,7 +2110,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 +2120,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 +2128,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 +2138,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 +2162,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 +2174,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, |