Bug 1114347 - Fix UseNewTypeForClone heuristic to check for the presence of |this|. r=bhackett
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 06 Jan 2015 17:05:56 +0100
changeset 248065 4a979ea519e248d197b639cc5034ef855d4f254e
parent 248064 3e1dac3caabe6e8874e7a089e862e79929b95d6b
child 248066 38f7539e3172f39aad5080f288eac6100b91a0e7
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1114347
milestone37.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 1114347 - Fix UseNewTypeForClone heuristic to check for the presence of |this|. r=bhackett
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/Parser.cpp
js/src/frontend/SharedContext.h
js/src/jsinfer.cpp
js/src/jsscript.cpp
js/src/jsscript.h
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -504,18 +504,18 @@ frontend::CompileLazyFunction(JSContext 
                                                   sourceObject, lazy->begin(), lazy->end()));
     if (!script)
         return false;
 
     script->bindings = pn->pn_funbox->bindings;
 
     if (lazy->directlyInsideEval())
         script->setDirectlyInsideEval();
-    if (lazy->usesArgumentsAndApply())
-        script->setUsesArgumentsAndApply();
+    if (lazy->usesArgumentsApplyAndThis())
+        script->setUsesArgumentsApplyAndThis();
     if (lazy->hasBeenCloned())
         script->setHasBeenCloned();
 
     BytecodeEmitter bce(/* parent = */ nullptr, &parser, pn->pn_funbox, script, lazy,
                         options.forEval, /* evalCaller = */ js::NullPtr(),
                         /* hasGlobalScope = */ true, options.lineno,
                         BytecodeEmitter::LazyFunction);
     if (!bce.init())
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5381,18 +5381,18 @@ EmitFunc(ExclusiveContext *cx, BytecodeE
                                  bce->emitterMode);
             if (!bce2.init())
                 return false;
 
             /* We measured the max scope depth when we parsed the function. */
             if (!EmitFunctionScript(cx, &bce2, pn->pn_body))
                 return false;
 
-            if (funbox->usesArguments && funbox->usesApply)
-                script->setUsesArgumentsAndApply();
+            if (funbox->usesArguments && funbox->usesApply && funbox->usesThis)
+                script->setUsesArgumentsApplyAndThis();
         }
     } else {
         MOZ_ASSERT(IsAsmJSModuleNative(fun->native()));
     }
 
     /* Make the function object a literal in the outer script's pool. */
     unsigned index = bce->objectList.add(pn->pn_funbox);
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -606,16 +606,17 @@ FunctionBox::FunctionBox(ExclusiveContex
     generatorKindBits_(GeneratorKindAsBits(generatorKind)),
     inWith(false),                  // initialized below
     inGenexpLambda(false),
     hasDestructuringArgs(false),
     useAsm(false),
     insideUseAsm(outerpc && outerpc->useAsmOrInsideUseAsm()),
     usesArguments(false),
     usesApply(false),
+    usesThis(false),
     funCxFlags()
 {
     // Functions created at parse time may be set singleton after parsing and
     // baked into JIT code, so they must be allocated tenured. They are held by
     // the JSScript so cannot be collected during a minor GC anyway.
     MOZ_ASSERT(fun->isTenured());
 
     if (!outerpc) {
@@ -2278,18 +2279,18 @@ Parser<SyntaxParseHandler>::finishFuncti
 
     HeapPtrFunction *innerFunctions = lazy->innerFunctions();
     for (size_t i = 0; i < numInnerFunctions; i++)
         innerFunctions[i].init(pc->innerFunctions[i]);
 
     if (pc->sc->strict)
         lazy->setStrict();
     lazy->setGeneratorKind(funbox->generatorKind());
-    if (funbox->usesArguments && funbox->usesApply)
-        lazy->setUsesArgumentsAndApply();
+    if (funbox->usesArguments && funbox->usesApply && funbox->usesThis)
+        lazy->setUsesArgumentsApplyAndThis();
     PropagateTransitiveParseFlags(funbox, lazy);
 
     fun->initLazyScript(lazy);
     return true;
 }
 
 template <>
 bool
@@ -8189,16 +8190,18 @@ Parser<ParseHandler>::primaryExpr(TokenK
       case TOK_NUMBER:
         return newNumber(tokenStream.currentToken());
 
       case TOK_TRUE:
         return handler.newBooleanLiteral(true, pos());
       case TOK_FALSE:
         return handler.newBooleanLiteral(false, pos());
       case TOK_THIS:
+        if (pc->sc->isFunctionBox())
+            pc->sc->asFunctionBox()->usesThis = true;
         return handler.newThisLiteral(pos());
       case TOK_NULL:
         return handler.newNullLiteral(pos());
 
       case TOK_TRIPLEDOT: {
         TokenKind next;
 
         // This isn't valid expression syntax, but it's valid in an arrow
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -250,16 +250,17 @@ class FunctionBox : public ObjectBox, pu
     bool            inGenexpLambda:1;       /* lambda from generator expression */
     bool            hasDestructuringArgs:1; /* arguments list contains destructuring expression */
     bool            useAsm:1;               /* see useAsmOrInsideUseAsm */
     bool            insideUseAsm:1;         /* see useAsmOrInsideUseAsm */
 
     // Fields for use in heuristics.
     bool            usesArguments:1;  /* contains a free use of 'arguments' */
     bool            usesApply:1;      /* contains an f.apply() call */
+    bool            usesThis:1;       /* contains 'this' */
 
     FunctionContextFlags funCxFlags;
 
     template <typename ParseHandler>
     FunctionBox(ExclusiveContext *cx, ObjectBox* traceListHead, JSFunction *fun,
                 ParseContext<ParseHandler> *pc, Directives directives,
                 bool extraWarnings, GeneratorKind generatorKind);
 
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3670,22 +3670,22 @@ types::UseNewTypeForClone(JSFunction *fu
      * initialize method. We capture this, along with similar cases, by looking
      * for short scripts which use both .apply and arguments. For such scripts,
      * whenever creating a new instance of the function we both give that
      * instance a singleton type and clone the underlying script.
      */
 
     uint32_t begin, end;
     if (fun->hasScript()) {
-        if (!fun->nonLazyScript()->usesArgumentsAndApply())
+        if (!fun->nonLazyScript()->usesArgumentsApplyAndThis())
             return false;
         begin = fun->nonLazyScript()->sourceStart();
         end = fun->nonLazyScript()->sourceEnd();
     } else {
-        if (!fun->lazyScript()->usesArgumentsAndApply())
+        if (!fun->lazyScript()->usesArgumentsApplyAndThis())
             return false;
         begin = fun->lazyScript()->begin();
         end = fun->lazyScript()->end();
     }
 
     return end - begin <= 100;
 }
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -3765,17 +3765,17 @@ LazyScript::CreateRaw(ExclusiveContext *
     p.version = version;
     p.numFreeVariables = numFreeVariables;
     p.numInnerFunctions = numInnerFunctions;
     p.generatorKindBits = GeneratorKindAsBits(NotGenerator);
     p.strict = false;
     p.bindingsAccessedDynamically = false;
     p.hasDebuggerStatement = false;
     p.directlyInsideEval = false;
-    p.usesArgumentsAndApply = false;
+    p.usesArgumentsApplyAndThis = false;
 
     LazyScript *res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column);
     MOZ_ASSERT_IF(res, res->version() == version);
     return res;
 }
 
 /* static */ LazyScript *
 LazyScript::Create(ExclusiveContext *cx, HandleFunction fun,
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -964,18 +964,18 @@ class JSScript : public js::gc::TenuredC
     bool isActiveEval_:1;
 
     // Script came from eval(), and is in eval cache.
     bool isCachedEval_:1;
 
     // Set for functions defined at the top level within an 'eval' script.
     bool directlyInsideEval_:1;
 
-    // Both 'arguments' and f.apply() are used. This is likely to be a wrapper.
-    bool usesArgumentsAndApply_:1;
+    // 'this', 'arguments' and f.apply() are used. This is likely to be a wrapper.
+    bool usesArgumentsApplyAndThis_:1;
 
     /* script is attempted to be cloned anew at each callsite. This is
        temporarily needed for ParallelArray selfhosted code until type
        information can be made context sensitive. See discussion in
        bug 826148. */
     bool shouldCloneAtCallsite_:1;
     bool isCallsiteClone_:1; /* is a callsite clone; has a link to the original function */
     bool shouldInline_:1;    /* hint to inline when possible */
@@ -1192,20 +1192,20 @@ class JSScript : public js::gc::TenuredC
         MOZ_ASSERT(isCachedEval() && !isActiveEval());
         isCachedEval_ = false;
         isActiveEval_ = true;
     }
 
     void setActiveEval() { isActiveEval_ = true; }
     void setDirectlyInsideEval() { directlyInsideEval_ = true; }
 
-    bool usesArgumentsAndApply() const {
-        return usesArgumentsAndApply_;
+    bool usesArgumentsApplyAndThis() const {
+        return usesArgumentsApplyAndThis_;
     }
-    void setUsesArgumentsAndApply() { usesArgumentsAndApply_ = true; }
+    void setUsesArgumentsApplyAndThis() { usesArgumentsApplyAndThis_ = true; }
 
     bool shouldCloneAtCallsite() const {
         return shouldCloneAtCallsite_;
     }
     bool shouldInline() const {
         return shouldInline_;
     }
 
@@ -1889,17 +1889,17 @@ class LazyScript : public gc::TenuredCel
 
         uint32_t generatorKindBits : 2;
 
         // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
         uint32_t strict : 1;
         uint32_t bindingsAccessedDynamically : 1;
         uint32_t hasDebuggerStatement : 1;
         uint32_t directlyInsideEval : 1;
-        uint32_t usesArgumentsAndApply : 1;
+        uint32_t usesArgumentsApplyAndThis : 1;
         uint32_t hasBeenCloned : 1;
         uint32_t treatAsRunOnce : 1;
     };
 
     union {
         PackedView p_;
         uint64_t packedFields_;
     };
@@ -2020,21 +2020,21 @@ class LazyScript : public gc::TenuredCel
 
     bool directlyInsideEval() const {
         return p_.directlyInsideEval;
     }
     void setDirectlyInsideEval() {
         p_.directlyInsideEval = true;
     }
 
-    bool usesArgumentsAndApply() const {
-        return p_.usesArgumentsAndApply;
+    bool usesArgumentsApplyAndThis() const {
+        return p_.usesArgumentsApplyAndThis;
     }
-    void setUsesArgumentsAndApply() {
-        p_.usesArgumentsAndApply = true;
+    void setUsesArgumentsApplyAndThis() {
+        p_.usesArgumentsApplyAndThis = true;
     }
 
     bool hasBeenCloned() const {
         return p_.hasBeenCloned;
     }
     void setHasBeenCloned() {
         p_.hasBeenCloned = true;
     }