| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 | 729 |
| 730 TestJSONStream stream; | 730 TestJSONStream stream; |
| 731 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); | 731 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); |
| 732 CHECK_GT(stream.size(), 0); | 732 CHECK_GT(stream.size(), 0); |
| 733 CHECK_EQ(1, stream.eos_signaled()); | 733 CHECK_EQ(1, stream.eos_signaled()); |
| 734 i::ScopedVector<char> json(stream.size()); | 734 i::ScopedVector<char> json(stream.size()); |
| 735 stream.WriteTo(json); | 735 stream.WriteTo(json); |
| 736 | 736 |
| 737 // Verify that snapshot string is valid JSON. | 737 // Verify that snapshot string is valid JSON. |
| 738 AsciiResource json_res(json); | 738 AsciiResource json_res(json); |
| 739 v8::Local<v8::String> json_string = v8::String::NewExternal(&json_res); | 739 v8::Local<v8::String> json_string = |
| 740 v8::String::NewExternal(env->GetIsolate(), &json_res); |
| 740 env->Global()->Set(v8_str("json_snapshot"), json_string); | 741 env->Global()->Set(v8_str("json_snapshot"), json_string); |
| 741 v8::Local<v8::Value> snapshot_parse_result = CompileRun( | 742 v8::Local<v8::Value> snapshot_parse_result = CompileRun( |
| 742 "var parsed = JSON.parse(json_snapshot); true;"); | 743 "var parsed = JSON.parse(json_snapshot); true;"); |
| 743 CHECK(!snapshot_parse_result.IsEmpty()); | 744 CHECK(!snapshot_parse_result.IsEmpty()); |
| 744 | 745 |
| 745 // Verify that snapshot object has required fields. | 746 // Verify that snapshot object has required fields. |
| 746 v8::Local<v8::Object> parsed_snapshot = | 747 v8::Local<v8::Object> parsed_snapshot = |
| 747 env->Global()->Get(v8_str("parsed"))->ToObject(); | 748 env->Global()->Get(v8_str("parsed"))->ToObject(); |
| 748 CHECK(parsed_snapshot->Has(v8_str("snapshot"))); | 749 CHECK(parsed_snapshot->Has(v8_str("snapshot"))); |
| 749 CHECK(parsed_snapshot->Has(v8_str("nodes"))); | 750 CHECK(parsed_snapshot->Has(v8_str("nodes"))); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 // Single chunk of data with 0 left entries expected in update. | 998 // Single chunk of data with 0 left entries expected in update. |
| 998 TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler); | 999 TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler); |
| 999 CHECK_EQ(1, stats_update.intervals_count()); | 1000 CHECK_EQ(1, stats_update.intervals_count()); |
| 1000 CHECK_EQ(1, stats_update.updates_written()); | 1001 CHECK_EQ(1, stats_update.updates_written()); |
| 1001 CHECK_EQ(0, stats_update.entries_size()); | 1002 CHECK_EQ(0, stats_update.entries_size()); |
| 1002 CHECK_EQ(0, stats_update.entries_count()); | 1003 CHECK_EQ(0, stats_update.entries_count()); |
| 1003 // The only string from the second interval was released. | 1004 // The only string from the second interval was released. |
| 1004 CHECK_EQ(2, stats_update.first_interval_index()); | 1005 CHECK_EQ(2, stats_update.first_interval_index()); |
| 1005 } | 1006 } |
| 1006 | 1007 |
| 1007 v8::Local<v8::Array> array = v8::Array::New(); | 1008 v8::Local<v8::Array> array = v8::Array::New(env->GetIsolate()); |
| 1008 CHECK_EQ(0, array->Length()); | 1009 CHECK_EQ(0, array->Length()); |
| 1009 // Force array's buffer allocation. | 1010 // Force array's buffer allocation. |
| 1010 array->Set(2, v8_num(7)); | 1011 array->Set(2, v8_num(7)); |
| 1011 | 1012 |
| 1012 uint32_t entries_size; | 1013 uint32_t entries_size; |
| 1013 { | 1014 { |
| 1014 // Single chunk of data with 2 entries expected in update. | 1015 // Single chunk of data with 2 entries expected in update. |
| 1015 TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler); | 1016 TestStatsStream stats_update = GetHeapStatsUpdate(heap_profiler); |
| 1016 CHECK_EQ(1, stats_update.intervals_count()); | 1017 CHECK_EQ(1, stats_update.intervals_count()); |
| 1017 CHECK_EQ(1, stats_update.updates_written()); | 1018 CHECK_EQ(1, stats_update.updates_written()); |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1573 v8::HandleScope scope(env->GetIsolate()); | 1574 v8::HandleScope scope(env->GetIsolate()); |
| 1574 CHECK(prop->GetHeapValue()->IsObject()); | 1575 CHECK(prop->GetHeapValue()->IsObject()); |
| 1575 } | 1576 } |
| 1576 CompileRun("delete a.p;"); | 1577 CompileRun("delete a.p;"); |
| 1577 CHECK(prop->GetHeapValue()->IsUndefined()); | 1578 CHECK(prop->GetHeapValue()->IsUndefined()); |
| 1578 } | 1579 } |
| 1579 | 1580 |
| 1580 | 1581 |
| 1581 static int StringCmp(const char* ref, i::String* act) { | 1582 static int StringCmp(const char* ref, i::String* act) { |
| 1582 i::SmartArrayPointer<char> s_act = act->ToCString(); | 1583 i::SmartArrayPointer<char> s_act = act->ToCString(); |
| 1583 int result = strcmp(ref, *s_act); | 1584 int result = strcmp(ref, s_act.get()); |
| 1584 if (result != 0) | 1585 if (result != 0) |
| 1585 fprintf(stderr, "Expected: \"%s\", Actual: \"%s\"\n", ref, *s_act); | 1586 fprintf(stderr, "Expected: \"%s\", Actual: \"%s\"\n", ref, s_act.get()); |
| 1586 return result; | 1587 return result; |
| 1587 } | 1588 } |
| 1588 | 1589 |
| 1589 | 1590 |
| 1590 TEST(GetConstructorName) { | 1591 TEST(GetConstructorName) { |
| 1591 LocalContext env; | 1592 LocalContext env; |
| 1592 v8::HandleScope scope(env->GetIsolate()); | 1593 v8::HandleScope scope(env->GetIsolate()); |
| 1593 | 1594 |
| 1594 CompileRun( | 1595 CompileRun( |
| 1595 "function Constructor1() {};\n" | 1596 "function Constructor1() {};\n" |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1755 const v8::HeapGraphNode* gc_roots = GetNode( | 1756 const v8::HeapGraphNode* gc_roots = GetNode( |
| 1756 snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "(GC roots)"); | 1757 snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "(GC roots)"); |
| 1757 CHECK_NE(NULL, gc_roots); | 1758 CHECK_NE(NULL, gc_roots); |
| 1758 const v8::HeapGraphNode* global_handles = GetNode( | 1759 const v8::HeapGraphNode* global_handles = GetNode( |
| 1759 gc_roots, v8::HeapGraphNode::kSynthetic, "(Global handles)"); | 1760 gc_roots, v8::HeapGraphNode::kSynthetic, "(Global handles)"); |
| 1760 CHECK_NE(NULL, global_handles); | 1761 CHECK_NE(NULL, global_handles); |
| 1761 return HasWeakEdge(global_handles); | 1762 return HasWeakEdge(global_handles); |
| 1762 } | 1763 } |
| 1763 | 1764 |
| 1764 | 1765 |
| 1765 static void PersistentHandleCallback(v8::Isolate* isolate, | 1766 static void PersistentHandleCallback( |
| 1766 v8::Persistent<v8::Value>* handle, | 1767 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) { |
| 1767 void*) { | 1768 data.GetParameter()->Reset(); |
| 1768 handle->Reset(); | 1769 delete data.GetParameter(); |
| 1769 } | 1770 } |
| 1770 | 1771 |
| 1771 | 1772 |
| 1772 TEST(WeakGlobalHandle) { | 1773 TEST(WeakGlobalHandle) { |
| 1773 LocalContext env; | 1774 LocalContext env; |
| 1774 v8::HandleScope scope(env->GetIsolate()); | 1775 v8::HandleScope scope(env->GetIsolate()); |
| 1775 | 1776 |
| 1776 CHECK(!HasWeakGlobalHandle()); | 1777 CHECK(!HasWeakGlobalHandle()); |
| 1777 | 1778 |
| 1778 v8::Persistent<v8::Object> handle(env->GetIsolate(), v8::Object::New()); | 1779 v8::Persistent<v8::Object>* handle = |
| 1779 handle.MakeWeak<v8::Value, void>(NULL, PersistentHandleCallback); | 1780 new v8::Persistent<v8::Object>(env->GetIsolate(), v8::Object::New()); |
| 1781 handle->SetWeak(handle, PersistentHandleCallback); |
| 1780 | 1782 |
| 1781 CHECK(HasWeakGlobalHandle()); | 1783 CHECK(HasWeakGlobalHandle()); |
| 1782 } | 1784 } |
| 1783 | 1785 |
| 1784 | 1786 |
| 1785 TEST(SfiAndJsFunctionWeakRefs) { | 1787 TEST(SfiAndJsFunctionWeakRefs) { |
| 1786 LocalContext env; | 1788 LocalContext env; |
| 1787 v8::HandleScope scope(env->GetIsolate()); | 1789 v8::HandleScope scope(env->GetIsolate()); |
| 1788 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); | 1790 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
| 1789 | 1791 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1929 const v8::HeapGraphNode* ok_object = | 1931 const v8::HeapGraphNode* ok_object = |
| 1930 GetProperty(global, v8::HeapGraphEdge::kProperty, "ok"); | 1932 GetProperty(global, v8::HeapGraphEdge::kProperty, "ok"); |
| 1931 CHECK_NE(NULL, ok_object); | 1933 CHECK_NE(NULL, ok_object); |
| 1932 const v8::HeapGraphNode* context_object = | 1934 const v8::HeapGraphNode* context_object = |
| 1933 GetProperty(ok_object, v8::HeapGraphEdge::kInternal, "context"); | 1935 GetProperty(ok_object, v8::HeapGraphEdge::kInternal, "context"); |
| 1934 CHECK_NE(NULL, context_object); | 1936 CHECK_NE(NULL, context_object); |
| 1935 // Check the objects are not duplicated in the context. | 1937 // Check the objects are not duplicated in the context. |
| 1936 CHECK_EQ(v8::internal::Context::MIN_CONTEXT_SLOTS + num_objects - 1, | 1938 CHECK_EQ(v8::internal::Context::MIN_CONTEXT_SLOTS + num_objects - 1, |
| 1937 context_object->GetChildrenCount()); | 1939 context_object->GetChildrenCount()); |
| 1938 // Check all the objects have got their names. | 1940 // Check all the objects have got their names. |
| 1939 // ... well check just every 8th because otherwise it's too slow in debug. | 1941 // ... well check just every 15th because otherwise it's too slow in debug. |
| 1940 for (int i = 0; i < num_objects - 1; i += 8) { | 1942 for (int i = 0; i < num_objects - 1; i += 15) { |
| 1941 i::EmbeddedVector<char, 100> var_name; | 1943 i::EmbeddedVector<char, 100> var_name; |
| 1942 i::OS::SNPrintF(var_name, "f_%d", i); | 1944 i::OS::SNPrintF(var_name, "f_%d", i); |
| 1943 const v8::HeapGraphNode* f_object = GetProperty( | 1945 const v8::HeapGraphNode* f_object = GetProperty( |
| 1944 context_object, v8::HeapGraphEdge::kContextVariable, var_name.start()); | 1946 context_object, v8::HeapGraphEdge::kContextVariable, var_name.start()); |
| 1945 CHECK_NE(NULL, f_object); | 1947 CHECK_NE(NULL, f_object); |
| 1946 } | 1948 } |
| 1947 } | 1949 } |
| 1948 | 1950 |
| 1949 | 1951 |
| 1950 TEST(AllocationSitesAreVisible) { | 1952 TEST(AllocationSitesAreVisible) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2014 GetProperty(foo_func, v8::HeapGraphEdge::kInternal, "code"); | 2016 GetProperty(foo_func, v8::HeapGraphEdge::kInternal, "code"); |
| 2015 CHECK_NE(NULL, code); | 2017 CHECK_NE(NULL, code); |
| 2016 } | 2018 } |
| 2017 | 2019 |
| 2018 | 2020 |
| 2019 | 2021 |
| 2020 class HeapProfilerExtension : public v8::Extension { | 2022 class HeapProfilerExtension : public v8::Extension { |
| 2021 public: | 2023 public: |
| 2022 static const char* kName; | 2024 static const char* kName; |
| 2023 HeapProfilerExtension() : v8::Extension(kName, kSource) { } | 2025 HeapProfilerExtension() : v8::Extension(kName, kSource) { } |
| 2024 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 2026 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate( |
| 2027 v8::Isolate* isolate, |
| 2025 v8::Handle<v8::String> name); | 2028 v8::Handle<v8::String> name); |
| 2026 static void FindUntrackedObjects( | 2029 static void FindUntrackedObjects( |
| 2027 const v8::FunctionCallbackInfo<v8::Value>& args); | 2030 const v8::FunctionCallbackInfo<v8::Value>& args); |
| 2028 private: | 2031 private: |
| 2029 static const char* kSource; | 2032 static const char* kSource; |
| 2030 }; | 2033 }; |
| 2031 | 2034 |
| 2032 const char* HeapProfilerExtension::kName = "v8/heap-profiler"; | 2035 const char* HeapProfilerExtension::kName = "v8/heap-profiler"; |
| 2033 | 2036 |
| 2034 | 2037 |
| 2035 const char* HeapProfilerExtension::kSource = | 2038 const char* HeapProfilerExtension::kSource = |
| 2036 "native function findUntrackedObjects();"; | 2039 "native function findUntrackedObjects();"; |
| 2037 | 2040 |
| 2038 | 2041 |
| 2039 v8::Handle<v8::FunctionTemplate> HeapProfilerExtension::GetNativeFunction( | 2042 v8::Handle<v8::FunctionTemplate> |
| 2040 v8::Handle<v8::String> name) { | 2043 HeapProfilerExtension::GetNativeFunctionTemplate(v8::Isolate* isolate, |
| 2041 if (name->Equals(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), | 2044 v8::Handle<v8::String> name) { |
| 2042 "findUntrackedObjects"))) { | 2045 if (name->Equals(v8::String::NewFromUtf8(isolate, "findUntrackedObjects"))) { |
| 2043 return v8::FunctionTemplate::New( | 2046 return v8::FunctionTemplate::New( |
| 2044 HeapProfilerExtension::FindUntrackedObjects); | 2047 HeapProfilerExtension::FindUntrackedObjects); |
| 2045 } else { | 2048 } else { |
| 2046 CHECK(false); | 2049 CHECK(false); |
| 2047 return v8::Handle<v8::FunctionTemplate>(); | 2050 return v8::Handle<v8::FunctionTemplate>(); |
| 2048 } | 2051 } |
| 2049 } | 2052 } |
| 2050 | 2053 |
| 2051 | 2054 |
| 2052 void HeapProfilerExtension::FindUntrackedObjects( | 2055 void HeapProfilerExtension::FindUntrackedObjects( |
| 2053 const v8::FunctionCallbackInfo<v8::Value>& args) { | 2056 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 2054 i::HeapProfiler* heap_profiler = | 2057 i::HeapProfiler* heap_profiler = |
| 2055 reinterpret_cast<i::HeapProfiler*>(args.GetIsolate()->GetHeapProfiler()); | 2058 reinterpret_cast<i::HeapProfiler*>(args.GetIsolate()->GetHeapProfiler()); |
| 2056 int untracked_objects = heap_profiler->FindUntrackedObjects(); | 2059 int untracked_objects = |
| 2060 heap_profiler->heap_object_map()->FindUntrackedObjects(); |
| 2057 args.GetReturnValue().Set(untracked_objects); | 2061 args.GetReturnValue().Set(untracked_objects); |
| 2058 CHECK_EQ(0, untracked_objects); | 2062 CHECK_EQ(0, untracked_objects); |
| 2059 } | 2063 } |
| 2060 | 2064 |
| 2061 | 2065 |
| 2062 static HeapProfilerExtension kHeapProfilerExtension; | 2066 static HeapProfilerExtension kHeapProfilerExtension; |
| 2063 v8::DeclareExtension kHeapProfilerExtensionDeclaration( | 2067 v8::DeclareExtension kHeapProfilerExtensionDeclaration( |
| 2064 &kHeapProfilerExtension); | 2068 &kHeapProfilerExtension); |
| 2065 | 2069 |
| 2066 | 2070 |
| 2067 // This is an example of using checking of JS allocations tracking in a test. | |
| 2068 TEST(HeapObjectsTracker) { | |
| 2069 const char* extensions[] = { HeapProfilerExtension::kName }; | |
| 2070 v8::ExtensionConfiguration config(1, extensions); | |
| 2071 LocalContext env(&config); | |
| 2072 v8::HandleScope scope(env->GetIsolate()); | |
| 2073 HeapObjectsTracker tracker; | |
| 2074 CompileRun("var a = 1.2"); | |
| 2075 CompileRun("var a = 1.2; var b = 1.0; var c = 1.0;"); | |
| 2076 CompileRun( | |
| 2077 "var a = [];\n" | |
| 2078 "for (var i = 0; i < 5; ++i)\n" | |
| 2079 " a[i] = i;\n" | |
| 2080 "findUntrackedObjects();\n" | |
| 2081 "for (var i = 0; i < 3; ++i)\n" | |
| 2082 " a.shift();\n" | |
| 2083 "findUntrackedObjects();\n"); | |
| 2084 } | |
| 2085 | |
| 2086 | |
| 2087 static const v8::HeapGraphNode* GetNodeByPath(const v8::HeapSnapshot* snapshot, | 2071 static const v8::HeapGraphNode* GetNodeByPath(const v8::HeapSnapshot* snapshot, |
| 2088 const char* path[], | 2072 const char* path[], |
| 2089 int depth) { | 2073 int depth) { |
| 2090 const v8::HeapGraphNode* node = snapshot->GetRoot(); | 2074 const v8::HeapGraphNode* node = snapshot->GetRoot(); |
| 2091 for (int current_depth = 0; current_depth < depth; ++current_depth) { | 2075 for (int current_depth = 0; current_depth < depth; ++current_depth) { |
| 2092 int i, count = node->GetChildrenCount(); | 2076 int i, count = node->GetChildrenCount(); |
| 2093 for (i = 0; i < count; ++i) { | 2077 for (i = 0; i < count; ++i) { |
| 2094 const v8::HeapGraphEdge* edge = node->GetChild(i); | 2078 const v8::HeapGraphEdge* edge = node->GetChild(i); |
| 2095 const v8::HeapGraphNode* to_node = edge->GetToNode(); | 2079 const v8::HeapGraphNode* to_node = edge->GetToNode(); |
| 2096 v8::String::Utf8Value edge_name(edge->GetName()); | 2080 v8::String::Utf8Value edge_name(edge->GetName()); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2172 "var instances = [];\n" | 2156 "var instances = [];\n" |
| 2173 "function start() {\n" | 2157 "function start() {\n" |
| 2174 " for (var i = 0; i < width; i++) {\n" | 2158 " for (var i = 0; i < width; i++) {\n" |
| 2175 " instances.push(topFunctions[i](0));\n" | 2159 " instances.push(topFunctions[i](0));\n" |
| 2176 " }\n" | 2160 " }\n" |
| 2177 "}\n" | 2161 "}\n" |
| 2178 "\n" | 2162 "\n" |
| 2179 "for (var i = 0; i < 100; i++) start();\n"; | 2163 "for (var i = 0; i < 100; i++) start();\n"; |
| 2180 | 2164 |
| 2181 | 2165 |
| 2182 static i::HeapSnapshot* ToInternal(const v8::HeapSnapshot* snapshot) { | |
| 2183 return const_cast<i::HeapSnapshot*>( | |
| 2184 reinterpret_cast<const i::HeapSnapshot*>(snapshot)); | |
| 2185 } | |
| 2186 | |
| 2187 | |
| 2188 static AllocationTraceNode* FindNode( | 2166 static AllocationTraceNode* FindNode( |
| 2189 AllocationTracker* tracker, const Vector<const char*>& names) { | 2167 AllocationTracker* tracker, const Vector<const char*>& names) { |
| 2190 AllocationTraceNode* node = tracker->trace_tree()->root(); | 2168 AllocationTraceNode* node = tracker->trace_tree()->root(); |
| 2191 for (int i = 0; node != NULL && i < names.length(); i++) { | 2169 for (int i = 0; node != NULL && i < names.length(); i++) { |
| 2192 const char* name = names[i]; | 2170 const char* name = names[i]; |
| 2193 Vector<AllocationTraceNode*> children = node->children(); | 2171 Vector<AllocationTraceNode*> children = node->children(); |
| 2194 node = NULL; | 2172 node = NULL; |
| 2195 for (int j = 0; j < children.length(); j++) { | 2173 for (int j = 0; j < children.length(); j++) { |
| 2196 v8::SnapshotObjectId id = children[j]->function_id(); | 2174 v8::SnapshotObjectId id = children[j]->function_id(); |
| 2197 AllocationTracker::FunctionInfo* info = tracker->GetFunctionInfo(id); | 2175 AllocationTracker::FunctionInfo* info = tracker->GetFunctionInfo(id); |
| 2198 if (info && strcmp(info->name, name) == 0) { | 2176 if (info && strcmp(info->name, name) == 0) { |
| 2199 node = children[j]; | 2177 node = children[j]; |
| 2200 break; | 2178 break; |
| 2201 } | 2179 } |
| 2202 } | 2180 } |
| 2203 } | 2181 } |
| 2204 return node; | 2182 return node; |
| 2205 } | 2183 } |
| 2206 | 2184 |
| 2207 | 2185 |
| 2186 TEST(ArrayGrowLeftTrim) { |
| 2187 LocalContext env; |
| 2188 v8::HandleScope scope(env->GetIsolate()); |
| 2189 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
| 2190 heap_profiler->StartTrackingHeapObjects(true); |
| 2191 |
| 2192 CompileRun( |
| 2193 "var a = [];\n" |
| 2194 "for (var i = 0; i < 5; ++i)\n" |
| 2195 " a[i] = i;\n" |
| 2196 "for (var i = 0; i < 3; ++i)\n" |
| 2197 " a.shift();\n"); |
| 2198 |
| 2199 const char* names[] = { "(anonymous function)" }; |
| 2200 AllocationTracker* tracker = |
| 2201 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); |
| 2202 CHECK_NE(NULL, tracker); |
| 2203 // Resolve all function locations. |
| 2204 tracker->PrepareForSerialization(); |
| 2205 // Print for better diagnostics in case of failure. |
| 2206 tracker->trace_tree()->Print(tracker); |
| 2207 |
| 2208 AllocationTraceNode* node = |
| 2209 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names))); |
| 2210 CHECK_NE(NULL, node); |
| 2211 CHECK_GE(node->allocation_count(), 2); |
| 2212 CHECK_GE(node->allocation_size(), 4 * 5); |
| 2213 heap_profiler->StopTrackingHeapObjects(); |
| 2214 } |
| 2215 |
| 2216 |
| 2208 TEST(TrackHeapAllocations) { | 2217 TEST(TrackHeapAllocations) { |
| 2209 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 2218 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 2210 LocalContext env; | 2219 LocalContext env; |
| 2211 | 2220 |
| 2212 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); | 2221 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
| 2213 heap_profiler->StartRecordingHeapAllocations(); | 2222 heap_profiler->StartTrackingHeapObjects(true); |
| 2214 | 2223 |
| 2215 CompileRun(record_trace_tree_source); | 2224 CompileRun(record_trace_tree_source); |
| 2216 | 2225 |
| 2217 const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot( | 2226 AllocationTracker* tracker = |
| 2218 v8::String::NewFromUtf8(env->GetIsolate(), "Test")); | 2227 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); |
| 2219 i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection(); | |
| 2220 AllocationTracker* tracker = collection->allocation_tracker(); | |
| 2221 CHECK_NE(NULL, tracker); | 2228 CHECK_NE(NULL, tracker); |
| 2222 // Resolve all function locations. | 2229 // Resolve all function locations. |
| 2223 tracker->PrepareForSerialization(); | 2230 tracker->PrepareForSerialization(); |
| 2224 // Print for better diagnostics in case of failure. | 2231 // Print for better diagnostics in case of failure. |
| 2225 tracker->trace_tree()->Print(tracker); | 2232 tracker->trace_tree()->Print(tracker); |
| 2226 | 2233 |
| 2227 const char* names[] = | 2234 const char* names[] = |
| 2228 { "(anonymous function)", "start", "f_0_0", "f_0_1", "f_0_2" }; | 2235 { "(anonymous function)", "start", "f_0_0", "f_0_1", "f_0_2" }; |
| 2229 AllocationTraceNode* node = | 2236 AllocationTraceNode* node = |
| 2230 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names))); | 2237 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names))); |
| 2231 CHECK_NE(NULL, node); | 2238 CHECK_NE(NULL, node); |
| 2232 CHECK_GE(node->allocation_count(), 100); | 2239 CHECK_GE(node->allocation_count(), 100); |
| 2233 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); | 2240 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); |
| 2234 heap_profiler->StopRecordingHeapAllocations(); | 2241 heap_profiler->StopTrackingHeapObjects(); |
| 2235 } | 2242 } |
| 2236 | 2243 |
| 2237 | 2244 |
| 2238 static const char* inline_heap_allocation_source = | 2245 static const char* inline_heap_allocation_source = |
| 2239 "function f_0(x) {\n" | 2246 "function f_0(x) {\n" |
| 2240 " return f_1(x+1);\n" | 2247 " return f_1(x+1);\n" |
| 2241 "}\n" | 2248 "}\n" |
| 2242 "%NeverOptimizeFunction(f_0);\n" | 2249 "%NeverOptimizeFunction(f_0);\n" |
| 2243 "function f_1(x) {\n" | 2250 "function f_1(x) {\n" |
| 2244 " return new f_2(x+1);\n" | 2251 " return new f_2(x+1);\n" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2256 | 2263 |
| 2257 TEST(TrackBumpPointerAllocations) { | 2264 TEST(TrackBumpPointerAllocations) { |
| 2258 i::FLAG_allow_natives_syntax = true; | 2265 i::FLAG_allow_natives_syntax = true; |
| 2259 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 2266 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 2260 LocalContext env; | 2267 LocalContext env; |
| 2261 | 2268 |
| 2262 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); | 2269 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
| 2263 const char* names[] = { "(anonymous function)", "start", "f_0", "f_1" }; | 2270 const char* names[] = { "(anonymous function)", "start", "f_0", "f_1" }; |
| 2264 // First check that normally all allocations are recorded. | 2271 // First check that normally all allocations are recorded. |
| 2265 { | 2272 { |
| 2266 heap_profiler->StartRecordingHeapAllocations(); | 2273 heap_profiler->StartTrackingHeapObjects(true); |
| 2267 | 2274 |
| 2268 CompileRun(inline_heap_allocation_source); | 2275 CompileRun(inline_heap_allocation_source); |
| 2269 | 2276 |
| 2270 const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot( | 2277 AllocationTracker* tracker = |
| 2271 v8::String::NewFromUtf8(env->GetIsolate(), "Test2")); | 2278 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); |
| 2272 i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection(); | |
| 2273 AllocationTracker* tracker = collection->allocation_tracker(); | |
| 2274 CHECK_NE(NULL, tracker); | 2279 CHECK_NE(NULL, tracker); |
| 2275 // Resolve all function locations. | 2280 // Resolve all function locations. |
| 2276 tracker->PrepareForSerialization(); | 2281 tracker->PrepareForSerialization(); |
| 2277 // Print for better diagnostics in case of failure. | 2282 // Print for better diagnostics in case of failure. |
| 2278 tracker->trace_tree()->Print(tracker); | 2283 tracker->trace_tree()->Print(tracker); |
| 2279 | 2284 |
| 2280 AllocationTraceNode* node = | 2285 AllocationTraceNode* node = |
| 2281 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names))); | 2286 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names))); |
| 2282 CHECK_NE(NULL, node); | 2287 CHECK_NE(NULL, node); |
| 2283 CHECK_GE(node->allocation_count(), 100); | 2288 CHECK_GE(node->allocation_count(), 100); |
| 2284 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); | 2289 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); |
| 2285 heap_profiler->StopRecordingHeapAllocations(); | 2290 heap_profiler->StopTrackingHeapObjects(); |
| 2286 } | 2291 } |
| 2287 | 2292 |
| 2288 { | 2293 { |
| 2289 heap_profiler->StartRecordingHeapAllocations(); | 2294 heap_profiler->StartTrackingHeapObjects(true); |
| 2290 | 2295 |
| 2291 // Now check that not all allocations are tracked if we manually reenable | 2296 // Now check that not all allocations are tracked if we manually reenable |
| 2292 // inline allocations. | 2297 // inline allocations. |
| 2293 CHECK(CcTest::heap()->inline_allocation_disabled()); | 2298 CHECK(CcTest::heap()->inline_allocation_disabled()); |
| 2294 CcTest::heap()->EnableInlineAllocation(); | 2299 CcTest::heap()->EnableInlineAllocation(); |
| 2295 | 2300 |
| 2296 CompileRun(inline_heap_allocation_source); | 2301 CompileRun(inline_heap_allocation_source); |
| 2297 | 2302 |
| 2298 const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot( | 2303 AllocationTracker* tracker = |
| 2299 v8::String::NewFromUtf8(env->GetIsolate(), "Test1")); | 2304 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); |
| 2300 i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection(); | |
| 2301 AllocationTracker* tracker = collection->allocation_tracker(); | |
| 2302 CHECK_NE(NULL, tracker); | 2305 CHECK_NE(NULL, tracker); |
| 2303 // Resolve all function locations. | 2306 // Resolve all function locations. |
| 2304 tracker->PrepareForSerialization(); | 2307 tracker->PrepareForSerialization(); |
| 2305 // Print for better diagnostics in case of failure. | 2308 // Print for better diagnostics in case of failure. |
| 2306 tracker->trace_tree()->Print(tracker); | 2309 tracker->trace_tree()->Print(tracker); |
| 2307 | 2310 |
| 2308 AllocationTraceNode* node = | 2311 AllocationTraceNode* node = |
| 2309 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names))); | 2312 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names))); |
| 2310 CHECK_NE(NULL, node); | 2313 CHECK_NE(NULL, node); |
| 2311 CHECK_LT(node->allocation_count(), 100); | 2314 CHECK_LT(node->allocation_count(), 100); |
| 2312 | 2315 |
| 2313 CcTest::heap()->DisableInlineAllocation(); | 2316 CcTest::heap()->DisableInlineAllocation(); |
| 2314 heap_profiler->StopRecordingHeapAllocations(); | 2317 heap_profiler->StopTrackingHeapObjects(); |
| 2315 } | 2318 } |
| 2316 } | 2319 } |
| OLD | NEW |