Bug 761510 - rm JSFUN_NULL_CLOSURE (r=jimb)
authorLuke Wagner <luke@mozilla.com>
Tue, 17 Jul 2012 16:35:58 -0700
changeset 99703 6a96719b7acf2cd2c5c29da830e9c62f8c527603
parent 99702 be1e9d076b8a367a004e4e2978aac35c2e145089
child 99704 8e406f71fadb009a313ca7b9d9b88a64976d3c12
push id12150
push userlwagner@mozilla.com
push dateWed, 18 Jul 2012 22:07:33 +0000
treeherdermozilla-inbound@8e406f71fadb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimb
bugs761510
milestone17.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 761510 - rm JSFUN_NULL_CLOSURE (r=jimb)
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/SemanticAnalysis.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/methodjit/Compiler.cpp
js/src/shell/js.cpp
js/src/vm/Xdr.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -4847,19 +4847,16 @@ EmitFunc(JSContext *cx, BytecodeEmitter 
          * for the already-emitted function definition prolog opcode. See
          * comments in EmitStatementList.
          */
         JS_ASSERT(pn->isOp(JSOP_NOP));
         JS_ASSERT(bce->sc->inFunction());
         return EmitFunctionDefNop(cx, bce, pn->pn_index);
     }
 
-    JS_ASSERT_IF(pn->pn_funbox->funIsHeavyweight(),
-                 fun->kind() == JSFUN_INTERPRETED);
-
     {
         FunctionBox *funbox = pn->pn_funbox;
         SharedContext sc(cx, /* scopeChain = */ NULL, fun, funbox, funbox->strictModeState);
         sc.cxFlags = funbox->cxFlags;
         if (bce->sc->funMightAliasLocals())
             sc.setFunMightAliasLocals();  // inherit funMightAliasLocals from parent
         sc.bindings.transfer(&funbox->bindings);
         JS_ASSERT_IF(bce->sc->inStrictMode(), sc.inStrictMode());
--- a/js/src/frontend/SemanticAnalysis.cpp
+++ b/js/src/frontend/SemanticAnalysis.cpp
@@ -51,56 +51,18 @@ SetFunctionKinds(FunctionBox *funbox, bo
         ParseNode *pn = fn->pn_body;
         if (!pn)
             continue;
 
         if (funbox->kids)
             SetFunctionKinds(funbox->kids, isHeavyweight, topInFunction, isDirectEval);
 
         JSFunction *fun = funbox->function();
-
-        JS_ASSERT(fun->kind() == JSFUN_INTERPRETED);
-
-        if (funbox->funIsHeavyweight()) {
-            /* nothing to do */
-        } else if (isDirectEval || funbox->inAnyDynamicScope()) {
-            /*
-             * Either we are in a with-block or a function scope that is
-             * subject to direct eval; or we are compiling strict direct eval
-             * code.
-             *
-             * In either case, fun may reference names that are not bound but
-             * are not necessarily global either. (In the strict direct eval
-             * case, we could bind them, but currently do not bother; see
-             * the comment about strict mode code in BindTopLevelVar.)
-             */
-            JS_ASSERT(!fun->isNullClosure());
-        } else {
-            bool hasUpvars = false;
-
-            if (pn->isKind(PNK_UPVARS)) {
-                AtomDefnMapPtr upvars = pn->pn_names;
-                JS_ASSERT(!upvars->empty());
-
-                /* Determine whether the this function contains upvars. */
-                for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) {
-                    if (!r.front().value()->resolve()->isFreeVar()) {
-                        hasUpvars = true;
-                        break;
-                    }
-                }
-            }
-
-            if (!hasUpvars) {
-                /* No lexical dependencies => null closure, for best performance. */
-                fun->setKind(JSFUN_NULL_CLOSURE);
-            }
-        }
-
-        if (fun->kind() == JSFUN_INTERPRETED && pn->isKind(PNK_UPVARS)) {
+        JS_ASSERT(fun->isInterpreted());
+        if (pn->isKind(PNK_UPVARS)) {
             /*
              * We loop again over all upvars, and for each non-free upvar,
              * ensure that its containing function has been flagged as
              * heavyweight.
              *
              * The emitter must see funIsHeavyweight() accurately before
              * generating any code for a tree of nested functions.
              */
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -382,17 +382,16 @@ js::XDRInterpretedFunction(XDRState<mode
     if (!xdr->codeUint32(&flagsword))
         return false;
 
     if (!XDRScript(xdr, enclosingScope, enclosingScript, fun, &script))
         return false;
 
     if (mode == XDR_DECODE) {
         fun->nargs = flagsword >> 16;
-        JS_ASSERT((flagsword & JSFUN_KINDMASK) >= JSFUN_INTERPRETED);
         fun->flags = uint16_t(flagsword);
         fun->atom.init(atom);
         fun->initScript(script);
         script->setFunction(fun);
         if (!fun->setTypeForScriptedFunction(cx))
             return false;
         JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs());
         js_CallNewScriptHook(cx, fun->script(), fun);
@@ -1214,18 +1213,18 @@ js_NewFunction(JSContext *cx, JSObject *
         funobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
         if (!funobj)
             return NULL;
     }
     RootedFunction fun(cx, static_cast<JSFunction *>(funobj));
 
     /* Initialize all function members. */
     fun->nargs = uint16_t(nargs);
-    fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK);
-    if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) {
+    fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED);
+    if (flags & JSFUN_INTERPRETED) {
         JS_ASSERT(!native);
         fun->mutableScript().init(NULL);
         fun->initEnvironment(parent);
     } else {
         fun->u.native = native;
         JS_ASSERT(fun->u.native);
     }
     if (kind == JSFunction::ExtendedFinalizeKind) {
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -35,19 +35,16 @@
  * pointer-chasing.
  */
 #define JSFUN_PROTOTYPE     0x0800  /* function is Function.prototype for some
                                        global object */
 
 #define JSFUN_EXPR_CLOSURE  0x1000  /* expression closure: function(x) x*x */
 #define JSFUN_EXTENDED      0x2000  /* structure is FunctionExtended */
 #define JSFUN_INTERPRETED   0x4000  /* use u.i if kind >= this value else u.native */
-#define JSFUN_NULL_CLOSURE  0x8000  /* null closure entrains no scope chain */
-#define JSFUN_KINDMASK      0xc000  /* encode interp vs. native and closure
-                                       optimization level -- see above */
 
 namespace js { class FunctionExtended; }
 
 struct JSFunction : public JSObject
 {
     uint16_t        nargs;        /* maximum number of specified arguments,
                                      reflected as f.length/f.arity */
     uint16_t        flags;        /* flags, see JSFUN_* below and in jsapi.h */
@@ -60,31 +57,24 @@ struct JSFunction : public JSObject
                                      use the accessor! */
         } i;
         void            *nativeOrScript;
     } u;
     js::HeapPtrAtom  atom;        /* name for diagnostics and decompiling */
 
     bool hasDefaults()       const { return flags & JSFUN_HAS_DEFAULTS; }
     bool hasRest()           const { return flags & JSFUN_HAS_REST; }
-    bool isInterpreted()     const { return kind() >= JSFUN_INTERPRETED; }
+    bool isInterpreted()     const { return flags & JSFUN_INTERPRETED; }
     bool isNative()          const { return !isInterpreted(); }
     bool isNativeConstructor() const { return flags & JSFUN_CONSTRUCTOR; }
     bool isHeavyweight()     const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
-    bool isNullClosure()     const { return kind() == JSFUN_NULL_CLOSURE; }
     bool isFunctionPrototype() const { return flags & JSFUN_PROTOTYPE; }
     bool isInterpretedConstructor() const { return isInterpreted() && !isFunctionPrototype(); }
     bool isNamedLambda()     const { return (flags & JSFUN_LAMBDA) && atom; }
 
-    uint16_t kind()          const { return flags & JSFUN_KINDMASK; }
-    void setKind(uint16_t k) {
-        JS_ASSERT(!(k & ~JSFUN_KINDMASK));
-        flags = (flags & ~JSFUN_KINDMASK) | k;
-    }
-
     /* Returns the strictness of this function, which must be interpreted. */
     inline bool inStrictMode() const;
 
     void setArgCount(uint16_t nargs) {
         JS_ASSERT(this->nargs == 0);
         this->nargs = nargs;
     }
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -4238,18 +4238,18 @@ mjit::Compiler::inlineCallHelper(uint32_
         /*
          * Test if the callee is even a function. If this doesn't match, we
          * take a _really_ slow path later.
          */
         Jump notFunction = stubcc.masm.testFunction(Assembler::NotEqual, icCalleeData, tmp);
 
         /* Test if the function is scripted. */
         stubcc.masm.load16(Address(icCalleeData, offsetof(JSFunction, flags)), tmp);
-        stubcc.masm.and32(Imm32(JSFUN_KINDMASK), tmp);
-        Jump isNative = stubcc.masm.branch32(Assembler::Below, tmp, Imm32(JSFUN_INTERPRETED));
+        Jump isNative = stubcc.masm.branchTest32(Assembler::Zero, tmp,
+                                                 Imm32(JSFUN_INTERPRETED));
         tempRegs.putReg(tmp);
 
         /*
          * N.B. After this call, the frame will have a dynamic frame size.
          * Check after the function is known not to be a native so that the
          * catch-all/native path has a static depth.
          */
         if (callIC.frameSize.isDynamic()) {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1722,19 +1722,16 @@ DisassembleScript(JSContext *cx, JSScrip
 #define SHOW_FLAG(flag) if (flags & JSFUN_##flag) Sprint(sp, " " #flag);
 
         SHOW_FLAG(LAMBDA);
         SHOW_FLAG(HEAVYWEIGHT);
         SHOW_FLAG(EXPR_CLOSURE);
 
 #undef SHOW_FLAG
 
-        if (fun->isNullClosure())
-            Sprint(sp, " NULL_CLOSURE");
-
         Sprint(sp, "\n");
     }
 
     if (!js_Disassemble(cx, script, lines, sp))
         return false;
     SrcNotes(cx, script, sp);
     TryNotes(cx, script, sp);
 
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -20,17 +20,17 @@ namespace js {
  * Bytecode version number. Increment the subtrahend whenever JS bytecode
  * changes incompatibly.
  *
  * This version number is XDR'd near the front of xdr bytecode and
  * aborts deserialization if there is a mismatch between the current
  * and saved versions. If deserialization fails, the data should be
  * invalidated if possible.
  */
-static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 120);
+static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 121);
 
 class XDRBuffer {
   public:
     XDRBuffer(JSContext *cx)
       : context(cx), base(NULL), cursor(NULL), limit(NULL) { }
 
     JSContext *cx() const {
         return context;