Index: src/profile-generator.cc |
diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
index 099b9dfa21e93073b280addfc9deb5c8019c9a95..379ac413f955c8257a209a1cca2001588c402db5 100644 |
--- a/src/profile-generator.cc |
+++ b/src/profile-generator.cc |
@@ -1826,25 +1826,29 @@ class IndexedReferencesExtractor : public ObjectVisitor { |
IndexedReferencesExtractor(V8HeapExplorer* generator, |
HeapObject* parent_obj, |
HeapEntry* parent_entry, |
- HeapObjectsSet* known_references = NULL) |
+ bool process_failure_tags = false) |
: generator_(generator), |
parent_obj_(parent_obj), |
parent_(parent_entry), |
- known_references_(known_references), |
+ process_failure_tags_(process_failure_tags), |
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 (process_failure_tags_ && (*p)->IsFailure()) { |
Vitaly Repeshko
2011/03/17 16:52:00
Please introduce a helper to test for the mark and
mnaganov (inactive)
2011/03/17 17:37:18
Done.
|
+ *p = reinterpret_cast<Object*>( |
+ reinterpret_cast<intptr_t>(*p) |
+ & (~kFailureTagMask | kHeapObjectTag)); |
+ ASSERT((*p)->IsHeapObject()); |
} |
+ generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
} |
} |
private: |
V8HeapExplorer* generator_; |
HeapObject* parent_obj_; |
HeapEntry* parent_; |
- HeapObjectsSet* known_references_; |
+ bool process_failure_tags_; |
Vitaly Repeshko
2011/03/17 16:52:00
Rename to "process_marks_"?
mnaganov (inactive)
2011/03/17 17:37:18
Renamed to process_field_marks_
|
int next_index_; |
}; |
@@ -1853,7 +1857,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 +1871,30 @@ 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(), |
+ js_fun->GetFieldAddress(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, |
+ js_fun->GetFieldAddress( |
+ 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 +1927,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 +1939,17 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, |
switch (descs->GetType(i)) { |
case FIELD: { |
int index = descs->GetFieldIndex(i); |
+ Address offset = js_obj->GetFastPropertyAddress(index); |
SetPropertyReference( |
- js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index)); |
+ js_obj, entry, |
+ descs->GetKey(i), js_obj->FastPropertyAt(index), |
+ offset); |
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 +2009,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)); |
} |
} |
@@ -2040,6 +2060,15 @@ bool V8HeapExplorer::IterateAndExtractReferences( |
} |
+void V8HeapExplorer::MarkAsFailure(Address field) { |
+ if (field != NULL) { |
+ ASSERT(!Memory::Object_at(field)->IsFailure()); |
+ ASSERT(Memory::Object_at(field)->IsHeapObject()); |
+ *field |= kFailureTag; |
+ } |
+} |
+ |
+ |
void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
HeapEntry* parent_entry, |
String* reference_name, |
@@ -2052,7 +2081,6 @@ void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj, |
collection_->names()->GetName(reference_name), |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
} |
} |
@@ -2069,7 +2097,6 @@ void V8HeapExplorer::SetElementReference(HeapObject* parent_obj, |
index, |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
} |
} |
@@ -2077,7 +2104,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, |
+ Address field) { |
Vitaly Repeshko
2011/03/17 16:52:00
You can pass field offset instead of its address a
mnaganov (inactive)
2011/03/17 17:37:18
Done.
|
HeapEntry* child_entry = GetEntry(child_obj); |
if (child_entry != NULL) { |
filler_->SetNamedReference(HeapGraphEdge::kInternal, |
@@ -2086,7 +2114,7 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
reference_name, |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
+ MarkAsFailure(field); |
} |
} |
@@ -2094,7 +2122,8 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
HeapEntry* parent_entry, |
int index, |
- Object* child_obj) { |
+ Object* child_obj, |
+ Address field) { |
HeapEntry* child_entry = GetEntry(child_obj); |
if (child_entry != NULL) { |
filler_->SetNamedReference(HeapGraphEdge::kInternal, |
@@ -2103,7 +2132,7 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, |
collection_->names()->GetName(index), |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
+ MarkAsFailure(field); |
} |
} |
@@ -2127,7 +2156,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, |
+ Address field) { |
HeapEntry* child_entry = GetEntry(child_obj); |
if (child_entry != NULL) { |
HeapGraphEdge::Type type = reference_name->length() > 0 ? |
@@ -2138,7 +2168,7 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, |
collection_->names()->GetName(reference_name), |
child_obj, |
child_entry); |
- known_references_.Insert(child_obj); |
+ MarkAsFailure(field); |
} |
} |