Bug 757336 - Clean up probes handling in CompileScript(). r=sfink.
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 22 May 2012 16:50:10 -0700
changeset 94639 4af1ce11dbed8447e3198c0334a7f051aeac7b09
parent 94638 f713ee5937ab3e395f91a94c410de26d67652e28
child 94640 87b89795891fa7afbecf7ad2ef8807f98ef55334
push id22732
push useremorley@mozilla.com
push dateWed, 23 May 2012 09:43:13 +0000
treeherdermozilla-central@aa2b52bd0374 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs757336
milestone15.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 757336 - Clean up probes handling in CompileScript(). r=sfink.
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/Parser.cpp
js/src/frontend/TreeContext-inl.h
js/src/frontend/TreeContext.h
js/src/jsprobes.h
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -69,148 +69,152 @@ JSScript *
 frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerFrame,
                         JSPrincipals *principals, JSPrincipals *originPrincipals,
                         bool compileAndGo, bool noScriptRval, bool needScriptGlobal,
                         const jschar *chars, size_t length,
                         const char *filename, unsigned lineno, JSVersion version,
                         JSString *source /* = NULL */,
                         unsigned staticLevel /* = 0 */)
 {
-    TokenKind tt;
-    ParseNode *pn;
-    bool inDirectivePrologue;
+    class ProbesManager
+    {
+        const char* filename;
+        unsigned lineno;
+
+      public:
+        ProbesManager(const char *f, unsigned l) : filename(f), lineno(l) {
+            Probes::compileScriptBegin(filename, lineno);
+        }
+        ~ProbesManager() { Probes::compileScriptEnd(filename, lineno); }
+    }; 
+    ProbesManager probesManager(filename, lineno);
 
     /*
      * The scripted callerFrame can only be given for compile-and-go scripts
      * and non-zero static level requires callerFrame.
      */
     JS_ASSERT_IF(callerFrame, compileAndGo);
     JS_ASSERT_IF(staticLevel != 0, callerFrame);
 
     bool foldConstants = true;
     Parser parser(cx, principals, originPrincipals, callerFrame, foldConstants, compileAndGo);
     if (!parser.init(chars, length, filename, lineno, version))
         return NULL;
 
-    TokenStream &tokenStream = parser.tokenStream;
-
     SharedContext sc(cx, /* inFunction = */ false);
 
     TreeContext tc(&parser, &sc);
-    if (!tc.init(cx))
+    if (!tc.init())
         return NULL;
 
-    BytecodeEmitter bce(&parser, &sc, tokenStream.getLineno(), noScriptRval, needScriptGlobal);
+    BytecodeEmitter bce(&parser, &sc, lineno, noScriptRval, needScriptGlobal);
     if (!bce.init())
         return NULL;
 
-    Probes::compileScriptBegin(cx, filename, lineno);
-    MUST_FLOW_THROUGH("out");
-
     // We can specialize a bit for the given scope chain if that scope chain is the global object.
     JSObject *globalObj = scopeChain && scopeChain == &scopeChain->global()
                           ? &scopeChain->global()
                           : NULL;
 
     JS_ASSERT_IF(globalObj, globalObj->isNative());
     JS_ASSERT_IF(globalObj, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalObj->getClass()));
 
-    RootedVar<JSScript*> script(cx);
-
     GlobalScope globalScope(cx, globalObj);
     bce.sc->setScopeChain(scopeChain);
     bce.globalScope = &globalScope;
     if (!SetStaticLevel(bce.sc, staticLevel))
-        goto out;
+        return NULL;
 
     /* If this is a direct call to eval, inherit the caller's strictness.  */
     if (callerFrame &&
         callerFrame->isScriptFrame() &&
         callerFrame->script()->strictModeCode)
     {
         bce.sc->setInStrictMode();
-        tokenStream.setStrictMode();
+        parser.tokenStream.setStrictMode();
     }
 
 #ifdef DEBUG
     bool savedCallerFun;
     savedCallerFun = false;
 #endif
     if (compileAndGo) {
         if (source) {
             /*
              * Save eval program source in script->atoms[0] for the
              * eval cache (see EvalCacheLookup in jsobj.cpp).
              */
             JSAtom *atom = js_AtomizeString(cx, source);
             jsatomid _;
             if (!atom || !bce.makeAtomIndex(atom, &_))
-                goto out;
+                return NULL;
         }
 
         if (callerFrame && callerFrame->isFunctionFrame()) {
             /*
              * An eval script in a caller frame needs to have its enclosing
              * function captured in case it refers to an upvar, and someone
              * wishes to decompile it while it's running.
              */
             ObjectBox *funbox = parser.newObjectBox(callerFrame->fun());
             if (!funbox)
-                goto out;
+                return NULL;
             funbox->emitLink = bce.objectList.lastbox;
             bce.objectList.lastbox = funbox;
             bce.objectList.length++;
 #ifdef DEBUG
             savedCallerFun = true;
 #endif
         }
     }
 
     /*
      * Inline this->statements to emit as we go to save AST space. We must
      * generate our script-body blockid since we aren't calling Statements.
      */
     uint32_t bodyid;
     if (!GenerateBlockId(bce.sc, bodyid))
-        goto out;
+        return NULL;
     bce.sc->bodyid = bodyid;
 
+    ParseNode *pn;
 #if JS_HAS_XML_SUPPORT
     pn = NULL;
     bool onlyXML;
     onlyXML = true;
 #endif
 
-    inDirectivePrologue = true;
+    bool inDirectivePrologue = true;
+    TokenStream &tokenStream = parser.tokenStream;
     tokenStream.setOctalCharacterEscape(false);
     for (;;) {
-        tt = tokenStream.peekToken(TSF_OPERAND);
+        TokenKind tt = tokenStream.peekToken(TSF_OPERAND);
         if (tt <= TOK_EOF) {
             if (tt == TOK_EOF)
                 break;
             JS_ASSERT(tt == TOK_ERROR);
-            goto out;
+            return NULL;
         }
 
         pn = parser.statement();
         if (!pn)
-            goto out;
+            return NULL;
 
         if (inDirectivePrologue && !parser.recognizeDirectivePrologue(pn, &inDirectivePrologue))
-            goto out;
+            return NULL;
 
         if (!FoldConstants(cx, pn, bce.parser))
-            goto out;
+            return NULL;
 
         if (!AnalyzeFunctions(bce.parser))
-            goto out;
+            return NULL;
         bce.sc->functionList = NULL;
 
         if (!EmitTree(cx, &bce, pn))
-            goto out;
+            return NULL;
 
 #if JS_HAS_XML_SUPPORT
         if (!pn->isKind(PNK_SEMI) || !pn->pn_kid || !pn->pn_kid->isXMLItem())
             onlyXML = false;
 #endif
         bce.parser->freeTree(pn);
     }
 
@@ -218,40 +222,39 @@ frontend::CompileScript(JSContext *cx, J
     /*
      * Prevent XML data theft via <script src="http://victim.com/foo.xml">.
      * For background, see:
      *
      * https://bugzilla.mozilla.org/show_bug.cgi?id=336551
      */
     if (pn && onlyXML && !callerFrame) {
         parser.reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_XML_WHOLE_PROGRAM);
-        goto out;
+        return NULL;
     }
 #endif
 
     /*
      * Nowadays the threaded interpreter needs a stop instruction, so we
      * do have to emit that here.
      */
     if (Emit1(cx, &bce, JSOP_STOP) < 0)
-        goto out;
+        return NULL;
 
     JS_ASSERT(bce.version() == version);
 
+    RootedVar<JSScript*> script(cx);
     script = JSScript::NewScriptFromEmitter(cx, &bce);
     if (!script)
-        goto out;
+        return NULL;
 
     JS_ASSERT(script->savedCallerFun == savedCallerFun);
 
     if (!MarkInnerAndOuterFunctions(cx, script))
-        script = NULL;
+        return NULL;
 
-  out:
-    Probes::compileScriptEnd(cx, script, filename, lineno);
     return script;
 }
 
 /*
  * Compile a JS function body, which might appear as the value of an event
  * handler attribute in an HTML <INPUT> tag.
  */
 bool
@@ -264,20 +267,20 @@ frontend::CompileFunctionBody(JSContext 
     if (!parser.init(chars, length, filename, lineno, version))
         return false;
 
     TokenStream &tokenStream = parser.tokenStream;
 
     SharedContext funsc(cx, /* inFunction = */ true);
 
     TreeContext funtc(&parser, &funsc);
-    if (!funtc.init(cx))
+    if (!funtc.init())
         return NULL;
 
-    BytecodeEmitter funbce(&parser, &funsc, tokenStream.getLineno(),
+    BytecodeEmitter funbce(&parser, &funsc, lineno,
                            /* noScriptRval = */ false, /* needsScriptGlobal = */ false);
     if (!funbce.init())
         return false;
 
     funsc.setFunction(fun);
     funsc.bindings.transfer(cx, bindings);
     fun->setArgCount(funsc.bindings.numArgs());
     if (!GenerateBlockId(&funsc, funsc.bodyid))
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -261,17 +261,17 @@ Parser::parse(JSObject *chain)
      * - nest on this thread due to out of memory (the so-called "last ditch"
      *   GC attempted within js_NewGCThing), or
      * - run for any reason on another thread if this thread is suspended on
      *   an object lock before it finishes generating bytecode into a script
      *   protected from the GC by a root or a stack frame reference.
      */
     SharedContext globalsc(context, /* inFunction = */ false);
     TreeContext globaltc(this, &globalsc);
-    if (!globaltc.init(context))
+    if (!globaltc.init())
         return NULL;
     globalsc.setScopeChain(chain);
     if (!GenerateBlockId(&globalsc, globalsc.bodyid))
         return NULL;
 
     ParseNode *pn = statements();
     if (pn) {
         if (!tokenStream.matchToken(TOK_EOF)) {
@@ -1500,17 +1500,17 @@ Parser::functionDef(HandlePropertyName f
         }
     }
 
     TreeContext *outertc = tc;
 
     /* Initialize early for possible flags mutation via destructuringExpr. */
     SharedContext funsc(context, /* inFunction = */ true);
     TreeContext funtc(this, &funsc);
-    if (!funtc.init(context))
+    if (!funtc.init())
         return NULL;
 
     FunctionBox *funbox = EnterFunction(pn, this, funName, kind);
     if (!funbox)
         return NULL;
 
     if (outertc->sc->inStrictMode())
         funsc.setInStrictMode();    // inherit strict mode from parent
@@ -5423,17 +5423,17 @@ Parser::generatorExpr(ParseNode *kid)
     genfn->setOp(JSOP_LAMBDA);
     JS_ASSERT(!genfn->pn_body);
     genfn->pn_dflags = 0;
 
     {
         TreeContext *outertc = tc;
         SharedContext gensc(context, /* inFunction = */ true);
         TreeContext gentc(this, &gensc);
-        if (!gentc.init(context))
+        if (!gentc.init())
             return NULL;
 
         FunctionBox *funbox = EnterFunction(genfn, this);
         if (!funbox)
             return NULL;
 
         /*
          * We assume conservatively that any deoptimization flags in tc->sc
@@ -6382,17 +6382,17 @@ Parser::parseXMLText(JSObject *chain, bo
 {
     /*
      * Push a compiler frame if we have no frames, or if the top frame is a
      * lightweight function activation, or if its scope chain doesn't match
      * the one passed to us.
      */
     SharedContext xmlsc(context, /* inFunction = */ false);
     TreeContext xmltc(this, &xmlsc);
-    if (!xmltc.init(context))
+    if (!xmltc.init())
         return NULL;
     JS_ASSERT(!xmlsc.inStrictMode());
     xmlsc.setScopeChain(chain);
 
     /* Set XML-only mode to turn off special treatment of {expr} in XML. */
     tokenStream.setXMLOnlyMode();
     TokenKind tt = tokenStream.getToken(TSF_OPERAND);
 
--- a/js/src/frontend/TreeContext-inl.h
+++ b/js/src/frontend/TreeContext-inl.h
@@ -78,17 +78,17 @@ TreeContext::TreeContext(Parser *prs, Sh
     hasReturnExpr(false),
     hasReturnVoid(false),
     inDeclDestructuring(false)
 {
     prs->tc = this;
 }
 
 inline bool
-TreeContext::init(JSContext *cx)
+TreeContext::init()
 {
     return decls.init() && lexdeps.ensureMap(sc->context);
 }
 
 // For functions the tree context is constructed and destructed a second
 // time during code generation. To avoid a redundant stats update in such
 // cases, we store UINT16_MAX in maxScopeDepth.
 inline
--- a/js/src/frontend/TreeContext.h
+++ b/js/src/frontend/TreeContext.h
@@ -274,17 +274,17 @@ struct TreeContext {                /* t
     // they need to be treated differently.
     bool            inDeclDestructuring:1;
 
     void trace(JSTracer *trc);
 
     inline TreeContext(Parser *prs, SharedContext *sc);
     inline ~TreeContext();
 
-    inline bool init(JSContext *cx);
+    inline bool init();
 };
 
 /*
  * NB: If you add enumerators for scope statements, add them between STMT_WITH
  * and STMT_CATCH, or you will break the STMT_TYPE_IS_SCOPE macro. If you add
  * non-looping statement enumerators, add them before STMT_DO_LOOP or you will
  * break the STMT_TYPE_IS_LOOP macro.
  *
--- a/js/src/jsprobes.h
+++ b/js/src/jsprobes.h
@@ -136,20 +136,20 @@ bool createString(JSContext *cx, JSStrin
 /*
  * String is about to be finalized
  *
  * |string| must still have a valid length.
  */
 bool finalizeString(JSString *string);
 
 /* Script is about to be compiled */
-bool compileScriptBegin(JSContext *cx, const char *filename, int lineno);
+bool compileScriptBegin(const char *filename, int lineno);
 
 /* Script has just finished compilation */
-bool compileScriptEnd(JSContext *cx, JSScript *script, const char *filename, int lineno);
+bool compileScriptEnd(const char *filename, int lineno);
 
 /* About to make a call from JS into native code */
 bool calloutBegin(JSContext *cx, JSFunction *fun);
 
 /* Native code called by JS has terminated */
 bool calloutEnd(JSContext *cx, JSFunction *fun);
 
 /* Unimplemented */
@@ -531,30 +531,30 @@ Probes::finalizeString(JSString *string)
     if (ProfilingActive && !ETWFinalizeString(string))
         ok = false;
 #endif
 
     return ok;
 }
 
 inline bool
-Probes::compileScriptBegin(JSContext *cx, const char *filename, int lineno)
+Probes::compileScriptBegin(const char *filename, int lineno)
 {
     bool ok = true;
 
 #ifdef MOZ_ETW
     if (ProfilingActive && !ETWCompileScriptBegin(filename, lineno))
         ok = false;
 #endif
 
     return ok;
 }
 
 inline bool
-Probes::compileScriptEnd(JSContext *cx, JSScript *script, const char *filename, int lineno)
+Probes::compileScriptEnd(const char *filename, int lineno)
 {
     bool ok = true;
 
 #ifdef MOZ_ETW
     if (ProfilingActive && !ETWCompileScriptEnd(filename, lineno))
         ok = false;
 #endif