Bug 1160182 - Handle extended functions in CreateLazyScriptsForCompartment. r=shu
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 13 May 2015 11:04:11 +0200
changeset 243663 7a62238aecdc491ae7cc60d37de1509d98e7a08e
parent 243662 fceaf20d128cb3b73eba8bbc31e56c497031710d
child 243664 1c91f5d39dea877e84bf75f38d7772c8893c1933
push id28744
push userkwierso@gmail.com
push dateWed, 13 May 2015 18:12:16 +0000
treeherdermozilla-central@324c3423deaf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1160182
milestone41.0a1
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
Bug 1160182 - Handle extended functions in CreateLazyScriptsForCompartment. r=shu
js/src/builtin/TestingFunctions.cpp
js/src/jit-test/tests/debug/bug1160182.js
js/src/jscompartment.cpp
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -418,17 +418,17 @@ IsLazyFunction(JSContext* cx, unsigned a
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != 1) {
         JS_ReportError(cx, "The function takes exactly one argument.");
         return false;
     }
     if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
         JS_ReportError(cx, "The first argument should be a function.");
-        return true;
+        return false;
     }
     args.rval().setBoolean(args[0].toObject().as<JSFunction>().isInterpretedLazy());
     return true;
 }
 
 static bool
 IsRelazifiableFunction(JSContext* cx, unsigned argc, Value* vp)
 {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug1160182.js
@@ -0,0 +1,11 @@
+var g = newGlobal();
+g.eval("(" + function() {
+    var o = {get x() {}};
+    this.method = Object.getOwnPropertyDescriptor(o, "x").get;
+    assertEq(isLazyFunction(method), true);
+} + ")()");
+var dbg = new Debugger();
+var gw = dbg.addDebuggee(g);
+var scripts = dbg.findScripts();
+var methodv = gw.makeDebuggeeValue(g.method);
+assertEq(scripts.indexOf(methodv.script) != -1, true);
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -744,35 +744,29 @@ AddInnerLazyFunctionsFromScript(JSScript
             if (!lazyFunctions.append(obj))
                 return false;
         }
     }
     return true;
 }
 
 static bool
-CreateLazyScriptsForCompartment(JSContext* cx)
+AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, AllocKind kind)
 {
-    AutoObjectVector lazyFunctions(cx);
-
     // Find all live root lazy functions in the compartment: those which have a
     // source object, indicating that they have a parent, and which do not have
     // an uncompiled enclosing script. The last condition is so that we don't
     // compile lazy scripts whose enclosing scripts failed to compile,
     // indicating that the lazy script did not escape the script.
     //
     // Some LazyScripts have a non-null |JSScript* script| pointer. We still
     // want to delazify in that case: this pointer is weak so the JSScript
     // could be destroyed at the next GC.
-    //
-    // Note that while we ideally iterate over LazyScripts, LazyScripts do not
-    // currently stand in 1-1 relation with JSScripts; JSFunctions with the
-    // same LazyScript may create different JSScripts due to relazification of
-    // clones. See bug 1105306.
-    for (gc::ZoneCellIter i(cx->zone(), AllocKind::FUNCTION); !i.done(); i.next()) {
+
+    for (gc::ZoneCellIter i(cx->zone(), kind); !i.done(); i.next()) {
         JSFunction* fun = &i.get<JSObject>()->as<JSFunction>();
 
         // Sweeping is incremental; take care to not delazify functions that
         // are about to be finalized. GC things referenced by objects that are
         // about to be finalized (e.g., in slots) may already be freed.
         if (gc::IsAboutToBeFinalizedUnbarriered(&fun) ||
             fun->compartment() != cx->compartment())
         {
@@ -783,16 +777,32 @@ CreateLazyScriptsForCompartment(JSContex
             LazyScript* lazy = fun->lazyScriptOrNull();
             if (lazy && lazy->sourceObject() && !lazy->hasUncompiledEnclosingScript()) {
                 if (!lazyFunctions.append(fun))
                     return false;
             }
         }
     }
 
+    return true;
+}
+
+static bool
+CreateLazyScriptsForCompartment(JSContext* cx)
+{
+    AutoObjectVector lazyFunctions(cx);
+
+    if (!AddLazyFunctionsForCompartment(cx, lazyFunctions, AllocKind::FUNCTION))
+        return false;
+
+    // Methods, for instance {get method() {}}, are extended functions that can
+    // be relazified, so we need to handle those as well.
+    if (!AddLazyFunctionsForCompartment(cx, lazyFunctions, AllocKind::FUNCTION_EXTENDED))
+        return false;
+
     // Create scripts for each lazy function, updating the list of functions to
     // process with any newly exposed inner functions in created scripts.
     // A function cannot be delazified until its outer script exists.
     for (size_t i = 0; i < lazyFunctions.length(); i++) {
         JSFunction* fun = &lazyFunctions[i]->as<JSFunction>();
 
         // lazyFunctions may have been populated with multiple functions for
         // a lazy script.