test_HeapSnapshot_deepStack_01.js (2777B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 "use strict"; 4 5 // Test that we can save a core dump with very deep allocation stacks and read 6 // it back into a HeapSnapshot. 7 8 function stackDepth(stack) { 9 return stack ? 1 + stackDepth(stack.parent) : 0; 10 } 11 12 function run_test() { 13 Services.prefs.setBoolPref( 14 "security.allow_parent_unrestricted_js_loads", 15 true 16 ); 17 Services.prefs.setBoolPref("security.allow_eval_with_system_principal", true); 18 Services.prefs.setBoolPref("security.allow_eval_in_parent_process", true); 19 registerCleanupFunction(() => { 20 Services.prefs.clearUserPref("security.allow_parent_unrestricted_js_loads"); 21 Services.prefs.clearUserPref("security.allow_eval_with_system_principal"); 22 Services.prefs.clearUserPref("security.allow_eval_in_parent_process"); 23 }); 24 25 // Create a Debugger observing a debuggee's allocations. 26 const debuggee = new Cu.Sandbox(null); 27 const dbg = new Debugger(debuggee); 28 dbg.memory.trackingAllocationSites = true; 29 30 // Allocate some objects in the debuggee that will have their allocation 31 // stacks recorded by the Debugger. 32 33 debuggee.eval("this.objects = []"); 34 debuggee.eval( 35 function recursiveAllocate(n) { 36 if (n <= 0) { 37 return; 38 } 39 40 // Make sure to recurse before pushing the object so that when TCO is 41 // implemented sometime in the future, it doesn't invalidate this test. 42 recursiveAllocate(n - 1); 43 this.objects.push({}); 44 }.toString() 45 ); 46 debuggee.eval("recursiveAllocate = recursiveAllocate.bind(this);"); 47 debuggee.eval("recursiveAllocate(200);"); 48 49 // Now save a snapshot that will include the allocation stacks and read it 50 // back again. 51 52 const filePath = ChromeUtils.saveHeapSnapshot({ runtime: true }); 53 ok(true, "Should be able to save a snapshot."); 54 55 const snapshot = ChromeUtils.readHeapSnapshot(filePath); 56 ok(snapshot, "Should be able to read a heap snapshot"); 57 ok(HeapSnapshot.isInstance(snapshot), "Should be an instanceof HeapSnapshot"); 58 59 const report = snapshot.takeCensus({ 60 breakdown: { 61 by: "allocationStack", 62 then: { by: "count", bytes: true, count: true }, 63 noStack: { by: "count", bytes: true, count: true }, 64 }, 65 }); 66 67 // Keep this synchronized with `HeapSnapshot::MAX_STACK_DEPTH`! 68 const MAX_STACK_DEPTH = 60; 69 70 let foundStacks = false; 71 report.forEach((v, k) => { 72 if (k === "noStack") { 73 return; 74 } 75 76 foundStacks = true; 77 const depth = stackDepth(k); 78 dumpn("Stack depth is " + depth); 79 Assert.lessOrEqual( 80 depth, 81 MAX_STACK_DEPTH, 82 "Every stack should have depth less than or equal to the maximum stack depth" 83 ); 84 }); 85 ok(foundStacks); 86 87 do_test_finished(); 88 }