Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Side by Side Diff: test/cctest/test-heap-profiler.cc

Issue 110573004: Merge bleeding_edge 17696:18016. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 13 matching lines...) Expand all
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 // 27 //
28 // Tests for heap profiler 28 // Tests for heap profiler
29 29
30 #include <ctype.h> 30 #include <ctype.h>
31 31
32 #include "v8.h" 32 #include "v8.h"
33 33
34 #include "allocation-tracker.h"
34 #include "cctest.h" 35 #include "cctest.h"
35 #include "hashmap.h" 36 #include "hashmap.h"
36 #include "heap-profiler.h" 37 #include "heap-profiler.h"
37 #include "snapshot.h" 38 #include "snapshot.h"
38 #include "debug.h" 39 #include "debug.h"
39 #include "utils-inl.h" 40 #include "utils-inl.h"
40 #include "../include/v8-profiler.h" 41 #include "../include/v8-profiler.h"
41 42
43 using i::AllocationTraceNode;
44 using i::AllocationTraceTree;
45 using i::AllocationTracker;
46 using i::HashMap;
47 using i::Vector;
48
42 namespace { 49 namespace {
43 50
44 class NamedEntriesDetector { 51 class NamedEntriesDetector {
45 public: 52 public:
46 NamedEntriesDetector() 53 NamedEntriesDetector()
47 : has_A2(false), has_B2(false), has_C2(false) { 54 : has_A2(false), has_B2(false), has_C2(false) {
48 } 55 }
49 56
50 void CheckEntry(i::HeapEntry* entry) { 57 void CheckEntry(i::HeapEntry* entry) {
51 if (strcmp(entry->name(), "A2") == 0) has_A2 = true; 58 if (strcmp(entry->name(), "A2") == 0) has_A2 = true;
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 "function myFunction(a, b) { this.a = a; this.b = b; }\n" 248 "function myFunction(a, b) { this.a = a; this.b = b; }\n"
242 "function AAAAA() {}\n" 249 "function AAAAA() {}\n"
243 "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n"); 250 "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n");
244 const v8::HeapSnapshot* snapshot = 251 const v8::HeapSnapshot* snapshot =
245 heap_profiler->TakeHeapSnapshot(v8_str("sizes")); 252 heap_profiler->TakeHeapSnapshot(v8_str("sizes"));
246 CHECK(ValidateSnapshot(snapshot)); 253 CHECK(ValidateSnapshot(snapshot));
247 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 254 const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
248 const v8::HeapGraphNode* f = 255 const v8::HeapGraphNode* f =
249 GetProperty(global, v8::HeapGraphEdge::kProperty, "boundFunction"); 256 GetProperty(global, v8::HeapGraphEdge::kProperty, "boundFunction");
250 CHECK(f); 257 CHECK(f);
251 CHECK_EQ(v8::String::New("native_bind"), f->GetName()); 258 CHECK_EQ(v8::String::NewFromUtf8(env->GetIsolate(), "native_bind"),
259 f->GetName());
252 const v8::HeapGraphNode* bindings = 260 const v8::HeapGraphNode* bindings =
253 GetProperty(f, v8::HeapGraphEdge::kInternal, "bindings"); 261 GetProperty(f, v8::HeapGraphEdge::kInternal, "bindings");
254 CHECK_NE(NULL, bindings); 262 CHECK_NE(NULL, bindings);
255 CHECK_EQ(v8::HeapGraphNode::kArray, bindings->GetType()); 263 CHECK_EQ(v8::HeapGraphNode::kArray, bindings->GetType());
256 CHECK_EQ(4, bindings->GetChildrenCount()); 264 CHECK_EQ(4, bindings->GetChildrenCount());
257 265
258 const v8::HeapGraphNode* bound_this = GetProperty( 266 const v8::HeapGraphNode* bound_this = GetProperty(
259 f, v8::HeapGraphEdge::kShortcut, "bound_this"); 267 f, v8::HeapGraphEdge::kShortcut, "bound_this");
260 CHECK(bound_this); 268 CHECK(bound_this);
261 CHECK_EQ(v8::HeapGraphNode::kObject, bound_this->GetType()); 269 CHECK_EQ(v8::HeapGraphNode::kObject, bound_this->GetType());
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after
1069 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); 1077 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
1070 CompileRun("globalObject = {};\n"); 1078 CompileRun("globalObject = {};\n");
1071 const v8::HeapSnapshot* snapshot = 1079 const v8::HeapSnapshot* snapshot =
1072 heap_profiler->TakeHeapSnapshot(v8_str("get_snapshot_object_id")); 1080 heap_profiler->TakeHeapSnapshot(v8_str("get_snapshot_object_id"));
1073 CHECK(ValidateSnapshot(snapshot)); 1081 CHECK(ValidateSnapshot(snapshot));
1074 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 1082 const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1075 const v8::HeapGraphNode* global_object = 1083 const v8::HeapGraphNode* global_object =
1076 GetProperty(global, v8::HeapGraphEdge::kProperty, "globalObject"); 1084 GetProperty(global, v8::HeapGraphEdge::kProperty, "globalObject");
1077 CHECK(global_object); 1085 CHECK(global_object);
1078 1086
1079 v8::Local<v8::Value> globalObjectHandle = 1087 v8::Local<v8::Value> globalObjectHandle = env->Global()->Get(
1080 env->Global()->Get(v8::String::New("globalObject")); 1088 v8::String::NewFromUtf8(env->GetIsolate(), "globalObject"));
1081 CHECK(!globalObjectHandle.IsEmpty()); 1089 CHECK(!globalObjectHandle.IsEmpty());
1082 CHECK(globalObjectHandle->IsObject()); 1090 CHECK(globalObjectHandle->IsObject());
1083 1091
1084 v8::SnapshotObjectId id = heap_profiler->GetObjectId(globalObjectHandle); 1092 v8::SnapshotObjectId id = heap_profiler->GetObjectId(globalObjectHandle);
1085 CHECK_NE(static_cast<int>(v8::HeapProfiler::kUnknownObjectId), 1093 CHECK_NE(static_cast<int>(v8::HeapProfiler::kUnknownObjectId),
1086 id); 1094 id);
1087 CHECK_EQ(static_cast<int>(id), global_object->GetId()); 1095 CHECK_EQ(static_cast<int>(id), global_object->GetId());
1088 } 1096 }
1089 1097
1090 1098
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
1705 heap_profiler->TakeHeapSnapshot(v8_str("HiddenPropertiesFastCase1")); 1713 heap_profiler->TakeHeapSnapshot(v8_str("HiddenPropertiesFastCase1"));
1706 CHECK(ValidateSnapshot(snapshot)); 1714 CHECK(ValidateSnapshot(snapshot));
1707 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 1715 const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1708 const v8::HeapGraphNode* c = 1716 const v8::HeapGraphNode* c =
1709 GetProperty(global, v8::HeapGraphEdge::kProperty, "c"); 1717 GetProperty(global, v8::HeapGraphEdge::kProperty, "c");
1710 CHECK_NE(NULL, c); 1718 CHECK_NE(NULL, c);
1711 const v8::HeapGraphNode* hidden_props = 1719 const v8::HeapGraphNode* hidden_props =
1712 GetProperty(c, v8::HeapGraphEdge::kInternal, "hidden_properties"); 1720 GetProperty(c, v8::HeapGraphEdge::kInternal, "hidden_properties");
1713 CHECK_EQ(NULL, hidden_props); 1721 CHECK_EQ(NULL, hidden_props);
1714 1722
1715 v8::Handle<v8::Value> cHandle = env->Global()->Get(v8::String::New("c")); 1723 v8::Handle<v8::Value> cHandle =
1724 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c"));
1716 CHECK(!cHandle.IsEmpty() && cHandle->IsObject()); 1725 CHECK(!cHandle.IsEmpty() && cHandle->IsObject());
1717 cHandle->ToObject()->SetHiddenValue(v8_str("key"), v8_str("val")); 1726 cHandle->ToObject()->SetHiddenValue(v8_str("key"), v8_str("val"));
1718 1727
1719 snapshot = heap_profiler->TakeHeapSnapshot( 1728 snapshot = heap_profiler->TakeHeapSnapshot(
1720 v8_str("HiddenPropertiesFastCase2")); 1729 v8_str("HiddenPropertiesFastCase2"));
1721 CHECK(ValidateSnapshot(snapshot)); 1730 CHECK(ValidateSnapshot(snapshot));
1722 global = GetGlobalObject(snapshot); 1731 global = GetGlobalObject(snapshot);
1723 c = GetProperty(global, v8::HeapGraphEdge::kProperty, "c"); 1732 c = GetProperty(global, v8::HeapGraphEdge::kProperty, "c");
1724 CHECK_NE(NULL, c); 1733 CHECK_NE(NULL, c);
1725 hidden_props = GetProperty(c, v8::HeapGraphEdge::kInternal, 1734 hidden_props = GetProperty(c, v8::HeapGraphEdge::kInternal,
(...skipping 23 matching lines...) Expand all
1749 const v8::HeapGraphNode* global_handles = GetNode( 1758 const v8::HeapGraphNode* global_handles = GetNode(
1750 gc_roots, v8::HeapGraphNode::kSynthetic, "(Global handles)"); 1759 gc_roots, v8::HeapGraphNode::kSynthetic, "(Global handles)");
1751 CHECK_NE(NULL, global_handles); 1760 CHECK_NE(NULL, global_handles);
1752 return HasWeakEdge(global_handles); 1761 return HasWeakEdge(global_handles);
1753 } 1762 }
1754 1763
1755 1764
1756 static void PersistentHandleCallback(v8::Isolate* isolate, 1765 static void PersistentHandleCallback(v8::Isolate* isolate,
1757 v8::Persistent<v8::Value>* handle, 1766 v8::Persistent<v8::Value>* handle,
1758 void*) { 1767 void*) {
1759 handle->Dispose(); 1768 handle->Reset();
1760 } 1769 }
1761 1770
1762 1771
1763 TEST(WeakGlobalHandle) { 1772 TEST(WeakGlobalHandle) {
1764 LocalContext env; 1773 LocalContext env;
1765 v8::HandleScope scope(env->GetIsolate()); 1774 v8::HandleScope scope(env->GetIsolate());
1766 1775
1767 CHECK(!HasWeakGlobalHandle()); 1776 CHECK(!HasWeakGlobalHandle());
1768 1777
1769 v8::Persistent<v8::Object> handle(env->GetIsolate(), v8::Object::New()); 1778 v8::Persistent<v8::Object> handle(env->GetIsolate(), v8::Object::New());
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
2022 2031
2023 const char* HeapProfilerExtension::kName = "v8/heap-profiler"; 2032 const char* HeapProfilerExtension::kName = "v8/heap-profiler";
2024 2033
2025 2034
2026 const char* HeapProfilerExtension::kSource = 2035 const char* HeapProfilerExtension::kSource =
2027 "native function findUntrackedObjects();"; 2036 "native function findUntrackedObjects();";
2028 2037
2029 2038
2030 v8::Handle<v8::FunctionTemplate> HeapProfilerExtension::GetNativeFunction( 2039 v8::Handle<v8::FunctionTemplate> HeapProfilerExtension::GetNativeFunction(
2031 v8::Handle<v8::String> name) { 2040 v8::Handle<v8::String> name) {
2032 if (name->Equals(v8::String::New("findUntrackedObjects"))) { 2041 if (name->Equals(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(),
2042 "findUntrackedObjects"))) {
2033 return v8::FunctionTemplate::New( 2043 return v8::FunctionTemplate::New(
2034 HeapProfilerExtension::FindUntrackedObjects); 2044 HeapProfilerExtension::FindUntrackedObjects);
2035 } else { 2045 } else {
2036 CHECK(false); 2046 CHECK(false);
2037 return v8::Handle<v8::FunctionTemplate>(); 2047 return v8::Handle<v8::FunctionTemplate>();
2038 } 2048 }
2039 } 2049 }
2040 2050
2041 2051
2042 void HeapProfilerExtension::FindUntrackedObjects( 2052 void HeapProfilerExtension::FindUntrackedObjects(
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
2118 CHECK_NE(NULL, node); 2128 CHECK_NE(NULL, node);
2119 2129
2120 const char* builtin_path[] = { 2130 const char* builtin_path[] = {
2121 "::(GC roots)", 2131 "::(GC roots)",
2122 "::(Builtins)", 2132 "::(Builtins)",
2123 "::(KeyedLoadIC_Generic code)" 2133 "::(KeyedLoadIC_Generic code)"
2124 }; 2134 };
2125 node = GetNodeByPath(snapshot, builtin_path, ARRAY_SIZE(builtin_path)); 2135 node = GetNodeByPath(snapshot, builtin_path, ARRAY_SIZE(builtin_path));
2126 CHECK_NE(NULL, node); 2136 CHECK_NE(NULL, node);
2127 } 2137 }
2138
2139
2140 static const char* record_trace_tree_source =
2141 "var topFunctions = [];\n"
2142 "var global = this;\n"
2143 "function generateFunctions(width, depth) {\n"
2144 " var script = [];\n"
2145 " for (var i = 0; i < width; i++) {\n"
2146 " for (var j = 0; j < depth; j++) {\n"
2147 " script.push('function f_' + i + '_' + j + '(x) {\\n');\n"
2148 " script.push(' try {\\n');\n"
2149 " if (j < depth-2) {\n"
2150 " script.push(' return f_' + i + '_' + (j+1) + '(x+1);\\n');\n"
2151 " } else if (j == depth - 2) {\n"
2152 " script.push(' return new f_' + i + '_' + (depth - 1) + '();\\n');\n"
2153 " } else if (j == depth - 1) {\n"
2154 " script.push(' this.ts = Date.now();\\n');\n"
2155 " }\n"
2156 " script.push(' } catch (e) {}\\n');\n"
2157 " script.push('}\\n');\n"
2158 " \n"
2159 " }\n"
2160 " }\n"
2161 " var script = script.join('');\n"
2162 " // throw script;\n"
2163 " global.eval(script);\n"
2164 " for (var i = 0; i < width; i++) {\n"
2165 " topFunctions.push(this['f_' + i + '_0']);\n"
2166 " }\n"
2167 "}\n"
2168 "\n"
2169 "var width = 3;\n"
2170 "var depth = 3;\n"
2171 "generateFunctions(width, depth);\n"
2172 "var instances = [];\n"
2173 "function start() {\n"
2174 " for (var i = 0; i < width; i++) {\n"
2175 " instances.push(topFunctions[i](0));\n"
2176 " }\n"
2177 "}\n"
2178 "\n"
2179 "for (var i = 0; i < 100; i++) start();\n";
2180
2181
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(
2189 AllocationTracker* tracker, const Vector<const char*>& names) {
2190 AllocationTraceNode* node = tracker->trace_tree()->root();
2191 for (int i = 0; node != NULL && i < names.length(); i++) {
2192 const char* name = names[i];
2193 Vector<AllocationTraceNode*> children = node->children();
2194 node = NULL;
2195 for (int j = 0; j < children.length(); j++) {
2196 v8::SnapshotObjectId id = children[j]->function_id();
2197 AllocationTracker::FunctionInfo* info = tracker->GetFunctionInfo(id);
2198 if (info && strcmp(info->name, name) == 0) {
2199 node = children[j];
2200 break;
2201 }
2202 }
2203 }
2204 return node;
2205 }
2206
2207
2208 TEST(TrackHeapAllocations) {
2209 v8::HandleScope scope(v8::Isolate::GetCurrent());
2210 LocalContext env;
2211
2212 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
2213 heap_profiler->StartRecordingHeapAllocations();
2214
2215 CompileRun(record_trace_tree_source);
2216
2217 const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(
2218 v8::String::NewFromUtf8(env->GetIsolate(), "Test"));
2219 i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection();
2220 AllocationTracker* tracker = collection->allocation_tracker();
2221 CHECK_NE(NULL, tracker);
2222 // Resolve all function locations.
2223 tracker->PrepareForSerialization();
2224 // Print for better diagnostics in case of failure.
2225 tracker->trace_tree()->Print(tracker);
2226
2227 const char* names[] =
2228 { "(anonymous function)", "start", "f_0_0", "f_0_1", "f_0_2" };
2229 AllocationTraceNode* node =
2230 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names)));
2231 CHECK_NE(NULL, node);
2232 CHECK_GE(node->allocation_count(), 100);
2233 CHECK_GE(node->allocation_size(), 4 * node->allocation_count());
2234 heap_profiler->StopRecordingHeapAllocations();
2235 }
2236
2237
2238 static const char* inline_heap_allocation_source =
2239 "function f_0(x) {\n"
2240 " return f_1(x+1);\n"
2241 "}\n"
2242 "%NeverOptimizeFunction(f_0);\n"
2243 "function f_1(x) {\n"
2244 " return new f_2(x+1);\n"
2245 "}\n"
2246 "function f_2(x) {\n"
2247 " this.foo = x;\n"
2248 "}\n"
2249 "var instances = [];\n"
2250 "function start() {\n"
2251 " instances.push(f_0(0));\n"
2252 "}\n"
2253 "\n"
2254 "for (var i = 0; i < 100; i++) start();\n";
2255
2256
2257 TEST(TrackBumpPointerAllocations) {
2258 i::FLAG_allow_natives_syntax = true;
2259 v8::HandleScope scope(v8::Isolate::GetCurrent());
2260 LocalContext env;
2261
2262 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
2263 const char* names[] = { "(anonymous function)", "start", "f_0", "f_1" };
2264 // First check that normally all allocations are recorded.
2265 {
2266 heap_profiler->StartRecordingHeapAllocations();
2267
2268 CompileRun(inline_heap_allocation_source);
2269
2270 const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(
2271 v8::String::NewFromUtf8(env->GetIsolate(), "Test2"));
2272 i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection();
2273 AllocationTracker* tracker = collection->allocation_tracker();
2274 CHECK_NE(NULL, tracker);
2275 // Resolve all function locations.
2276 tracker->PrepareForSerialization();
2277 // Print for better diagnostics in case of failure.
2278 tracker->trace_tree()->Print(tracker);
2279
2280 AllocationTraceNode* node =
2281 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names)));
2282 CHECK_NE(NULL, node);
2283 CHECK_GE(node->allocation_count(), 100);
2284 CHECK_GE(node->allocation_size(), 4 * node->allocation_count());
2285 heap_profiler->StopRecordingHeapAllocations();
2286 }
2287
2288 {
2289 heap_profiler->StartRecordingHeapAllocations();
2290
2291 // Now check that not all allocations are tracked if we manually reenable
2292 // inline allocations.
2293 CHECK(CcTest::heap()->inline_allocation_disabled());
2294 CcTest::heap()->EnableInlineAllocation();
2295
2296 CompileRun(inline_heap_allocation_source);
2297
2298 const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(
2299 v8::String::NewFromUtf8(env->GetIsolate(), "Test1"));
2300 i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection();
2301 AllocationTracker* tracker = collection->allocation_tracker();
2302 CHECK_NE(NULL, tracker);
2303 // Resolve all function locations.
2304 tracker->PrepareForSerialization();
2305 // Print for better diagnostics in case of failure.
2306 tracker->trace_tree()->Print(tracker);
2307
2308 AllocationTraceNode* node =
2309 FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names)));
2310 CHECK_NE(NULL, node);
2311 CHECK_LT(node->allocation_count(), 100);
2312
2313 CcTest::heap()->DisableInlineAllocation();
2314 heap_profiler->StopRecordingHeapAllocations();
2315 }
2316 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698