From bd5fafd58a3fea315cb954b5c9fb14539c6ed034 Mon Sep 17 00:00:00 2001 From: "alph@chromium.org" Date: Tue, 25 Jun 2013 11:55:33 +0000 Subject: [PATCH] Handle AccessorPair struct in heap snapshot. R=svenpanne@chromium.org, yurys@chromium.org Review URL: https://codereview.chromium.org/17616002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15320 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap-snapshot-generator.cc | 52 +++++++++++++++++++++++++------------- src/heap-snapshot-generator.h | 3 +++ test/cctest/test-heap-profiler.cc | 53 +++++++++++++++++++++++++++++++++------ 3 files changed, 83 insertions(+), 25 deletions(-) diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc index 217d1ca..882f706 100644 --- a/src/heap-snapshot-generator.cc +++ b/src/heap-snapshot-generator.cc @@ -974,6 +974,8 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) { ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj)); } else if (obj->IsScript()) { ExtractScriptReferences(entry, Script::cast(obj)); + } else if (obj->IsAccessorPair()) { + ExtractAccessorPairReferences(entry, AccessorPair::cast(obj)); } else if (obj->IsCodeCache()) { ExtractCodeCacheReferences(entry, CodeCache::cast(obj)); } else if (obj->IsCode()) { @@ -1242,6 +1244,15 @@ void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { } +void V8HeapExplorer::ExtractAccessorPairReferences( + int entry, AccessorPair* accessors) { + SetInternalReference(accessors, entry, "getter", accessors->getter(), + AccessorPair::kGetterOffset); + SetInternalReference(accessors, entry, "setter", accessors->setter(), + AccessorPair::kSetterOffset); +} + + void V8HeapExplorer::ExtractCodeCacheReferences( int entry, CodeCache* code_cache) { TagObject(code_cache->default_cache(), "(default code cache)"); @@ -1353,21 +1364,11 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { js_obj, entry, descs->GetKey(i), descs->GetConstantFunction(i)); break; - case CALLBACKS: { - Object* callback_obj = descs->GetValue(i); - if (callback_obj->IsAccessorPair()) { - AccessorPair* accessors = AccessorPair::cast(callback_obj); - if (Object* getter = accessors->getter()) { - SetPropertyReference(js_obj, entry, descs->GetKey(i), - getter, "get-%s"); - } - if (Object* setter = accessors->setter()) { - SetPropertyReference(js_obj, entry, descs->GetKey(i), - setter, "set-%s"); - } - } + case CALLBACKS: + ExtractAccessorPairProperty( + js_obj, entry, + descs->GetKey(i), descs->GetValue(i)); break; - } case NORMAL: // only in slow mode case HANDLER: // only in lookup results, not in descriptors case INTERCEPTOR: // only in lookup results, not in descriptors @@ -1389,18 +1390,35 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { Object* value = target->IsPropertyCell() ? PropertyCell::cast(target)->value() : target; - if (k != heap_->hidden_string()) { - SetPropertyReference(js_obj, entry, String::cast(k), value); - } else { + if (k == heap_->hidden_string()) { TagObject(value, "(hidden properties)"); SetInternalReference(js_obj, entry, "hidden_properties", value); + continue; } + if (ExtractAccessorPairProperty(js_obj, entry, k, value)) continue; + SetPropertyReference(js_obj, entry, String::cast(k), value); } } } } +bool V8HeapExplorer::ExtractAccessorPairProperty( + JSObject* js_obj, int entry, Object* key, Object* callback_obj) { + if (!callback_obj->IsAccessorPair()) return false; + AccessorPair* accessors = AccessorPair::cast(callback_obj); + Object* getter = accessors->getter(); + if (!getter->IsOddball()) { + SetPropertyReference(js_obj, entry, String::cast(key), getter, "get %s"); + } + Object* setter = accessors->setter(); + if (!setter->IsOddball()) { + SetPropertyReference(js_obj, entry, String::cast(key), setter, "set %s"); + } + return true; +} + + void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) { if (js_obj->HasFastObjectElements()) { FixedArray* elements = FixedArray::cast(js_obj->elements()); diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h index c9a82f0..d942bbe 100644 --- a/src/heap-snapshot-generator.h +++ b/src/heap-snapshot-generator.h @@ -462,12 +462,15 @@ class V8HeapExplorer : public HeapEntriesAllocator { void ExtractSharedFunctionInfoReferences(int entry, SharedFunctionInfo* shared); void ExtractScriptReferences(int entry, Script* script); + void ExtractAccessorPairReferences(int entry, AccessorPair* accessors); void ExtractCodeCacheReferences(int entry, CodeCache* code_cache); void ExtractCodeReferences(int entry, Code* code); void ExtractCellReferences(int entry, Cell* cell); void ExtractPropertyCellReferences(int entry, PropertyCell* cell); 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); diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 33b0fb9..2ca6e29 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -1507,7 +1507,7 @@ TEST(GetConstructorName) { } -TEST(FastCaseGetter) { +TEST(FastCaseAccessors) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); @@ -1520,21 +1520,58 @@ TEST(FastCaseGetter) { " return this.value_ = value;\n" "});\n"); const v8::HeapSnapshot* snapshot = - heap_profiler->TakeHeapSnapshot(v8_str("fastCaseGetter")); + heap_profiler->TakeHeapSnapshot(v8_str("fastCaseAccessors")); const v8::HeapGraphNode* global = GetGlobalObject(snapshot); CHECK_NE(NULL, global); const v8::HeapGraphNode* obj1 = GetProperty(global, v8::HeapGraphEdge::kProperty, "obj1"); CHECK_NE(NULL, obj1); - const v8::HeapGraphNode* getterFunction = - GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter"); - CHECK_NE(NULL, getterFunction); - const v8::HeapGraphNode* setterFunction = - GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set-propWithSetter"); - CHECK_NE(NULL, setterFunction); + const v8::HeapGraphNode* func; + func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get propWithGetter"); + CHECK_NE(NULL, func); + func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set propWithGetter"); + CHECK_EQ(NULL, func); + func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set propWithSetter"); + CHECK_NE(NULL, func); + func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get propWithSetter"); + CHECK_EQ(NULL, func); } + +TEST(SlowCaseAccessors) { + LocalContext env; + v8::HandleScope scope(env->GetIsolate()); + v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); + + CompileRun("var obj1 = {};\n" + "for (var i = 0; i < 100; ++i) obj1['z' + i] = {};" + "obj1.__defineGetter__('propWithGetter', function Y() {\n" + " return 42;\n" + "});\n" + "obj1.__defineSetter__('propWithSetter', function Z(value) {\n" + " return this.value_ = value;\n" + "});\n"); + const v8::HeapSnapshot* snapshot = + heap_profiler->TakeHeapSnapshot(v8_str("slowCaseAccessors")); + + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_NE(NULL, global); + const v8::HeapGraphNode* obj1 = + GetProperty(global, v8::HeapGraphEdge::kProperty, "obj1"); + CHECK_NE(NULL, obj1); + const v8::HeapGraphNode* func; + func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get propWithGetter"); + CHECK_NE(NULL, func); + func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set propWithGetter"); + CHECK_EQ(NULL, func); + func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set propWithSetter"); + CHECK_NE(NULL, func); + func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get propWithSetter"); + CHECK_EQ(NULL, func); +} + + TEST(HiddenPropertiesFastCase) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); -- 2.7.4