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 26 matching lines...) Expand all Loading... |
37 #include "src/hashmap.h" | 37 #include "src/hashmap.h" |
38 #include "src/profiler/allocation-tracker.h" | 38 #include "src/profiler/allocation-tracker.h" |
39 #include "src/profiler/heap-profiler.h" | 39 #include "src/profiler/heap-profiler.h" |
40 #include "src/profiler/heap-snapshot-generator-inl.h" | 40 #include "src/profiler/heap-snapshot-generator-inl.h" |
41 #include "test/cctest/cctest.h" | 41 #include "test/cctest/cctest.h" |
42 | 42 |
43 using i::AllocationTraceNode; | 43 using i::AllocationTraceNode; |
44 using i::AllocationTraceTree; | 44 using i::AllocationTraceTree; |
45 using i::AllocationTracker; | 45 using i::AllocationTracker; |
46 using i::HashMap; | 46 using i::HashMap; |
| 47 using i::ArrayVector; |
47 using i::Vector; | 48 using i::Vector; |
48 | 49 |
49 namespace { | 50 namespace { |
50 | 51 |
51 class NamedEntriesDetector { | 52 class NamedEntriesDetector { |
52 public: | 53 public: |
53 NamedEntriesDetector() | 54 NamedEntriesDetector() |
54 : has_A2(false), has_B2(false), has_C2(false) { | 55 : has_A2(false), has_B2(false), has_C2(false) { |
55 } | 56 } |
56 | 57 |
(...skipping 2449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2506 | 2507 |
2507 const char* names[] = {""}; | 2508 const char* names[] = {""}; |
2508 AllocationTracker* tracker = | 2509 AllocationTracker* tracker = |
2509 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); | 2510 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); |
2510 CHECK(tracker); | 2511 CHECK(tracker); |
2511 // Resolve all function locations. | 2512 // Resolve all function locations. |
2512 tracker->PrepareForSerialization(); | 2513 tracker->PrepareForSerialization(); |
2513 // Print for better diagnostics in case of failure. | 2514 // Print for better diagnostics in case of failure. |
2514 tracker->trace_tree()->Print(tracker); | 2515 tracker->trace_tree()->Print(tracker); |
2515 | 2516 |
2516 AllocationTraceNode* node = | 2517 AllocationTraceNode* node = FindNode(tracker, ArrayVector(names)); |
2517 FindNode(tracker, Vector<const char*>(names, arraysize(names))); | |
2518 CHECK(node); | 2518 CHECK(node); |
2519 CHECK_GE(node->allocation_count(), 2u); | 2519 CHECK_GE(node->allocation_count(), 2u); |
2520 CHECK_GE(node->allocation_size(), 4u * 5u); | 2520 CHECK_GE(node->allocation_size(), 4u * 5u); |
2521 heap_profiler->StopTrackingHeapObjects(); | 2521 heap_profiler->StopTrackingHeapObjects(); |
2522 } | 2522 } |
2523 | 2523 |
2524 | 2524 |
2525 TEST(TrackHeapAllocations) { | 2525 TEST(TrackHeapAllocations) { |
2526 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 2526 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
2527 LocalContext env; | 2527 LocalContext env; |
2528 | 2528 |
2529 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); | 2529 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
2530 heap_profiler->StartTrackingHeapObjects(true); | 2530 heap_profiler->StartTrackingHeapObjects(true); |
2531 | 2531 |
2532 CompileRun(record_trace_tree_source); | 2532 CompileRun(record_trace_tree_source); |
2533 | 2533 |
2534 AllocationTracker* tracker = | 2534 AllocationTracker* tracker = |
2535 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); | 2535 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); |
2536 CHECK(tracker); | 2536 CHECK(tracker); |
2537 // Resolve all function locations. | 2537 // Resolve all function locations. |
2538 tracker->PrepareForSerialization(); | 2538 tracker->PrepareForSerialization(); |
2539 // Print for better diagnostics in case of failure. | 2539 // Print for better diagnostics in case of failure. |
2540 tracker->trace_tree()->Print(tracker); | 2540 tracker->trace_tree()->Print(tracker); |
2541 | 2541 |
2542 const char* names[] = {"", "start", "f_0_0", "f_0_1", "f_0_2"}; | 2542 const char* names[] = {"", "start", "f_0_0", "f_0_1", "f_0_2"}; |
2543 AllocationTraceNode* node = | 2543 AllocationTraceNode* node = FindNode(tracker, ArrayVector(names)); |
2544 FindNode(tracker, Vector<const char*>(names, arraysize(names))); | |
2545 CHECK(node); | 2544 CHECK(node); |
2546 CHECK_GE(node->allocation_count(), 100u); | 2545 CHECK_GE(node->allocation_count(), 100u); |
2547 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); | 2546 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); |
2548 heap_profiler->StopTrackingHeapObjects(); | 2547 heap_profiler->StopTrackingHeapObjects(); |
2549 } | 2548 } |
2550 | 2549 |
2551 | 2550 |
2552 static const char* inline_heap_allocation_source = | 2551 static const char* inline_heap_allocation_source = |
2553 "function f_0(x) {\n" | 2552 "function f_0(x) {\n" |
2554 " return f_1(x+1);\n" | 2553 " return f_1(x+1);\n" |
(...skipping 28 matching lines...) Expand all Loading... |
2583 CompileRun(inline_heap_allocation_source); | 2582 CompileRun(inline_heap_allocation_source); |
2584 | 2583 |
2585 AllocationTracker* tracker = | 2584 AllocationTracker* tracker = |
2586 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); | 2585 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); |
2587 CHECK(tracker); | 2586 CHECK(tracker); |
2588 // Resolve all function locations. | 2587 // Resolve all function locations. |
2589 tracker->PrepareForSerialization(); | 2588 tracker->PrepareForSerialization(); |
2590 // Print for better diagnostics in case of failure. | 2589 // Print for better diagnostics in case of failure. |
2591 tracker->trace_tree()->Print(tracker); | 2590 tracker->trace_tree()->Print(tracker); |
2592 | 2591 |
2593 AllocationTraceNode* node = | 2592 AllocationTraceNode* node = FindNode(tracker, ArrayVector(names)); |
2594 FindNode(tracker, Vector<const char*>(names, arraysize(names))); | |
2595 CHECK(node); | 2593 CHECK(node); |
2596 CHECK_GE(node->allocation_count(), 100u); | 2594 CHECK_GE(node->allocation_count(), 100u); |
2597 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); | 2595 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); |
2598 heap_profiler->StopTrackingHeapObjects(); | 2596 heap_profiler->StopTrackingHeapObjects(); |
2599 } | 2597 } |
2600 | 2598 |
2601 { | 2599 { |
2602 heap_profiler->StartTrackingHeapObjects(true); | 2600 heap_profiler->StartTrackingHeapObjects(true); |
2603 | 2601 |
2604 // Now check that not all allocations are tracked if we manually reenable | 2602 // Now check that not all allocations are tracked if we manually reenable |
2605 // inline allocations. | 2603 // inline allocations. |
2606 CHECK(CcTest::heap()->inline_allocation_disabled()); | 2604 CHECK(CcTest::heap()->inline_allocation_disabled()); |
2607 CcTest::heap()->EnableInlineAllocation(); | 2605 CcTest::heap()->EnableInlineAllocation(); |
2608 | 2606 |
2609 CompileRun(inline_heap_allocation_source); | 2607 CompileRun(inline_heap_allocation_source); |
2610 | 2608 |
2611 AllocationTracker* tracker = | 2609 AllocationTracker* tracker = |
2612 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); | 2610 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); |
2613 CHECK(tracker); | 2611 CHECK(tracker); |
2614 // Resolve all function locations. | 2612 // Resolve all function locations. |
2615 tracker->PrepareForSerialization(); | 2613 tracker->PrepareForSerialization(); |
2616 // Print for better diagnostics in case of failure. | 2614 // Print for better diagnostics in case of failure. |
2617 tracker->trace_tree()->Print(tracker); | 2615 tracker->trace_tree()->Print(tracker); |
2618 | 2616 |
2619 AllocationTraceNode* node = | 2617 AllocationTraceNode* node = FindNode(tracker, ArrayVector(names)); |
2620 FindNode(tracker, Vector<const char*>(names, arraysize(names))); | |
2621 CHECK(node); | 2618 CHECK(node); |
2622 CHECK_LT(node->allocation_count(), 100u); | 2619 CHECK_LT(node->allocation_count(), 100u); |
2623 | 2620 |
2624 CcTest::heap()->DisableInlineAllocation(); | 2621 CcTest::heap()->DisableInlineAllocation(); |
2625 heap_profiler->StopTrackingHeapObjects(); | 2622 heap_profiler->StopTrackingHeapObjects(); |
2626 } | 2623 } |
2627 } | 2624 } |
2628 | 2625 |
2629 | 2626 |
2630 TEST(TrackV8ApiAllocation) { | 2627 TEST(TrackV8ApiAllocation) { |
2631 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 2628 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
2632 LocalContext env; | 2629 LocalContext env; |
2633 | 2630 |
2634 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); | 2631 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
2635 const char* names[] = { "(V8 API)" }; | 2632 const char* names[] = { "(V8 API)" }; |
2636 heap_profiler->StartTrackingHeapObjects(true); | 2633 heap_profiler->StartTrackingHeapObjects(true); |
2637 | 2634 |
2638 v8::Local<v8::Object> o1 = v8::Object::New(env->GetIsolate()); | 2635 v8::Local<v8::Object> o1 = v8::Object::New(env->GetIsolate()); |
2639 o1->Clone(); | 2636 o1->Clone(); |
2640 | 2637 |
2641 AllocationTracker* tracker = | 2638 AllocationTracker* tracker = |
2642 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); | 2639 reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker(); |
2643 CHECK(tracker); | 2640 CHECK(tracker); |
2644 // Resolve all function locations. | 2641 // Resolve all function locations. |
2645 tracker->PrepareForSerialization(); | 2642 tracker->PrepareForSerialization(); |
2646 // Print for better diagnostics in case of failure. | 2643 // Print for better diagnostics in case of failure. |
2647 tracker->trace_tree()->Print(tracker); | 2644 tracker->trace_tree()->Print(tracker); |
2648 | 2645 |
2649 AllocationTraceNode* node = | 2646 AllocationTraceNode* node = FindNode(tracker, ArrayVector(names)); |
2650 FindNode(tracker, Vector<const char*>(names, arraysize(names))); | |
2651 CHECK(node); | 2647 CHECK(node); |
2652 CHECK_GE(node->allocation_count(), 2u); | 2648 CHECK_GE(node->allocation_count(), 2u); |
2653 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); | 2649 CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); |
2654 heap_profiler->StopTrackingHeapObjects(); | 2650 heap_profiler->StopTrackingHeapObjects(); |
2655 } | 2651 } |
2656 | 2652 |
2657 | 2653 |
2658 TEST(ArrayBufferAndArrayBufferView) { | 2654 TEST(ArrayBufferAndArrayBufferView) { |
2659 LocalContext env; | 2655 LocalContext env; |
2660 v8::HandleScope scope(env->GetIsolate()); | 2656 v8::HandleScope scope(env->GetIsolate()); |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2915 int count_1024 = 0; | 2911 int count_1024 = 0; |
2916 { | 2912 { |
2917 heap_profiler->StartSamplingHeapProfiler(1024); | 2913 heap_profiler->StartSamplingHeapProfiler(1024); |
2918 CompileRun(script_source); | 2914 CompileRun(script_source); |
2919 | 2915 |
2920 v8::base::SmartPointer<v8::AllocationProfile> profile( | 2916 v8::base::SmartPointer<v8::AllocationProfile> profile( |
2921 heap_profiler->GetAllocationProfile()); | 2917 heap_profiler->GetAllocationProfile()); |
2922 CHECK(!profile.is_empty()); | 2918 CHECK(!profile.is_empty()); |
2923 | 2919 |
2924 const char* names[] = {"", "foo", "bar"}; | 2920 const char* names[] = {"", "foo", "bar"}; |
2925 auto node_bar = FindAllocationProfileNode( | 2921 auto node_bar = FindAllocationProfileNode(*profile, ArrayVector(names)); |
2926 *profile, Vector<const char*>(names, arraysize(names))); | |
2927 CHECK(node_bar); | 2922 CHECK(node_bar); |
2928 | 2923 |
2929 // Count the number of allocations we sampled from bar. | 2924 // Count the number of allocations we sampled from bar. |
2930 for (auto allocation : node_bar->allocations) { | 2925 for (auto allocation : node_bar->allocations) { |
2931 count_1024 += allocation.count; | 2926 count_1024 += allocation.count; |
2932 } | 2927 } |
2933 | 2928 |
2934 heap_profiler->StopSamplingHeapProfiler(); | 2929 heap_profiler->StopSamplingHeapProfiler(); |
2935 } | 2930 } |
2936 | 2931 |
2937 // Samples should get cleared once sampling is stopped. | 2932 // Samples should get cleared once sampling is stopped. |
2938 { | 2933 { |
2939 v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile(); | 2934 v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile(); |
2940 CHECK(profile == nullptr); | 2935 CHECK(profile == nullptr); |
2941 } | 2936 } |
2942 | 2937 |
2943 // Sampling at a higher rate should give us similar numbers of objects. | 2938 // Sampling at a higher rate should give us similar numbers of objects. |
2944 { | 2939 { |
2945 heap_profiler->StartSamplingHeapProfiler(128); | 2940 heap_profiler->StartSamplingHeapProfiler(128); |
2946 CompileRun(script_source); | 2941 CompileRun(script_source); |
2947 | 2942 |
2948 v8::base::SmartPointer<v8::AllocationProfile> profile( | 2943 v8::base::SmartPointer<v8::AllocationProfile> profile( |
2949 heap_profiler->GetAllocationProfile()); | 2944 heap_profiler->GetAllocationProfile()); |
2950 CHECK(!profile.is_empty()); | 2945 CHECK(!profile.is_empty()); |
2951 | 2946 |
2952 const char* names[] = {"", "foo", "bar"}; | 2947 const char* names[] = {"", "foo", "bar"}; |
2953 auto node_bar = FindAllocationProfileNode( | 2948 auto node_bar = FindAllocationProfileNode(*profile, ArrayVector(names)); |
2954 *profile, Vector<const char*>(names, arraysize(names))); | |
2955 CHECK(node_bar); | 2949 CHECK(node_bar); |
2956 | 2950 |
2957 // Count the number of allocations we sampled from bar. | 2951 // Count the number of allocations we sampled from bar. |
2958 int count_128 = 0; | 2952 int count_128 = 0; |
2959 for (auto allocation : node_bar->allocations) { | 2953 for (auto allocation : node_bar->allocations) { |
2960 count_128 += allocation.count; | 2954 count_128 += allocation.count; |
2961 } | 2955 } |
2962 | 2956 |
2963 // We should have similar unsampled counts of allocations. Though | 2957 // We should have similar unsampled counts of allocations. Though |
2964 // we will sample different numbers of objects at different rates, | 2958 // we will sample different numbers of objects at different rates, |
(...skipping 13 matching lines...) Expand all Loading... |
2978 // generated function names. | 2972 // generated function names. |
2979 { | 2973 { |
2980 heap_profiler->StartSamplingHeapProfiler(64); | 2974 heap_profiler->StartSamplingHeapProfiler(64); |
2981 CompileRun(record_trace_tree_source); | 2975 CompileRun(record_trace_tree_source); |
2982 | 2976 |
2983 v8::base::SmartPointer<v8::AllocationProfile> profile( | 2977 v8::base::SmartPointer<v8::AllocationProfile> profile( |
2984 heap_profiler->GetAllocationProfile()); | 2978 heap_profiler->GetAllocationProfile()); |
2985 CHECK(!profile.is_empty()); | 2979 CHECK(!profile.is_empty()); |
2986 | 2980 |
2987 const char* names1[] = {"", "start", "f_0_0", "f_0_1", "f_0_2"}; | 2981 const char* names1[] = {"", "start", "f_0_0", "f_0_1", "f_0_2"}; |
2988 auto node1 = FindAllocationProfileNode( | 2982 auto node1 = FindAllocationProfileNode(*profile, ArrayVector(names1)); |
2989 *profile, Vector<const char*>(names1, arraysize(names1))); | |
2990 CHECK(node1); | 2983 CHECK(node1); |
2991 | 2984 |
2992 const char* names2[] = {"", "generateFunctions"}; | 2985 const char* names2[] = {"", "generateFunctions"}; |
2993 auto node2 = FindAllocationProfileNode( | 2986 auto node2 = FindAllocationProfileNode(*profile, ArrayVector(names2)); |
2994 *profile, Vector<const char*>(names2, arraysize(names2))); | |
2995 CHECK(node2); | 2987 CHECK(node2); |
2996 | 2988 |
2997 heap_profiler->StopSamplingHeapProfiler(); | 2989 heap_profiler->StopSamplingHeapProfiler(); |
2998 } | 2990 } |
2999 | 2991 |
3000 // A test case with scripts unloaded before profile gathered | 2992 // A test case with scripts unloaded before profile gathered |
3001 { | 2993 { |
3002 heap_profiler->StartSamplingHeapProfiler(64); | 2994 heap_profiler->StartSamplingHeapProfiler(64); |
3003 CompileRun( | 2995 CompileRun( |
3004 "for (var i = 0; i < 1024; i++) {\n" | 2996 "for (var i = 0; i < 1024; i++) {\n" |
(...skipping 22 matching lines...) Expand all Loading... |
3027 v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true; | 3019 v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true; |
3028 | 3020 |
3029 heap_profiler->StartSamplingHeapProfiler(256); | 3021 heap_profiler->StartSamplingHeapProfiler(256); |
3030 | 3022 |
3031 for (int i = 0; i < 8 * 1024; ++i) v8::Object::New(env->GetIsolate()); | 3023 for (int i = 0; i < 8 * 1024; ++i) v8::Object::New(env->GetIsolate()); |
3032 | 3024 |
3033 v8::base::SmartPointer<v8::AllocationProfile> profile( | 3025 v8::base::SmartPointer<v8::AllocationProfile> profile( |
3034 heap_profiler->GetAllocationProfile()); | 3026 heap_profiler->GetAllocationProfile()); |
3035 CHECK(!profile.is_empty()); | 3027 CHECK(!profile.is_empty()); |
3036 const char* names[] = {"(V8 API)"}; | 3028 const char* names[] = {"(V8 API)"}; |
3037 auto node = FindAllocationProfileNode( | 3029 auto node = FindAllocationProfileNode(*profile, ArrayVector(names)); |
3038 *profile, Vector<const char*>(names, arraysize(names))); | |
3039 CHECK(node); | 3030 CHECK(node); |
3040 | 3031 |
3041 heap_profiler->StopSamplingHeapProfiler(); | 3032 heap_profiler->StopSamplingHeapProfiler(); |
3042 } | 3033 } |
3043 | 3034 |
3044 TEST(SamplingHeapProfilerLeftTrimming) { | 3035 TEST(SamplingHeapProfilerLeftTrimming) { |
3045 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 3036 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
3046 LocalContext env; | 3037 LocalContext env; |
3047 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); | 3038 v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
3048 | 3039 |
3049 // Suppress randomness to avoid flakiness in tests. | 3040 // Suppress randomness to avoid flakiness in tests. |
3050 v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true; | 3041 v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true; |
3051 | 3042 |
3052 heap_profiler->StartSamplingHeapProfiler(64); | 3043 heap_profiler->StartSamplingHeapProfiler(64); |
3053 | 3044 |
3054 CompileRun( | 3045 CompileRun( |
3055 "for (var j = 0; j < 500; ++j) {\n" | 3046 "for (var j = 0; j < 500; ++j) {\n" |
3056 " var a = [];\n" | 3047 " var a = [];\n" |
3057 " for (var i = 0; i < 5; ++i)\n" | 3048 " for (var i = 0; i < 5; ++i)\n" |
3058 " a[i] = i;\n" | 3049 " a[i] = i;\n" |
3059 " for (var i = 0; i < 3; ++i)\n" | 3050 " for (var i = 0; i < 3; ++i)\n" |
3060 " a.shift();\n" | 3051 " a.shift();\n" |
3061 "}\n"); | 3052 "}\n"); |
3062 | 3053 |
3063 CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE); | 3054 CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE); |
3064 // Should not crash. | 3055 // Should not crash. |
3065 | 3056 |
3066 heap_profiler->StopSamplingHeapProfiler(); | 3057 heap_profiler->StopSamplingHeapProfiler(); |
3067 } | 3058 } |
OLD | NEW |