Commit bd5fafd5 authored by alph@chromium.org's avatar alph@chromium.org

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
parent eac9b219
...@@ -974,6 +974,8 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) { ...@@ -974,6 +974,8 @@ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj)); ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj));
} else if (obj->IsScript()) { } else if (obj->IsScript()) {
ExtractScriptReferences(entry, Script::cast(obj)); ExtractScriptReferences(entry, Script::cast(obj));
} else if (obj->IsAccessorPair()) {
ExtractAccessorPairReferences(entry, AccessorPair::cast(obj));
} else if (obj->IsCodeCache()) { } else if (obj->IsCodeCache()) {
ExtractCodeCacheReferences(entry, CodeCache::cast(obj)); ExtractCodeCacheReferences(entry, CodeCache::cast(obj));
} else if (obj->IsCode()) { } else if (obj->IsCode()) {
...@@ -1242,6 +1244,15 @@ void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { ...@@ -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( void V8HeapExplorer::ExtractCodeCacheReferences(
int entry, CodeCache* code_cache) { int entry, CodeCache* code_cache) {
TagObject(code_cache->default_cache(), "(default code cache)"); TagObject(code_cache->default_cache(), "(default code cache)");
...@@ -1353,21 +1364,11 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { ...@@ -1353,21 +1364,11 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
js_obj, entry, js_obj, entry,
descs->GetKey(i), descs->GetConstantFunction(i)); descs->GetKey(i), descs->GetConstantFunction(i));
break; break;
case CALLBACKS: { case CALLBACKS:
Object* callback_obj = descs->GetValue(i); ExtractAccessorPairProperty(
if (callback_obj->IsAccessorPair()) { js_obj, entry,
AccessorPair* accessors = AccessorPair::cast(callback_obj); descs->GetKey(i), descs->GetValue(i));
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");
}
}
break; break;
}
case NORMAL: // only in slow mode case NORMAL: // only in slow mode
case HANDLER: // only in lookup results, not in descriptors case HANDLER: // only in lookup results, not in descriptors
case INTERCEPTOR: // 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) { ...@@ -1389,18 +1390,35 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
Object* value = target->IsPropertyCell() Object* value = target->IsPropertyCell()
? PropertyCell::cast(target)->value() ? PropertyCell::cast(target)->value()
: target; : target;
if (k != heap_->hidden_string()) { if (k == heap_->hidden_string()) {
SetPropertyReference(js_obj, entry, String::cast(k), value);
} else {
TagObject(value, "(hidden properties)"); TagObject(value, "(hidden properties)");
SetInternalReference(js_obj, entry, "hidden_properties", value); 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) { void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) {
if (js_obj->HasFastObjectElements()) { if (js_obj->HasFastObjectElements()) {
FixedArray* elements = FixedArray::cast(js_obj->elements()); FixedArray* elements = FixedArray::cast(js_obj->elements());
......
...@@ -462,12 +462,15 @@ class V8HeapExplorer : public HeapEntriesAllocator { ...@@ -462,12 +462,15 @@ class V8HeapExplorer : public HeapEntriesAllocator {
void ExtractSharedFunctionInfoReferences(int entry, void ExtractSharedFunctionInfoReferences(int entry,
SharedFunctionInfo* shared); SharedFunctionInfo* shared);
void ExtractScriptReferences(int entry, Script* script); void ExtractScriptReferences(int entry, Script* script);
void ExtractAccessorPairReferences(int entry, AccessorPair* accessors);
void ExtractCodeCacheReferences(int entry, CodeCache* code_cache); void ExtractCodeCacheReferences(int entry, CodeCache* code_cache);
void ExtractCodeReferences(int entry, Code* code); void ExtractCodeReferences(int entry, Code* code);
void ExtractCellReferences(int entry, Cell* cell); void ExtractCellReferences(int entry, Cell* cell);
void ExtractPropertyCellReferences(int entry, PropertyCell* cell); void ExtractPropertyCellReferences(int entry, PropertyCell* cell);
void ExtractClosureReferences(JSObject* js_obj, int entry); void ExtractClosureReferences(JSObject* js_obj, int entry);
void ExtractPropertyReferences(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 ExtractElementReferences(JSObject* js_obj, int entry);
void ExtractInternalReferences(JSObject* js_obj, int entry); void ExtractInternalReferences(JSObject* js_obj, int entry);
bool IsEssentialObject(Object* object); bool IsEssentialObject(Object* object);
......
...@@ -1507,7 +1507,7 @@ TEST(GetConstructorName) { ...@@ -1507,7 +1507,7 @@ TEST(GetConstructorName) {
} }
TEST(FastCaseGetter) { TEST(FastCaseAccessors) {
LocalContext env; LocalContext env;
v8::HandleScope scope(env->GetIsolate()); v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
...@@ -1520,21 +1520,58 @@ TEST(FastCaseGetter) { ...@@ -1520,21 +1520,58 @@ TEST(FastCaseGetter) {
" return this.value_ = value;\n" " return this.value_ = value;\n"
"});\n"); "});\n");
const v8::HeapSnapshot* snapshot = const v8::HeapSnapshot* snapshot =
heap_profiler->TakeHeapSnapshot(v8_str("fastCaseGetter")); heap_profiler->TakeHeapSnapshot(v8_str("fastCaseAccessors"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot); const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_NE(NULL, global); CHECK_NE(NULL, global);
const v8::HeapGraphNode* obj1 = const v8::HeapGraphNode* obj1 =
GetProperty(global, v8::HeapGraphEdge::kProperty, "obj1"); GetProperty(global, v8::HeapGraphEdge::kProperty, "obj1");
CHECK_NE(NULL, obj1); CHECK_NE(NULL, obj1);
const v8::HeapGraphNode* getterFunction = const v8::HeapGraphNode* func;
GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter"); func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get propWithGetter");
CHECK_NE(NULL, getterFunction); CHECK_NE(NULL, func);
const v8::HeapGraphNode* setterFunction = func = GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set propWithGetter");
GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set-propWithSetter"); CHECK_EQ(NULL, func);
CHECK_NE(NULL, setterFunction); 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) { TEST(HiddenPropertiesFastCase) {
LocalContext env; LocalContext env;
v8::HandleScope scope(env->GetIsolate()); v8::HandleScope scope(env->GetIsolate());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment