Backed out changeset ace4dd426349 (bug 972045) for mochitest failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 24 Apr 2014 15:10:44 -0400
changeset 198565 9688e85bd87c14f571c15a15b074ae6b1ebfb2df
parent 198564 5e6769176ce1af8da2951b36dba0b86590720c1c
child 198566 a38d0ab6d6b844c65448f601bd7b668f5f2d7cd5
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs972045
milestone31.0a1
backs outace4dd4263499c5cc8592af910ae464ee212f87c
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset ace4dd426349 (bug 972045) for mochitest failures.
js/public/MemoryMetrics.h
js/src/builtin/TestingFunctions.cpp
js/src/jit-test/tests/saved-stacks/SavedFrame-constructor.js
js/src/jit-test/tests/saved-stacks/evals.js
js/src/jit-test/tests/saved-stacks/function-display-name.js
js/src/jit-test/tests/saved-stacks/gc-frame-cache.js
js/src/jit-test/tests/saved-stacks/generators.js
js/src/jit-test/tests/saved-stacks/get-set.js
js/src/jit-test/tests/saved-stacks/getters-on-invalid-objects.js
js/src/jit-test/tests/saved-stacks/native-calls.js
js/src/jit-test/tests/saved-stacks/principals-01.js
js/src/jit-test/tests/saved-stacks/principals-02.js
js/src/jit-test/tests/saved-stacks/proxy-handlers.js
js/src/jit-test/tests/saved-stacks/same-stack.js
js/src/jit-test/tests/saved-stacks/self-hosted.js
js/src/jit-test/tests/saved-stacks/shared-parent-frames.js
js/src/jit-test/tests/saved-stacks/stringify-with-self-hosted.js
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/moz.build
js/src/vm/MemoryMetrics.cpp
js/src/vm/SavedStacks.cpp
js/src/vm/SavedStacks.h
js/src/vm/Stack.cpp
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -507,18 +507,17 @@ struct CompartmentStats
     macro(Other,   NotLiveGCThing, ionData) \
     macro(Other,   NotLiveGCThing, typeInferenceTypeScripts) \
     macro(Other,   NotLiveGCThing, typeInferenceAllocationSiteTables) \
     macro(Other,   NotLiveGCThing, typeInferenceArrayTypeTables) \
     macro(Other,   NotLiveGCThing, typeInferenceObjectTypeTables) \
     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)
         objectsExtra(),
         extra()
     {}
 
     CompartmentStats(const CompartmentStats &other)
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -18,17 +18,16 @@
 
 #include "jit/AsmJS.h"
 #include "jit/AsmJSLink.h"
 #include "js/StructuredClone.h"
 #include "vm/ForkJoin.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/ProxyObject.h"
-#include "vm/SavedStacks.h"
 #include "vm/TraceLogging.h"
 
 #include "jscntxtinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace JS;
 
@@ -846,35 +845,16 @@ CountHeap(JSContext *cx, unsigned argc, 
         JS_ReportOutOfMemory(cx);
         return false;
     }
 
     args.rval().setNumber(double(counter));
     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<SavedFrame*> 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)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != 1) {
         JS_ReportError(cx, "count argument required");
         return false;
@@ -1565,25 +1545,16 @@ static const JSFunctionSpecWithHelp Test
 "countHeap([start[, kind[, thing]]])",
 "  Count the number of live GC things in the heap or things reachable from\n"
 "  start when it is given and is not null. kind is either 'all' (default) to\n"
 "  count all things or one of 'object', 'double', 'string', 'function'\n"
 "  to count only things of that kind. If kind is the string 'specific',\n"
 "  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)",
 "  After 'count' js_malloc memory allocations, fail every following allocation\n"
 "  (return NULL)."),
 #endif
 
     JS_FN_HELP("makeFinalizeObserver", MakeFinalizeObserver, 0, 0,
deleted file mode 100644
--- 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");
deleted file mode 100644
--- 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);
deleted file mode 100644
--- 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);
-
deleted file mode 100644
--- 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);
deleted file mode 100644
--- 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);
deleted file mode 100644
--- 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);
deleted file mode 100644
--- 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);
-}
deleted file mode 100644
--- 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");
deleted file mode 100644
--- 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);
deleted file mode 100644
--- 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);
-
deleted file mode 100644
--- 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");
deleted file mode 100644
--- 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);
-}
deleted file mode 100644
--- 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");
deleted file mode 100644
--- 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);
deleted file mode 100644
--- 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);
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -108,19 +108,16 @@ JSCompartment::init(JSContext *cx)
 
     if (!regExps.init(cx))
         return false;
 
     enumerators = NativeIterator::allocateSentinel(cx);
     if (!enumerators)
         return false;
 
-    if (!savedStacks_.init())
-        return false;
-
     return debuggees.init(0);
 }
 
 #ifdef JS_ION
 jit::JitRuntime *
 JSRuntime::createJitRuntime(JSContext *cx)
 {
     // The shared stubs are created in the atoms compartment, which may be
@@ -561,17 +558,16 @@ JSCompartment::sweep(FreeOp *fop, bool r
 
         /* Remove dead references held weakly by the compartment. */
 
         sweepBaseShapeTable();
         sweepInitialShapeTable();
         sweepNewTypeObjectTable(newTypeObjects);
         sweepNewTypeObjectTable(lazyTypeObjects);
         sweepCallsiteClones();
-        savedStacks_.sweep(rt);
 
         if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet()))
             global_ = nullptr;
 
         if (selfHostingScriptSource &&
             IsObjectAboutToBeFinalized((JSObject **) selfHostingScriptSource.unsafeGet()))
         {
             selfHostingScriptSource = nullptr;
@@ -664,18 +660,16 @@ JSCompartment::clearTables()
     if (baseShapes.initialized())
         baseShapes.clear();
     if (initialShapes.initialized())
         initialShapes.clear();
     if (newTypeObjects.initialized())
         newTypeObjects.clear();
     if (lazyTypeObjects.initialized())
         lazyTypeObjects.clear();
-    if (savedStacks_.initialized())
-        savedStacks_.clear();
 }
 
 void
 JSCompartment::setObjectMetadataCallback(js::ObjectMetadataCallback callback)
 {
     // Clear any jitcode in the runtime, which behaves differently depending on
     // whether there is a creation callback.
     ReleaseAllJITCode(runtime_->defaultFreeOp());
@@ -916,29 +910,27 @@ void
 JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
                                       size_t *tiAllocationSiteTables,
                                       size_t *tiArrayTypeTables,
                                       size_t *tiObjectTypeTables,
                                       size_t *compartmentObject,
                                       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,
                                  tiArrayTypeTables, tiObjectTypeTables);
     *shapesCompartmentTables += baseShapes.sizeOfExcludingThis(mallocSizeOf)
                               + initialShapes.sizeOfExcludingThis(mallocSizeOf)
                               + newTypeObjects.sizeOfExcludingThis(mallocSizeOf)
                               + lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
     *crossCompartmentWrappersArg += crossCompartmentWrappers.sizeOfExcludingThis(mallocSizeOf);
     *regexpCompartment += regExps.sizeOfExcludingThis(mallocSizeOf);
     *debuggeesSet += debuggees.sizeOfExcludingThis(mallocSizeOf);
-    *savedStacksSet += savedStacks_.sizeOfExcludingThis(mallocSizeOf);
 }
 
 void
 JSCompartment::adoptWorkerAllocator(Allocator *workerAllocator)
 {
     zone()->allocator.arenas.adoptArenas(runtimeFromMainThread(), &workerAllocator->arenas);
 }
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -8,17 +8,16 @@
 #define jscompartment_h
 
 #include "mozilla/MemoryReporting.h"
 
 #include "builtin/TypedObject.h"
 #include "gc/Zone.h"
 #include "vm/GlobalObject.h"
 #include "vm/PIC.h"
-#include "vm/SavedStacks.h"
 
 namespace js {
 
 namespace jit {
 class JitCompartment;
 }
 
 namespace gc {
@@ -194,18 +193,16 @@ struct JSCompartment
     /* Type information about the scripts and objects in this compartment. */
     js::types::TypeCompartment   types;
 
     void                         *data;
 
   private:
     js::ObjectMetadataCallback   objectMetadataCallback;
 
-    js::SavedStacks              savedStacks_;
-
     js::WrapperMap               crossCompartmentWrappers;
 
   public:
     /* Last time at which an animation was played for a global in this compartment. */
     int64_t                      lastAnimationTime;
 
     js::RegExpCompartment        regExps;
 
@@ -222,18 +219,17 @@ struct JSCompartment
     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
                                 size_t *tiAllocationSiteTables,
                                 size_t *tiArrayTypeTables,
                                 size_t *tiObjectTypeTables,
                                 size_t *compartmentObject,
                                 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.
      */
     js::PropertyTree             propertyTree;
 
     /* Set of all unowned base shapes in the compartment. */
     js::BaseShapeSet             baseShapes;
@@ -341,18 +337,16 @@ struct JSCompartment
     void clearTables();
 
     bool hasObjectMetadataCallback() const { return objectMetadataCallback; }
     void setObjectMetadataCallback(js::ObjectMetadataCallback callback);
     bool callObjectMetadataCallback(JSContext *cx, JSObject **obj) const {
         return objectMetadataCallback(cx, obj);
     }
 
-    js::SavedStacks &savedStacks() { return savedStacks_; }
-
     void findOutgoingEdges(js::gc::ComponentFinder<JS::Zone> &finder);
 
     js::DtoaCache dtoaCache;
 
     /* Random number generator state, used by jsmath.cpp. */
     uint64_t rngState;
 
   private:
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -174,17 +174,16 @@ UNIFIED_SOURCES += [
     'vm/OldDebugAPI.cpp',
     'vm/PIC.cpp',
     'vm/Probes.cpp',
     'vm/PropertyKey.cpp',
     'vm/ProxyObject.cpp',
     'vm/RegExpObject.cpp',
     'vm/RegExpStatics.cpp',
     'vm/Runtime.cpp',
-    'vm/SavedStacks.cpp',
     'vm/ScopeObject.cpp',
     'vm/SelfHosting.cpp',
     'vm/Shape.cpp',
     'vm/SharedArrayObject.cpp',
     'vm/SPSProfiler.cpp',
     'vm/Stack.cpp',
     'vm/String.cpp',
     'vm/StringBuffer.cpp',
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -254,18 +254,17 @@ StatsCompartmentCallback(JSRuntime *rt, 
     compartment->addSizeOfIncludingThis(rtStats->mallocSizeOf_,
                                         &cStats.typeInferenceAllocationSiteTables,
                                         &cStats.typeInferenceArrayTypeTables,
                                         &cStats.typeInferenceObjectTypeTables,
                                         &cStats.compartmentObject,
                                         &cStats.shapesMallocHeapCompartmentTables,
                                         &cStats.crossCompartmentWrappersTable,
                                         &cStats.regexpCompartment,
-                                        &cStats.debuggeesSet,
-                                        &cStats.savedStacksSet);
+                                        &cStats.debuggeesSet);
 }
 
 static void
 StatsArenaCallback(JSRuntime *rt, void *data, gc::Arena *arena,
                    JSGCTraceKind traceKind, size_t thingSize)
 {
     RuntimeStats *rtStats = static_cast<StatsClosure *>(data)->rtStats;
 
deleted file mode 100644
--- 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<SavedFrame>().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<SavedFrame>() : nullptr;
-}
-
-JSPrincipals *
-SavedFrame::getPrincipals()
-{
-    const Value &v = getReservedSlot(JSSLOT_PRINCIPALS);
-    if (v.isUndefined())
-        return nullptr;
-    return static_cast<JSPrincipals *>(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<JSObject *>(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<SavedFrame>()) {
-        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<SavedFrame>() 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<SavedFrame>();
-}
-
-// 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<SavedFrame *> frame (will be non-null)
-#define THIS_SAVEDFRAME(cx, argc, vp, fnName, args, frame)         \
-    CallArgs args = CallArgsFromVp(argc, vp);                      \
-    Rooted<SavedFrame *> 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<SavedFrame*> 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<JSObject *>(e.front());
-            JSObject *temp = obj;
-
-            if (IsObjectAboutToBeFinalized(&obj)) {
-                e.removeFront();
-            } else {
-                SavedFrame *frame = &obj->as<SavedFrame>();
-                bool parentMoved = frame->parentMoved();
-
-                if (parentMoved) {
-                    frame->updatePrivateParent();
-                }
-
-                if (obj != temp || parentMoved) {
-                    Rooted<SavedFrame*> 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<SavedFrame*> frame)
-{
-    if (iter.done()) {
-        frame.set(nullptr);
-        return true;
-    }
-
-    ScriptFrameIter thisFrame(iter);
-    Rooted<SavedFrame*> 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<SavedFrame *> 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<GlobalObject *> 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<SavedFrame>();
-    f.initFromLookup(lookup);
-
-    return &f;
-}
-
-} /* namespace js */
deleted file mode 100644
--- 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<SavedFrame *,
-                    HashPolicy,
-                    SystemAllocPolicy> 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<SavedFrame*> 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<SavedFrame*> parent;
-    JSPrincipals        *principals;
-};
-
-struct SavedFrame::HashPolicy
-{
-    typedef SavedFrame::Lookup               Lookup;
-    typedef PointerHasher<SavedFrame *, 3>   SavedFramePtrHasher;
-    typedef PointerHasher<JSPrincipals *, 3> 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<SavedFrame*> 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<SavedFrame*> 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 */
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -672,17 +672,17 @@ FrameIter::FrameIter(JSContext *cx, Cont
 {
     settleOnActivation();
 }
 
 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
 {
 }
 
 FrameIter::FrameIter(const Data &data)
   : data_(data)
 #ifdef JS_ION
   , ionInlineFrames_(data.cx_, data_.jitFrames_.isIonJS() ? &data_.jitFrames_ : nullptr)