Revision: 20429
Author: [email protected]
Date: Wed Apr 2 11:19:53 2014 UTC
Log: Show references from weak containers as weak in heap snapshots.
BUG=356590
LOG=Y
[email protected], [email protected]
Review URL: https://codereview.chromium.org/213673006
http://code.google.com/p/v8/source/detail?r=20429
Modified:
/branches/bleeding_edge/src/heap-snapshot-generator.cc
/branches/bleeding_edge/src/heap-snapshot-generator.h
/branches/bleeding_edge/test/cctest/test-heap-profiler.cc
=======================================
--- /branches/bleeding_edge/src/heap-snapshot-generator.cc Thu Mar 27
14:19:51 2014 UTC
+++ /branches/bleeding_edge/src/heap-snapshot-generator.cc Wed Apr 2
11:19:53 2014 UTC
@@ -1101,10 +1101,8 @@
};
-void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
- HeapEntry* heap_entry = GetEntry(obj);
- if (heap_entry == NULL) return; // No interest in this object.
- int entry = heap_entry->index();
+bool V8HeapExplorer::ExtractReferencesPass1(int entry, HeapObject* obj) {
+ if (obj->IsFixedArray()) return false; // FixedArrays are processed on
pass 2
if (obj->IsJSGlobalProxy()) {
ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj));
@@ -1114,8 +1112,6 @@
ExtractJSObjectReferences(entry, JSObject::cast(obj));
} else if (obj->IsString()) {
ExtractStringReferences(entry, String::cast(obj));
- } else if (obj->IsContext()) {
- ExtractContextReferences(entry, Context::cast(obj));
} else if (obj->IsMap()) {
ExtractMapReferences(entry, Map::cast(obj));
} else if (obj->IsSharedFunctionInfo()) {
@@ -1137,12 +1133,19 @@
} else if (obj->IsAllocationSite()) {
ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj));
}
- SetInternalReference(obj, entry, "map", obj->map(),
HeapObject::kMapOffset);
+ return true;
+}
- // Extract unvisited fields as hidden references and restore tags
- // of visited fields.
- IndexedReferencesExtractor refs_extractor(this, obj, entry);
- obj->Iterate(&refs_extractor);
+
+bool V8HeapExplorer::ExtractReferencesPass2(int entry, HeapObject* obj) {
+ if (!obj->IsFixedArray()) return false;
+
+ if (obj->IsContext()) {
+ ExtractContextReferences(entry, Context::cast(obj));
+ } else {
+ ExtractFixedArrayReferences(entry, FixedArray::cast(obj));
+ }
+ return true;
}
@@ -1320,6 +1323,7 @@
SetInternalReference(transitions, transitions_entry,
"back_pointer", back_pointer);
TagObject(transitions, "(transition array)");
+ MarkAsWeakContainer(transitions);
SetInternalReference(map, entry,
"transitions", transitions,
Map::kTransitionsOrBackPointerOffset);
@@ -1336,6 +1340,7 @@
"descriptors", descriptors,
Map::kDescriptorsOffset);
+ MarkAsWeakContainer(map->code_cache());
SetInternalReference(map, entry,
"code_cache", map->code_cache(),
Map::kCodeCacheOffset);
@@ -1345,6 +1350,7 @@
"constructor", map->constructor(),
Map::kConstructorOffset);
TagObject(map->dependent_code(), "(dependent code)");
+ MarkAsWeakContainer(map->dependent_code());
SetInternalReference(map, entry,
"dependent_code", map->dependent_code(),
Map::kDependentCodeOffset);
@@ -1506,6 +1512,7 @@
ExtractCellReferences(entry, cell);
SetInternalReference(cell, entry, "type", cell->type(),
PropertyCell::kTypeOffset);
+ MarkAsWeakContainer(cell->dependent_code());
SetInternalReference(cell, entry, "dependent_code",
cell->dependent_code(),
PropertyCell::kDependentCodeOffset);
}
@@ -1517,6 +1524,7 @@
AllocationSite::kTransitionInfoOffset);
SetInternalReference(site, entry, "nested_site", site->nested_site(),
AllocationSite::kNestedSiteOffset);
+ MarkAsWeakContainer(site->dependent_code());
SetInternalReference(site, entry, "dependent_code",
site->dependent_code(),
AllocationSite::kDependentCodeOffset);
// Do not visit weak_next as it is not visited by the StaticVisitor,
@@ -1560,6 +1568,20 @@
filler_->SetNamedReference(HeapGraphEdge::kInternal,
entry, "backing_store", data_entry);
}
+
+
+void V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray*
array) {
+ bool is_weak = weak_containers_.Contains(array);
+ for (int i = 0, l = array->length(); i < l; ++i) {
+ if (is_weak) {
+ SetWeakReference(array, entry,
+ i, array->get(i), array->OffsetOfElementAt(i));
+ } else {
+ SetInternalReference(array, entry,
+ i, array->get(i), array->OffsetOfElementAt(i));
+ }
+ }
+}
void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry)
{
@@ -1833,6 +1855,25 @@
heap_->IterateRoots(&extractor, VISIT_ALL);
extractor.FillReferences(this);
+ // We have to do two passes as sometimes FixedArrays are used
+ // to weakly hold their items, and it's impossible to distinguish
+ // between these cases without processing the array owner first.
+ bool interrupted =
+
IterateAndExtractSinglePass<&V8HeapExplorer::ExtractReferencesPass1>() ||
+
IterateAndExtractSinglePass<&V8HeapExplorer::ExtractReferencesPass2>();
+
+ if (interrupted) {
+ filler_ = NULL;
+ return false;
+ }
+
+ filler_ = NULL;
+ return progress_->ProgressReport(true);
+}
+
+
+template<V8HeapExplorer::ExtractReferencesMethod extractor>
+bool V8HeapExplorer::IterateAndExtractSinglePass() {
// Now iterate the whole heap.
bool interrupted = false;
HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable);
@@ -1840,18 +1881,22 @@
for (HeapObject* obj = iterator.next();
obj != NULL;
obj = iterator.next(), progress_->ProgressStep()) {
- if (!interrupted) {
- ExtractReferences(obj);
- if (!progress_->ProgressReport(false)) interrupted = true;
+ if (interrupted) continue;
+
+ HeapEntry* heap_entry = GetEntry(obj);
+ int entry = heap_entry->index();
+ if ((this->*extractor)(entry, obj)) {
+ SetInternalReference(obj, entry,
+ "map", obj->map(), HeapObject::kMapOffset);
+ // Extract unvisited fields as hidden references and restore tags
+ // of visited fields.
+ IndexedReferencesExtractor refs_extractor(this, obj, entry);
+ obj->Iterate(&refs_extractor);
}
- }
- if (interrupted) {
- filler_ = NULL;
- return false;
- }
- filler_ = NULL;
- return progress_->ProgressReport(true);
+ if (!progress_->ProgressReport(false)) interrupted = true;
+ }
+ return interrupted;
}
@@ -1985,6 +2030,24 @@
}
IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
}
+
+
+void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
+ int parent_entry,
+ int index,
+ Object* child_obj,
+ int field_offset) {
+ ASSERT(parent_entry == GetEntry(parent_obj)->index());
+ HeapEntry* child_entry = GetEntry(child_obj);
+ if (child_entry == NULL) return;
+ if (IsEssentialObject(child_obj)) {
+ filler_->SetNamedReference(HeapGraphEdge::kWeak,
+ parent_entry,
+ names_->GetFormatted("%d", index),
+ child_entry);
+ }
+ IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
+}
void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
@@ -2112,6 +2175,13 @@
}
}
}
+
+
+void V8HeapExplorer::MarkAsWeakContainer(Object* object) {
+ if (IsEssentialObject(object) && object->IsFixedArray()) {
+ weak_containers_.Insert(object);
+ }
+}
class GlobalObjectsEnumerator : public ObjectVisitor {
@@ -2504,7 +2574,7 @@
debug_heap->Verify();
#endif
- SetProgressTotal(1); // 1 pass.
+ SetProgressTotal(2); // 2 passes.
#ifdef VERIFY_HEAP
debug_heap->Verify();
=======================================
--- /branches/bleeding_edge/src/heap-snapshot-generator.h Thu Mar 13
07:48:42 2014 UTC
+++ /branches/bleeding_edge/src/heap-snapshot-generator.h Wed Apr 2
11:19:53 2014 UTC
@@ -376,6 +376,9 @@
static HeapObject* const kInternalRootObject;
private:
+ typedef bool (V8HeapExplorer::*ExtractReferencesMethod)(int entry,
+ HeapObject*
object);
+
HeapEntry* AddEntry(HeapObject* object);
HeapEntry* AddEntry(HeapObject* object,
HeapEntry::Type type,
@@ -383,7 +386,11 @@
const char* GetSystemEntryName(HeapObject* object);
- void ExtractReferences(HeapObject* obj);
+ template<V8HeapExplorer::ExtractReferencesMethod extractor>
+ bool IterateAndExtractSinglePass();
+
+ bool ExtractReferencesPass1(int entry, HeapObject* obj);
+ bool ExtractReferencesPass2(int entry, HeapObject* obj);
void ExtractJSGlobalProxyReferences(int entry, JSGlobalProxy* proxy);
void ExtractJSObjectReferences(int entry, JSObject* js_obj);
void ExtractStringReferences(int entry, String* obj);
@@ -400,12 +407,14 @@
void ExtractPropertyCellReferences(int entry, PropertyCell* cell);
void ExtractAllocationSiteReferences(int entry, AllocationSite* site);
void ExtractJSArrayBufferReferences(int entry, JSArrayBuffer* buffer);
+ void ExtractFixedArrayReferences(int entry, FixedArray* array);
void ExtractClosureReferences(JSObject* js_obj, int entry);
void ExtractPropertyReferences(JSObject* js_obj, int entry);
bool ExtractAccessorPairProperty(JSObject* js_obj, int entry,
Object* key, Object* callback_obj);
void ExtractElementReferences(JSObject* js_obj, int entry);
void ExtractInternalReferences(JSObject* js_obj, int entry);
+
bool IsEssentialObject(Object* object);
void SetContextReference(HeapObject* parent_obj,
int parent,
@@ -437,6 +446,11 @@
void SetWeakReference(HeapObject* parent_obj,
int parent,
const char* reference_name,
+ Object* child_obj,
+ int field_offset);
+ void SetWeakReference(HeapObject* parent_obj,
+ int parent,
+ int index,
Object* child_obj,
int field_offset);
void SetPropertyReference(HeapObject* parent_obj,
@@ -452,6 +466,7 @@
VisitorSynchronization::SyncTag tag, bool is_weak, Object* child);
const char* GetStrongGcSubrootName(Object* object);
void TagObject(Object* obj, const char* tag);
+ void MarkAsWeakContainer(Object* object);
HeapEntry* GetEntry(Object* obj);
@@ -467,6 +482,7 @@
HeapObjectsSet objects_tags_;
HeapObjectsSet strong_gc_subroot_names_;
HeapObjectsSet user_roots_;
+ HeapObjectsSet weak_containers_;
v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_;
static HeapObject* const kGcRootsObject;
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Fri Mar 7
17:20:03 2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Wed Apr 2
11:19:53 2014 UTC
@@ -2506,6 +2506,41 @@
GetProperty(box_node, v8::HeapGraphEdge::kInternal, "value");
CHECK_NE(NULL, box_value);
}
+
+
+TEST(WeakContainers) {
+ i::FLAG_allow_natives_syntax = true;
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ if (!CcTest::i_isolate()->use_crankshaft()) return;
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+ CompileRun(
+ "function foo(a) { return a.x; }\n"
+ "obj = {x : 123};\n"
+ "foo(obj);\n"
+ "foo(obj);\n"
+ "%OptimizeFunctionOnNextCall(foo);\n"
+ "foo(obj);\n");
+ const v8::HeapSnapshot* snapshot =
+ heap_profiler->TakeHeapSnapshot(v8_str("snapshot"));
+ CHECK(ValidateSnapshot(snapshot));
+ const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+ const v8::HeapGraphNode* obj =
+ GetProperty(global, v8::HeapGraphEdge::kProperty, "obj");
+ CHECK_NE(NULL, obj);
+ const v8::HeapGraphNode* map =
+ GetProperty(obj, v8::HeapGraphEdge::kInternal, "map");
+ CHECK_NE(NULL, map);
+ const v8::HeapGraphNode* dependent_code =
+ GetProperty(map, v8::HeapGraphEdge::kInternal, "dependent_code");
+ if (!dependent_code) return;
+ int count = dependent_code->GetChildrenCount();
+ CHECK_NE(0, count);
+ for (int i = 0; i < count; ++i) {
+ const v8::HeapGraphEdge* prop = dependent_code->GetChild(i);
+ CHECK_EQ(v8::HeapGraphEdge::kWeak, prop->GetType());
+ }
+}
static inline i::Address ToAddress(int n) {
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.