Chromium Code Reviews| 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); |
| } |
| } |