From fac2b02c395f0842e8ffdd806f3b3fac1c10ac38 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 24 Apr 2014 15:10:44 -0400 Subject: [PATCH] Backed out changeset ace4dd426349 (bug 972045) for mochitest failures. --- js/public/MemoryMetrics.h | 3 +- js/src/builtin/TestingFunctions.cpp | 29 - .../saved-stacks/SavedFrame-constructor.js | 3 - js/src/jit-test/tests/saved-stacks/evals.js | 38 -- .../saved-stacks/function-display-name.js | 17 - .../tests/saved-stacks/gc-frame-cache.js | 76 --- .../jit-test/tests/saved-stacks/generators.js | 15 - js/src/jit-test/tests/saved-stacks/get-set.js | 25 - .../getters-on-invalid-objects.js | 21 - .../tests/saved-stacks/native-calls.js | 12 - .../tests/saved-stacks/principals-01.js | 70 --- .../tests/saved-stacks/principals-02.js | 56 -- .../tests/saved-stacks/proxy-handlers.js | 10 - .../jit-test/tests/saved-stacks/same-stack.js | 12 - .../tests/saved-stacks/self-hosted.js | 26 - .../saved-stacks/shared-parent-frames.js | 19 - .../stringify-with-self-hosted.js | 8 - js/src/jscompartment.cpp | 10 +- js/src/jscompartment.h | 8 +- js/src/moz.build | 1 - js/src/vm/MemoryMetrics.cpp | 3 +- js/src/vm/SavedStacks.cpp | 512 ------------------ js/src/vm/SavedStacks.h | 144 ----- js/src/vm/Stack.cpp | 2 +- 24 files changed, 5 insertions(+), 1115 deletions(-) delete mode 100644 js/src/jit-test/tests/saved-stacks/SavedFrame-constructor.js delete mode 100644 js/src/jit-test/tests/saved-stacks/evals.js delete mode 100644 js/src/jit-test/tests/saved-stacks/function-display-name.js delete mode 100644 js/src/jit-test/tests/saved-stacks/gc-frame-cache.js delete mode 100644 js/src/jit-test/tests/saved-stacks/generators.js delete mode 100644 js/src/jit-test/tests/saved-stacks/get-set.js delete mode 100644 js/src/jit-test/tests/saved-stacks/getters-on-invalid-objects.js delete mode 100644 js/src/jit-test/tests/saved-stacks/native-calls.js delete mode 100644 js/src/jit-test/tests/saved-stacks/principals-01.js delete mode 100644 js/src/jit-test/tests/saved-stacks/principals-02.js delete mode 100644 js/src/jit-test/tests/saved-stacks/proxy-handlers.js delete mode 100644 js/src/jit-test/tests/saved-stacks/same-stack.js delete mode 100644 js/src/jit-test/tests/saved-stacks/self-hosted.js delete mode 100644 js/src/jit-test/tests/saved-stacks/shared-parent-frames.js delete mode 100644 js/src/jit-test/tests/saved-stacks/stringify-with-self-hosted.js delete mode 100644 js/src/vm/SavedStacks.cpp delete mode 100644 js/src/vm/SavedStacks.h diff --git a/js/public/MemoryMetrics.h b/js/public/MemoryMetrics.h index 74f9cd194d0..fd2775e78ef 100644 --- a/js/public/MemoryMetrics.h +++ b/js/public/MemoryMetrics.h @@ -512,8 +512,7 @@ struct CompartmentStats macro(Other, NotLiveGCThing, compartmentObject) \ macro(Other, NotLiveGCThing, crossCompartmentWrappersTable) \ macro(Other, NotLiveGCThing, regexpCompartment) \ - macro(Other, NotLiveGCThing, debuggeesSet) \ - macro(Other, IsLiveGCThing, savedStacksSet) + macro(Other, NotLiveGCThing, debuggeesSet) CompartmentStats() : FOR_EACH_SIZE(ZERO_SIZE) diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index f86219e89d0..2c4ff311120 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -23,7 +23,6 @@ #include "vm/GlobalObject.h" #include "vm/Interpreter.h" #include "vm/ProxyObject.h" -#include "vm/SavedStacks.h" #include "vm/TraceLogging.h" #include "jscntxtinlines.h" @@ -851,25 +850,6 @@ CountHeap(JSContext *cx, unsigned argc, jsval *vp) return true; } -static bool -GetSavedFrameCount(JSContext *cx, unsigned argc, jsval *vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - args.rval().setNumber(cx->compartment()->savedStacks().count()); - return true; -} - -static bool -SaveStack(JSContext *cx, unsigned argc, jsval *vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - Rooted frame(cx); - if (!cx->compartment()->savedStacks().saveCurrentStack(cx, &frame)) - return false; - args.rval().setObject(*frame.get()); - return true; -} - #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) static bool OOMAfterAllocations(JSContext *cx, unsigned argc, jsval *vp) @@ -1570,15 +1550,6 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = { " then you can provide an extra argument with some specific traceable\n" " thing to count.\n"), - JS_FN_HELP("getSavedFrameCount", GetSavedFrameCount, 0, 0, -"getSavedFrameCount()", -" Return the number of SavedFrame instances stored in this compartment's\n" -" SavedStacks cache."), - - JS_FN_HELP("saveStack", SaveStack, 0, 0, -"saveStack()", -" Capture a stack.\n"), - #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) JS_FN_HELP("oomAfterAllocations", OOMAfterAllocations, 1, 0, "oomAfterAllocations(count)", diff --git a/js/src/jit-test/tests/saved-stacks/SavedFrame-constructor.js b/js/src/jit-test/tests/saved-stacks/SavedFrame-constructor.js deleted file mode 100644 index 4a3ed4d6a4c..00000000000 --- a/js/src/jit-test/tests/saved-stacks/SavedFrame-constructor.js +++ /dev/null @@ -1,3 +0,0 @@ -// The SavedFrame constructor shouldn't have been exposed to JS on the global. - -assertEq(typeof SavedFrame, "undefined"); diff --git a/js/src/jit-test/tests/saved-stacks/evals.js b/js/src/jit-test/tests/saved-stacks/evals.js deleted file mode 100644 index 93f6dca057b..00000000000 --- a/js/src/jit-test/tests/saved-stacks/evals.js +++ /dev/null @@ -1,38 +0,0 @@ -// Test that we can save stacks with direct and indirect eval calls. - -const directEval = (function iife() { - return eval("(" + function evalFrame() { - return saveStack(); - } + "())"); -}()); - -assertEq(directEval.source.contains("> eval"), true); -assertEq(directEval.functionDisplayName, "evalFrame"); - -assertEq(directEval.parent.source.contains("> eval"), true); - -assertEq(directEval.parent.parent.source.contains("> eval"), false); -assertEq(directEval.parent.parent.functionDisplayName, "iife"); - -assertEq(directEval.parent.parent.parent.source.contains("> eval"), false); - -assertEq(directEval.parent.parent.parent.parent, null); - -const lave = eval; -const indirectEval = (function iife() { - return lave("(" + function evalFrame() { - return saveStack(); - } + "())"); -}()); - -assertEq(indirectEval.source.contains("> eval"), true); -assertEq(indirectEval.functionDisplayName, "evalFrame"); - -assertEq(indirectEval.parent.source.contains("> eval"), true); - -assertEq(indirectEval.parent.parent.source.contains("> eval"), false); -assertEq(indirectEval.parent.parent.functionDisplayName, "iife"); - -assertEq(indirectEval.parent.parent.parent.source.contains("> eval"), false); - -assertEq(indirectEval.parent.parent.parent.parent, null); diff --git a/js/src/jit-test/tests/saved-stacks/function-display-name.js b/js/src/jit-test/tests/saved-stacks/function-display-name.js deleted file mode 100644 index cfe175758c8..00000000000 --- a/js/src/jit-test/tests/saved-stacks/function-display-name.js +++ /dev/null @@ -1,17 +0,0 @@ -// Test the functionDisplayName of SavedFrame instances. - -function uno() { return dos(); } -const dos = () => tres.quattro(); -const tres = { - quattro: () => saveStack() -}; - -const frame = uno(); - -assertEq(frame.functionDisplayName, "tres.quattro"); -assertEq(frame.parent.functionDisplayName, "dos"); -assertEq(frame.parent.parent.functionDisplayName, "uno"); -assertEq(frame.parent.parent.parent.functionDisplayName, null); - -assertEq(frame.parent.parent.parent.parent, null); - diff --git a/js/src/jit-test/tests/saved-stacks/gc-frame-cache.js b/js/src/jit-test/tests/saved-stacks/gc-frame-cache.js deleted file mode 100644 index 35f56fbcb08..00000000000 --- a/js/src/jit-test/tests/saved-stacks/gc-frame-cache.js +++ /dev/null @@ -1,76 +0,0 @@ -// Test that SavedFrame instances get removed from the SavedStacks frames cache -// after a GC. - -const FUZZ_FACTOR = 3; - -function assertAboutEq(actual, expected) { - if (Math.abs(actual - expected) > FUZZ_FACTOR) - throw new Error("Assertion failed: expected about " + expected + ", got " + actual + - ". FUZZ_FACTOR = " + FUZZ_FACTOR); -} - -const stacks = []; - -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); -stacks.push(saveStack()); - -assertAboutEq(getSavedFrameCount(), 50); - -while (stacks.length) { - stacks.pop(); -} -gc(); - -stacks = null; -gc(); - -assertAboutEq(getSavedFrameCount(), 0); diff --git a/js/src/jit-test/tests/saved-stacks/generators.js b/js/src/jit-test/tests/saved-stacks/generators.js deleted file mode 100644 index 69cd1e4adf3..00000000000 --- a/js/src/jit-test/tests/saved-stacks/generators.js +++ /dev/null @@ -1,15 +0,0 @@ -// Test that we can save stacks which have generator frames. - -const { value: frame } = (function iife1() { - return (function* generator() { - yield (function iife2() { - return saveStack(); - }()); - }()).next(); -}()); - -assertEq(frame.functionDisplayName, "iife2"); -assertEq(frame.parent.functionDisplayName, "generator"); -assertEq(frame.parent.parent.functionDisplayName, "iife1"); -assertEq(frame.parent.parent.parent.functionDisplayName, null); -assertEq(frame.parent.parent.parent.parent, null); diff --git a/js/src/jit-test/tests/saved-stacks/get-set.js b/js/src/jit-test/tests/saved-stacks/get-set.js deleted file mode 100644 index be2e2073993..00000000000 --- a/js/src/jit-test/tests/saved-stacks/get-set.js +++ /dev/null @@ -1,25 +0,0 @@ -// Test that we can save stacks with getter and setter function frames. - -function assertStackLengthEq(stack, expectedLength) { - let actual = 0; - while (stack) { - actual++; - stack = stack.parent; - } - assertEq(actual, expectedLength); -} - -const get = { get s() { return saveStack(); } }.s; -assertStackLengthEq(get, 2); - -let set; -try { - ({ - set s(v) { - throw saveStack(); - } - }).s = 1; -} catch (s) { - set = s; -} -assertStackLengthEq(set, 2); diff --git a/js/src/jit-test/tests/saved-stacks/getters-on-invalid-objects.js b/js/src/jit-test/tests/saved-stacks/getters-on-invalid-objects.js deleted file mode 100644 index ff009bc5b0d..00000000000 --- a/js/src/jit-test/tests/saved-stacks/getters-on-invalid-objects.js +++ /dev/null @@ -1,21 +0,0 @@ -// Test that you can't call the SavedFrame constructor and can only use -// SavedFrame's getters on SavedFrame instances. - -load(libdir + "asserts.js"); - -let proto = Object.getPrototypeOf(saveStack()); - -// Can't create new SavedFrame instances by hand. -assertThrowsInstanceOf(() => { - new proto.constructor(); -}, TypeError); - -for (let p of ["source", "line", "column", "functionDisplayName", "parent"]) { - // The getters shouldn't work on the prototype. - assertThrowsInstanceOf(() => proto[p], TypeError); - - // Nor should they work on random objects. - let o = {}; - Object.defineProperty(o, p, Object.getOwnPropertyDescriptor(proto, p)); - assertThrowsInstanceOf(() => o[p], TypeError); -} diff --git a/js/src/jit-test/tests/saved-stacks/native-calls.js b/js/src/jit-test/tests/saved-stacks/native-calls.js deleted file mode 100644 index 9c6a273253d..00000000000 --- a/js/src/jit-test/tests/saved-stacks/native-calls.js +++ /dev/null @@ -1,12 +0,0 @@ -// Test that we can save stacks with native code on the stack. - -// Unlike Array.prototype.map, Array.prototype.filter is not self-hosted. -const filter = (function iife() { - try { - [3].filter(n => { throw saveStack() }); - } catch (s) { - return s; - } -}()); - -assertEq(filter.parent.functionDisplayName, "iife"); diff --git a/js/src/jit-test/tests/saved-stacks/principals-01.js b/js/src/jit-test/tests/saved-stacks/principals-01.js deleted file mode 100644 index 1c67956b2df..00000000000 --- a/js/src/jit-test/tests/saved-stacks/principals-01.js +++ /dev/null @@ -1,70 +0,0 @@ -// Test that SavedFrame.prototype.parent gives the next older frame whose -// principals are subsumed by the caller's principals. - -// Given a string of letters |expected|, say "abc", assert that the stack -// contains calls to a series of functions named by the next letter from -// the string, say a, b, and then c. Younger frames appear earlier in -// |expected| than older frames. -function check(expected, stack) { - print("check(" + uneval(expected) + ") against:\n" + stack); - count++; - - while (stack.length && expected.length) { - assertEq(stack.shift(), expected[0]); - expected = expected.slice(1); - } - - if (expected.length > 0) { - throw new Error("Missing frames for: " + expected); - } - if (stack.length > 0 && !stack.every(s => s === null)) { - throw new Error("Unexpected extra frame(s):\n" + stack); - } -} - -// Go from a SavedFrame linked list to an array of function display names. -function extract(stack) { - const results = []; - while (stack) { - results.push(stack.functionDisplayName); - stack = stack.parent; - } - return results; -} - -const low = newGlobal({ principal: 0 }); -const mid = newGlobal({ principal: 0xffff }); -const high = newGlobal({ principal: 0xfffff }); - -var count = 0; - - eval('function a() { check("a", extract(saveStack())); b(); }'); -low .eval('function b() { check("b", extract(saveStack())); c(); }'); -mid .eval('function c() { check("cba", extract(saveStack())); d(); }'); -high.eval('function d() { check("dcba", extract(saveStack())); e(); }'); - eval('function e() { check("edcba", extract(saveStack())); f(); }'); // no principal, so checks skipped -low .eval('function f() { check("fb", extract(saveStack())); g(); }'); -mid .eval('function g() { check("gfecba", extract(saveStack())); h(); }'); -high.eval('function h() { check("hgfedcba", extract(saveStack())); }'); - -// Make everyone's functions visible to each other, as needed. - b = low .b; -low .c = mid .c; -mid .d = high.d; -high.e = e; - f = low .f; -low .g = mid .g; -mid .h = high.h; - -low.check = mid.check = high.check = check; - -// They each must have their own extract so that CCWs don't mess up the -// principals when we ask for the parent property. -low. eval("" + extract); -mid. eval("" + extract); -high.eval("" + extract); - -// Kick the whole process off. -a(); - -assertEq(count, 8); diff --git a/js/src/jit-test/tests/saved-stacks/principals-02.js b/js/src/jit-test/tests/saved-stacks/principals-02.js deleted file mode 100644 index 796c48b0694..00000000000 --- a/js/src/jit-test/tests/saved-stacks/principals-02.js +++ /dev/null @@ -1,56 +0,0 @@ -// Test that SavedFrame.prototype.toString only shows frames whose principal is -// subsumed by the caller's principal. - -var count = 0; - -// Given a string of letters |expected|, say "abc", assert that the stack -// contains calls to a series of functions named by the next letter from -// the string, say a, b, and then c. Younger frames appear earlier in -// |expected| than older frames. -function check(expected, stack) { - print("check(" + uneval(expected) + ") against:\n" + stack); - count++; - - // Extract only the function names from the stack trace. Omit the frames - // for the top-level evaluation, if it is present. - const frames = stack - .split("\n") - .filter(f => f.match(/^.@/)) - .map(f => f.replace(/@.*$/g, "")); - - // Check the function names against the expected sequence. - assertEq(frames.length, expected.length); - for (var i = 0; i < expected.length; i++) { - assertEq(frames[i], expected[i]); - } -} - -var low = newGlobal({ principal: 0 }); -var mid = newGlobal({ principal: 0xffff }); -var high = newGlobal({ principal: 0xfffff }); - - eval('function a() { check("a", saveStack().toString()); b(); }'); -low .eval('function b() { check("b", saveStack().toString()); c(); }'); -mid .eval('function c() { check("cba", saveStack().toString()); d(); }'); -high.eval('function d() { check("dcba", saveStack().toString()); e(); }'); - eval('function e() { check("edcba", saveStack().toString()); f(); }'); // no principal, so checks skipped -low .eval('function f() { check("fb", saveStack().toString()); g(); }'); -mid .eval('function g() { check("gfecba", saveStack().toString()); h(); }'); -high.eval('function h() { check("hgfedcba", saveStack().toString()); }'); - -// Make everyone's functions visible to each other, as needed. - b = low .b; -low .c = mid .c; -mid .d = high.d; -high.e = e; - f = low .f; -low .g = mid .g; -mid .h = high.h; - -low.check = mid.check = high.check = check; - -// Kick the whole process off. -a(); - -assertEq(count, 8); - diff --git a/js/src/jit-test/tests/saved-stacks/proxy-handlers.js b/js/src/jit-test/tests/saved-stacks/proxy-handlers.js deleted file mode 100644 index 7ad1f6dc682..00000000000 --- a/js/src/jit-test/tests/saved-stacks/proxy-handlers.js +++ /dev/null @@ -1,10 +0,0 @@ -// Test that we can save stacks with proxy handler frames. - -const stack = (function iife() { - return (new Proxy({}, { - get: function get(t, n, r) { return saveStack(); } - })).stack; -}()); - -assertEq(stack.functionDisplayName, "get"); -assertEq(stack.parent.functionDisplayName, "iife"); diff --git a/js/src/jit-test/tests/saved-stacks/same-stack.js b/js/src/jit-test/tests/saved-stacks/same-stack.js deleted file mode 100644 index b82ba1c04ab..00000000000 --- a/js/src/jit-test/tests/saved-stacks/same-stack.js +++ /dev/null @@ -1,12 +0,0 @@ -// Test that the same saved stack is only ever allocated once. - -const stacks = []; - -for (let i = 0; i < 10; i++) { - stacks.push(saveStack()); -} - -const s = stacks.pop(); -for (let stack of stacks) { - assertEq(s, stack); -} diff --git a/js/src/jit-test/tests/saved-stacks/self-hosted.js b/js/src/jit-test/tests/saved-stacks/self-hosted.js deleted file mode 100644 index 88f8ce20070..00000000000 --- a/js/src/jit-test/tests/saved-stacks/self-hosted.js +++ /dev/null @@ -1,26 +0,0 @@ -// Test that we can save stacks with self-hosted function frames in them. - -const map = (function () { - return [3].map(n => saveStack()).pop(); -}()); - -assertEq(map.parent.functionDisplayName, "map"); -assertEq(map.parent.source, "self-hosted"); - -const reduce = (function () { - return [3].reduce(() => saveStack(), 3); -}()); - -assertEq(reduce.parent.functionDisplayName, "reduce"); -assertEq(reduce.parent.source, "self-hosted"); - -const forEach = (function () { - try { - [3].forEach(n => { throw saveStack() }); - } catch (s) { - return s; - } -}()); - -assertEq(forEach.parent.functionDisplayName, "forEach"); -assertEq(forEach.parent.source, "self-hosted"); diff --git a/js/src/jit-test/tests/saved-stacks/shared-parent-frames.js b/js/src/jit-test/tests/saved-stacks/shared-parent-frames.js deleted file mode 100644 index c6b4332dd97..00000000000 --- a/js/src/jit-test/tests/saved-stacks/shared-parent-frames.js +++ /dev/null @@ -1,19 +0,0 @@ -// Test that parent frames are shared when the older portions of two stacks are -// the same. - -let f1, f2; - -function dos() { - f1 = saveStack(); - f2 = saveStack(); -} - -(function uno() { - dos(); -}()); - - -// Different youngest frames. -assertEq(f1 == f2, false); -// However the parents should be the same. -assertEq(f1.parent, f2.parent); diff --git a/js/src/jit-test/tests/saved-stacks/stringify-with-self-hosted.js b/js/src/jit-test/tests/saved-stacks/stringify-with-self-hosted.js deleted file mode 100644 index 7e55ca31b3d..00000000000 --- a/js/src/jit-test/tests/saved-stacks/stringify-with-self-hosted.js +++ /dev/null @@ -1,8 +0,0 @@ -// Test that stringify'ing a saved frame with self-hosted parent frames doesn't -// include the self-hosted parent frame in the output. - -const map = (function () { - return [3].map(n => saveStack()).pop(); -}()); - -assertEq(map.toString().contains("@self-hosted:"), false); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 4512ae1b523..714f28851e9 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -113,9 +113,6 @@ JSCompartment::init(JSContext *cx) if (!enumerators) return false; - if (!savedStacks_.init()) - return false; - return debuggees.init(0); } @@ -566,7 +563,6 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes) sweepNewTypeObjectTable(newTypeObjects); sweepNewTypeObjectTable(lazyTypeObjects); sweepCallsiteClones(); - savedStacks_.sweep(rt); if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet())) global_ = nullptr; @@ -669,8 +665,6 @@ JSCompartment::clearTables() newTypeObjects.clear(); if (lazyTypeObjects.initialized()) lazyTypeObjects.clear(); - if (savedStacks_.initialized()) - savedStacks_.clear(); } void @@ -921,8 +915,7 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *shapesCompartmentTables, size_t *crossCompartmentWrappersArg, size_t *regexpCompartment, - size_t *debuggeesSet, - size_t *savedStacksSet) + size_t *debuggeesSet) { *compartmentObject += mallocSizeOf(this); types.addSizeOfExcludingThis(mallocSizeOf, tiAllocationSiteTables, @@ -934,7 +927,6 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, *crossCompartmentWrappersArg += crossCompartmentWrappers.sizeOfExcludingThis(mallocSizeOf); *regexpCompartment += regExps.sizeOfExcludingThis(mallocSizeOf); *debuggeesSet += debuggees.sizeOfExcludingThis(mallocSizeOf); - *savedStacksSet += savedStacks_.sizeOfExcludingThis(mallocSizeOf); } void diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index f1d26d7b179..ed766e6b456 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -13,7 +13,6 @@ #include "gc/Zone.h" #include "vm/GlobalObject.h" #include "vm/PIC.h" -#include "vm/SavedStacks.h" namespace js { @@ -199,8 +198,6 @@ struct JSCompartment private: js::ObjectMetadataCallback objectMetadataCallback; - js::SavedStacks savedStacks_; - js::WrapperMap crossCompartmentWrappers; public: @@ -227,8 +224,7 @@ struct JSCompartment size_t *shapesCompartmentTables, size_t *crossCompartmentWrappers, size_t *regexpCompartment, - size_t *debuggeesSet, - size_t *savedStacksSet); + size_t *debuggeesSet); /* * Shared scope property tree, and arena-pool for allocating its nodes. @@ -346,8 +342,6 @@ struct JSCompartment return objectMetadataCallback(cx, obj); } - js::SavedStacks &savedStacks() { return savedStacks_; } - void findOutgoingEdges(js::gc::ComponentFinder &finder); js::DtoaCache dtoaCache; diff --git a/js/src/moz.build b/js/src/moz.build index 96aefd06661..f6b2eea022e 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -179,7 +179,6 @@ UNIFIED_SOURCES += [ 'vm/RegExpObject.cpp', 'vm/RegExpStatics.cpp', 'vm/Runtime.cpp', - 'vm/SavedStacks.cpp', 'vm/ScopeObject.cpp', 'vm/SelfHosting.cpp', 'vm/Shape.cpp', diff --git a/js/src/vm/MemoryMetrics.cpp b/js/src/vm/MemoryMetrics.cpp index 5862324c46c..197f43f5b04 100644 --- a/js/src/vm/MemoryMetrics.cpp +++ b/js/src/vm/MemoryMetrics.cpp @@ -259,8 +259,7 @@ StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment) &cStats.shapesMallocHeapCompartmentTables, &cStats.crossCompartmentWrappersTable, &cStats.regexpCompartment, - &cStats.debuggeesSet, - &cStats.savedStacksSet); + &cStats.debuggeesSet); } static void diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp deleted file mode 100644 index 7a07a9af7ec..00000000000 --- a/js/src/vm/SavedStacks.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -#include "vm/SavedStacks.h" - -#include "jscompartment.h" -#include "jsnum.h" - -#include "vm/GlobalObject.h" -#include "vm/StringBuffer.h" - -#include "jsobjinlines.h" - -using mozilla::AddToHash; -using mozilla::HashString; - -namespace js { - -/* static */ HashNumber -SavedFrame::HashPolicy::hash(const Lookup &lookup) -{ - return AddToHash(HashString(lookup.source->chars(), lookup.source->length()), - lookup.line, - lookup.column, - lookup.functionDisplayName, - SavedFramePtrHasher::hash(lookup.parent), - JSPrincipalsPtrHasher::hash(lookup.principals)); -} - -/* static */ bool -SavedFrame::HashPolicy::match(SavedFrame *existing, const Lookup &lookup) -{ - if (existing->getLine() != lookup.line) - return false; - - if (existing->getColumn() != lookup.column) - return false; - - if (existing->getParent() != lookup.parent) - return false; - - if (existing->getPrincipals() != lookup.principals) - return false; - - JSAtom *source = existing->getSource(); - if (source->length() != lookup.source->length()) - return false; - if (source != lookup.source) - return false; - - JSAtom *functionDisplayName = existing->getFunctionDisplayName(); - if (functionDisplayName) { - if (!lookup.functionDisplayName) - return false; - if (functionDisplayName->length() != lookup.functionDisplayName->length()) - return false; - if (0 != CompareAtoms(functionDisplayName, lookup.functionDisplayName)) - return false; - } else if (lookup.functionDisplayName) { - return false; - } - - return true; -} - -/* static */ void -SavedFrame::HashPolicy::rekey(Key &key, const Key &newKey) -{ - key = newKey; -} - -/* static */ const Class SavedFrame::class_ = { - "SavedFrame", - JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | - JSCLASS_HAS_RESERVED_SLOTS(SavedFrame::JSSLOT_COUNT), - - JS_PropertyStub, // addProperty - JS_DeletePropertyStub, // delProperty - JS_PropertyStub, // getProperty - JS_StrictPropertyStub, // setProperty - JS_EnumerateStub, // enumerate - JS_ResolveStub, // resolve - JS_ConvertStub, // convert - - SavedFrame::finalize // finalize -}; - -/* static */ void -SavedFrame::finalize(FreeOp *fop, JSObject *obj) -{ - JSPrincipals *p = obj->as().getPrincipals(); - if (p) { - JSRuntime *rt = obj->runtimeFromMainThread(); - JS_DropPrincipals(rt, p); - } -} - -JSAtom * -SavedFrame::getSource() -{ - const Value &v = getReservedSlot(JSSLOT_SOURCE); - JSString *s = v.toString(); - return &s->asAtom(); -} - -size_t -SavedFrame::getLine() -{ - const Value &v = getReservedSlot(JSSLOT_LINE); - return v.toInt32(); -} - -size_t -SavedFrame::getColumn() -{ - const Value &v = getReservedSlot(JSSLOT_COLUMN); - return v.toInt32(); -} - -JSAtom * -SavedFrame::getFunctionDisplayName() -{ - const Value &v = getReservedSlot(JSSLOT_FUNCTIONDISPLAYNAME); - if (v.isNull()) - return nullptr; - JSString *s = v.toString(); - return &s->asAtom(); -} - -SavedFrame * -SavedFrame::getParent() -{ - const Value &v = getReservedSlot(JSSLOT_PARENT); - return v.isObject() ? &v.toObject().as() : nullptr; -} - -JSPrincipals * -SavedFrame::getPrincipals() -{ - const Value &v = getReservedSlot(JSSLOT_PRINCIPALS); - if (v.isUndefined()) - return nullptr; - return static_cast(v.toPrivate()); -} - -void -SavedFrame::initFromLookup(Lookup &lookup) -{ - JS_ASSERT(lookup.source); - JS_ASSERT(getReservedSlot(JSSLOT_SOURCE).isUndefined()); - setReservedSlot(JSSLOT_SOURCE, StringValue(lookup.source)); - - setReservedSlot(JSSLOT_LINE, NumberValue(lookup.line)); - setReservedSlot(JSSLOT_COLUMN, NumberValue(lookup.column)); - setReservedSlot(JSSLOT_FUNCTIONDISPLAYNAME, - lookup.functionDisplayName - ? StringValue(lookup.functionDisplayName) - : NullValue()); - setReservedSlot(JSSLOT_PARENT, ObjectOrNullValue(lookup.parent)); - setReservedSlot(JSSLOT_PRIVATE_PARENT, PrivateValue(lookup.parent)); - - JS_ASSERT(getReservedSlot(JSSLOT_PRINCIPALS).isUndefined()); - if (lookup.principals) - JS_HoldPrincipals(lookup.principals); - setReservedSlot(JSSLOT_PRINCIPALS, PrivateValue(lookup.principals)); -} - -bool -SavedFrame::parentMoved() -{ - const Value &v = getReservedSlot(JSSLOT_PRIVATE_PARENT); - JSObject *p = static_cast(v.toPrivate()); - return p == getParent(); -} - -void -SavedFrame::updatePrivateParent() -{ - setReservedSlot(JSSLOT_PRIVATE_PARENT, PrivateValue(getParent())); -} - -bool -SavedFrame::isSelfHosted() -{ - JSAtom *source = getSource(); - return StringEqualsAscii(source, "self-hosted"); -} - -/* static */ bool -SavedFrame::construct(JSContext *cx, unsigned argc, Value *vp) -{ - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR, - "SavedFrame"); - return false; -} - -/* static */ SavedFrame * -SavedFrame::checkThis(JSContext *cx, CallArgs &args, const char *fnName) -{ - const Value &thisValue = args.thisv(); - - if (!thisValue.isObject()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT); - return nullptr; - } - - JSObject &thisObject = thisValue.toObject(); - if (!thisObject.is()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO, - SavedFrame::class_.name, fnName, thisObject.getClass()->name); - return nullptr; - } - - // Check for SavedFrame.prototype, which has the same class as SavedFrame - // instances, however doesn't actually represent a captured stack frame. It - // is the only object that is() but doesn't have a source. - if (thisObject.getReservedSlot(JSSLOT_SOURCE).isNull()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO, - SavedFrame::class_.name, fnName, "prototype object"); - return nullptr; - } - - return &thisObject.as(); -} - -// Get the SavedFrame * from the current this value and handle any errors that -// might occur therein. -// -// These parameters must already exist when calling this macro: -// - JSContext *cx -// - unsigned argc -// - Value *vp -// - const char *fnName -// These parameters will be defined after calling this macro: -// - CallArgs args -// - Rooted frame (will be non-null) -#define THIS_SAVEDFRAME(cx, argc, vp, fnName, args, frame) \ - CallArgs args = CallArgsFromVp(argc, vp); \ - Rooted frame(cx, checkThis(cx, args, fnName)); \ - if (!frame) \ - return false - -/* static */ bool -SavedFrame::sourceProperty(JSContext *cx, unsigned argc, Value *vp) -{ - THIS_SAVEDFRAME(cx, argc, vp, "(get source)", args, frame); - args.rval().setString(frame->getSource()); - return true; -} - -/* static */ bool -SavedFrame::lineProperty(JSContext *cx, unsigned argc, Value *vp) -{ - THIS_SAVEDFRAME(cx, argc, vp, "(get line)", args, frame); - uint32_t line = frame->getLine(); - args.rval().setNumber(line); - return true; -} - -/* static */ bool -SavedFrame::columnProperty(JSContext *cx, unsigned argc, Value *vp) -{ - THIS_SAVEDFRAME(cx, argc, vp, "(get column)", args, frame); - uint32_t column = frame->getColumn(); - args.rval().setNumber(column); - return true; -} - -/* static */ bool -SavedFrame::functionDisplayNameProperty(JSContext *cx, unsigned argc, Value *vp) -{ - THIS_SAVEDFRAME(cx, argc, vp, "(get functionDisplayName)", args, frame); - RootedAtom name(cx, frame->getFunctionDisplayName()); - if (name) - args.rval().setString(name); - else - args.rval().setNull(); - return true; -} - -/* static */ bool -SavedFrame::parentProperty(JSContext *cx, unsigned argc, Value *vp) -{ - THIS_SAVEDFRAME(cx, argc, vp, "(get parent)", args, frame); - JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes; - JSPrincipals *principals = cx->compartment()->principals; - - do - frame = frame->getParent(); - while (frame && principals && subsumes && - !subsumes(principals, frame->getPrincipals())); - - args.rval().setObjectOrNull(frame); - return true; -} - -/* static */ const JSPropertySpec SavedFrame::properties[] = { - JS_PSG("source", SavedFrame::sourceProperty, 0), - JS_PSG("line", SavedFrame::lineProperty, 0), - JS_PSG("column", SavedFrame::columnProperty, 0), - JS_PSG("functionDisplayName", SavedFrame::functionDisplayNameProperty, 0), - JS_PSG("parent", SavedFrame::parentProperty, 0), - JS_PS_END -}; - -/* static */ bool -SavedFrame::toStringMethod(JSContext *cx, unsigned argc, Value *vp) -{ - THIS_SAVEDFRAME(cx, argc, vp, "toString", args, frame); - StringBuffer sb(cx); - JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes; - JSPrincipals *principals = cx->compartment()->principals; - - do { - if (principals && subsumes && !subsumes(principals, frame->getPrincipals())) - continue; - if (frame->isSelfHosted()) - continue; - - RootedAtom name(cx, frame->getFunctionDisplayName()); - if ((name && !sb.append(name)) - || !sb.append('@') - || !sb.append(frame->getSource()) - || !sb.append(':') - || !NumberValueToStringBuffer(cx, NumberValue(frame->getLine()), sb) - || !sb.append(':') - || !NumberValueToStringBuffer(cx, NumberValue(frame->getColumn()), sb) - || !sb.append('\n')) { - return false; - } - } while ((frame = frame->getParent())); - - args.rval().setString(sb.finishString()); - return true; -} - -/* static */ const JSFunctionSpec SavedFrame::methods[] = { - JS_FN("toString", SavedFrame::toStringMethod, 0, 0), - JS_FS_END -}; - -bool -SavedStacks::init() -{ - return frames.init(); -} - -bool -SavedStacks::saveCurrentStack(JSContext *cx, MutableHandle frame) -{ - JS_ASSERT(initialized()); - JS_ASSERT(&cx->compartment()->savedStacks() == this); - - ScriptFrameIter iter(cx); - return insertFrames(cx, iter, frame); -} - -void -SavedStacks::sweep(JSRuntime *rt) -{ - if (frames.initialized()) { - for (SavedFrame::Set::Enum e(frames); !e.empty(); e.popFront()) { - JSObject *obj = static_cast(e.front()); - JSObject *temp = obj; - - if (IsObjectAboutToBeFinalized(&obj)) { - e.removeFront(); - } else { - SavedFrame *frame = &obj->as(); - bool parentMoved = frame->parentMoved(); - - if (parentMoved) { - frame->updatePrivateParent(); - } - - if (obj != temp || parentMoved) { - Rooted parent(rt, frame->getParent()); - e.rekeyFront(SavedFrame::Lookup(frame->getSource(), - frame->getLine(), - frame->getColumn(), - frame->getFunctionDisplayName(), - parent, - frame->getPrincipals()), - frame); - } - } - } - } - - if (savedFrameProto && IsObjectAboutToBeFinalized(&savedFrameProto)) { - savedFrameProto = nullptr; - } -} - -uint32_t -SavedStacks::count() -{ - JS_ASSERT(initialized()); - return frames.count(); -} - -void -SavedStacks::clear() -{ - frames.clear(); -} - -size_t -SavedStacks::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) -{ - return frames.sizeOfExcludingThis(mallocSizeOf); -} - -bool -SavedStacks::insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle frame) -{ - if (iter.done()) { - frame.set(nullptr); - return true; - } - - ScriptFrameIter thisFrame(iter); - Rooted parentFrame(cx); - if (!insertFrames(cx, ++iter, &parentFrame)) - return false; - - RootedScript script(cx, thisFrame.script()); - RootedFunction callee(cx, thisFrame.maybeCallee()); - const char *filename = script->filename(); - RootedAtom source(cx, Atomize(cx, filename, strlen(filename))); - if (!source) - return false; - uint32_t column; - uint32_t line = PCToLineNumber(script, thisFrame.pc(), &column); - - SavedFrame::Lookup lookup(source, - line, - column, - callee ? callee->displayAtom() : nullptr, - parentFrame, - thisFrame.compartment()->principals); - - frame.set(getOrCreateSavedFrame(cx, lookup)); - return frame.address() != nullptr; -} - -SavedFrame * -SavedStacks::getOrCreateSavedFrame(JSContext *cx, SavedFrame::Lookup &lookup) -{ - SavedFrame::Set::AddPtr p = frames.lookupForAdd(lookup); - if (p) - return *p; - - Rooted frame(cx, createFrameFromLookup(cx, lookup)); - if (!frame) - return nullptr; - - if (!frames.relookupOrAdd(p, lookup, frame)) - return nullptr; - - return frame; -} - -JSObject * -SavedStacks::getOrCreateSavedFramePrototype(JSContext *cx) -{ - if (savedFrameProto) - return savedFrameProto; - - Rooted global(cx, cx->compartment()->maybeGlobal()); - if (!global) - return nullptr; - - savedFrameProto = js_InitClass(cx, global, global->getOrCreateObjectPrototype(cx), - &SavedFrame::class_, SavedFrame::construct, 0, - SavedFrame::properties, SavedFrame::methods, nullptr, nullptr); - // The only object with the SavedFrame::class_ that doesn't have a source - // should be the prototype. - savedFrameProto->setReservedSlot(SavedFrame::JSSLOT_SOURCE, NullValue()); - return savedFrameProto; -} - -SavedFrame * -SavedStacks::createFrameFromLookup(JSContext *cx, SavedFrame::Lookup &lookup) -{ - RootedObject proto(cx, getOrCreateSavedFramePrototype(cx)); - if (!proto) - return nullptr; - - JS_ASSERT(proto->compartment() == cx->compartment()); - - RootedObject global(cx, cx->compartment()->maybeGlobal()); - if (!global) - return nullptr; - - JS_ASSERT(global->compartment() == cx->compartment()); - - RootedObject frameObj(cx, NewObjectWithGivenProto(cx, &SavedFrame::class_, proto, global)); - if (!frameObj) - return nullptr; - - SavedFrame &f = frameObj->as(); - f.initFromLookup(lookup); - - return &f; -} - -} /* namespace js */ diff --git a/js/src/vm/SavedStacks.h b/js/src/vm/SavedStacks.h deleted file mode 100644 index dc8b9c02e31..00000000000 --- a/js/src/vm/SavedStacks.h +++ /dev/null @@ -1,144 +0,0 @@ - -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef vm_SavedStacks_h -#define vm_SavedStacks_h - -#include "jscntxt.h" -#include "js/HashTable.h" -#include "vm/Stack.h" - -namespace js { - -class SavedFrame : public JSObject { - friend class SavedStacks; - - public: - static const Class class_; - static void finalize(FreeOp *fop, JSObject *obj); - - // Prototype methods and properties to be exposed to JS. - static const JSPropertySpec properties[]; - static const JSFunctionSpec methods[]; - static bool construct(JSContext *cx, unsigned argc, Value *vp); - static bool sourceProperty(JSContext *cx, unsigned argc, Value *vp); - static bool lineProperty(JSContext *cx, unsigned argc, Value *vp); - static bool columnProperty(JSContext *cx, unsigned argc, Value *vp); - static bool functionDisplayNameProperty(JSContext *cx, unsigned argc, Value *vp); - static bool parentProperty(JSContext *cx, unsigned argc, Value *vp); - static bool toStringMethod(JSContext *cx, unsigned argc, Value *vp); - - // Convenient getters for SavedFrame's reserved slots for use from C++. - JSAtom *getSource(); - size_t getLine(); - size_t getColumn(); - JSAtom *getFunctionDisplayName(); - SavedFrame *getParent(); - JSPrincipals *getPrincipals(); - - bool isSelfHosted(); - - struct Lookup; - struct HashPolicy; - - typedef HashSet Set; - - private: - void initFromLookup(Lookup &lookup); - - enum { - // The reserved slots in the SavedFrame class. - JSSLOT_SOURCE, - JSSLOT_LINE, - JSSLOT_COLUMN, - JSSLOT_FUNCTIONDISPLAYNAME, - JSSLOT_PARENT, - JSSLOT_PRINCIPALS, - JSSLOT_PRIVATE_PARENT, - - // The total number of reserved slots in the SavedFrame class. - JSSLOT_COUNT - }; - - // Because we hash the parent pointer, we need to rekey a saved frame - // whenever its parent was relocated by the GC. However, the GC doesn't - // notify us when this occurs. As a work around, we keep a duplicate copy of - // the parent pointer as a private value in a reserved slot. Whenever the - // private value parent pointer doesn't match the regular parent pointer, we - // know that GC moved the parent and we need to update our private value and - // rekey the saved frame in its hash set. These two methods are helpers for - // this process. - bool parentMoved(); - void updatePrivateParent(); - - static SavedFrame *checkThis(JSContext *cx, CallArgs &args, const char *fnName); -}; - -struct SavedFrame::Lookup { - Lookup(JSAtom *source, size_t line, size_t column, JSAtom *functionDisplayName, - Handle parent, JSPrincipals *principals) - : source(source), - line(line), - column(column), - functionDisplayName(functionDisplayName), - parent(parent), - principals(principals) - { - JS_ASSERT(source); - } - - JSAtom *source; - size_t line; - size_t column; - JSAtom *functionDisplayName; - Handle parent; - JSPrincipals *principals; -}; - -struct SavedFrame::HashPolicy -{ - typedef SavedFrame::Lookup Lookup; - typedef PointerHasher SavedFramePtrHasher; - typedef PointerHasher JSPrincipalsPtrHasher; - - static HashNumber hash(const Lookup &lookup); - static bool match(SavedFrame *existing, const Lookup &lookup); - - typedef SavedFrame* Key; - static void rekey(Key &key, const Key &newKey); -}; - -class SavedStacks { - public: - SavedStacks() : frames(), savedFrameProto(nullptr) { } - - bool init(); - bool initialized() const { return frames.initialized(); } - bool saveCurrentStack(JSContext *cx, MutableHandle frame); - void sweep(JSRuntime *rt); - uint32_t count(); - void clear(); - - size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); - - private: - SavedFrame::Set frames; - JSObject *savedFrameProto; - - bool insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle frame); - SavedFrame *getOrCreateSavedFrame(JSContext *cx, SavedFrame::Lookup &lookup); - // |SavedFrame.prototype| is created lazily and held weakly. It should only - // be accessed through this method. - JSObject *getOrCreateSavedFramePrototype(JSContext *cx); - SavedFrame *createFrameFromLookup(JSContext *cx, SavedFrame::Lookup &lookup); -}; - -} /* namespace js */ - -#endif /* vm_SavedStacks_h */ diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index a027502159e..6cc175a6782 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -677,7 +677,7 @@ FrameIter::FrameIter(const FrameIter &other) : data_(other.data_) #ifdef JS_ION , ionInlineFrames_(other.data_.cx_, - data_.jitFrames_.isIonJS() ? &other.ionInlineFrames_ : nullptr) + data_.jitFrames_.isScripted() ? &other.ionInlineFrames_ : nullptr) #endif { }