Bug 752816 (part 2) - Remove TCF_{NO_SCRIPT_RVAL,NEED_SCRIPT_GLOBAL} from TreeContextFlags. r=luke.

--HG--
extra : rebase_source : 26aacee3d6663be4a77a758b5ebab77a48c797e5
This commit is contained in:
Nicholas Nethercote 2012-05-14 18:00:17 -07:00
parent 8166b79251
commit fd43f617aa
9 changed files with 69 additions and 53 deletions

View File

@ -101,7 +101,7 @@ MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script)
JSScript *
frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerFrame,
JSPrincipals *principals, JSPrincipals *originPrincipals,
uint32_t tcflags,
bool compileAndGo, bool noScriptRval, bool needScriptGlobal,
const jschar *chars, size_t length,
const char *filename, unsigned lineno, JSVersion version,
JSString *source /* = NULL */,
@ -111,13 +111,11 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
ParseNode *pn;
bool inDirectivePrologue;
JS_ASSERT(!(tcflags & ~(TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL | TCF_NEED_SCRIPT_GLOBAL)));
/*
* The scripted callerFrame can only be given for compile-and-go scripts
* and non-zero static level requires callerFrame.
*/
JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO);
JS_ASSERT_IF(callerFrame, compileAndGo);
JS_ASSERT_IF(staticLevel != 0, callerFrame);
Parser parser(cx, principals, originPrincipals, callerFrame);
@ -132,7 +130,7 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
if (!tc.init(cx))
return NULL;
BytecodeEmitter bce(&parser, &sc, tokenStream.getLineno());
BytecodeEmitter bce(&parser, &sc, tokenStream.getLineno(), noScriptRval, needScriptGlobal);
if (!bce.init())
return NULL;
@ -149,8 +147,9 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
RootedVar<JSScript*> script(cx);
sc.flags |= compileAndGo ? TCF_COMPILE_N_GO : 0;
GlobalScope globalScope(cx, globalObj);
bce.sc->flags |= tcflags;
bce.sc->setScopeChain(scopeChain);
bce.globalScope = &globalScope;
if (!SetStaticLevel(bce.sc, staticLevel))
@ -168,7 +167,7 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
bool savedCallerFun;
savedCallerFun = false;
#endif
if (tcflags & TCF_COMPILE_N_GO) {
if (compileAndGo) {
if (source) {
/*
* Save eval program source in script->atoms[0] for the
@ -306,7 +305,8 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
if (!funtc.init(cx))
return NULL;
BytecodeEmitter funbce(&parser, &funsc, tokenStream.getLineno());
BytecodeEmitter funbce(&parser, &funsc, tokenStream.getLineno(),
/* noScriptRval = */ false, /* needsScriptGlobal = */ false);
if (!funbce.init())
return false;

View File

@ -55,7 +55,8 @@ CompileFunctionBody(JSContext *cx, JSFunction *fun,
JSScript *
CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerFrame,
JSPrincipals *principals, JSPrincipals *originPrincipals,
uint32_t tcflags, const jschar *chars, size_t length,
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);

View File

@ -98,7 +98,8 @@ NewTryNote(JSContext *cx, BytecodeEmitter *bce, JSTryNoteKind kind, unsigned sta
static JSBool
SetSrcNoteOffset(JSContext *cx, BytecodeEmitter *bce, unsigned index, unsigned which, ptrdiff_t offset);
BytecodeEmitter::BytecodeEmitter(Parser *parser, SharedContext *sc, unsigned lineno)
BytecodeEmitter::BytecodeEmitter(Parser *parser, SharedContext *sc, unsigned lineno,
bool noScriptRval, bool needScriptGlobal)
: sc(sc),
parent(NULL),
parser(parser),
@ -112,7 +113,9 @@ BytecodeEmitter::BytecodeEmitter(Parser *parser, SharedContext *sc, unsigned lin
globalScope(NULL),
closedArgs(sc->context),
closedVars(sc->context),
typesetCount(0)
typesetCount(0),
noScriptRval(noScriptRval),
needScriptGlobal(needScriptGlobal)
{
memset(&prolog, 0, sizeof prolog);
memset(&main, 0, sizeof main);
@ -4828,7 +4831,8 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
SharedContext sc(cx);
BytecodeEmitter bce2(bce->parser, &sc, pn->pn_pos.begin.lineno);
BytecodeEmitter bce2(bce->parser, &sc, pn->pn_pos.begin.lineno,
/* noScriptRval = */ false, /* needsScriptGlobal = */ false);
if (!bce2.init())
return false;
@ -5200,8 +5204,13 @@ EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* API users may also set the JSOPTION_NO_SCRIPT_RVAL option when
* calling JS_Compile* to suppress JSOP_POPV.
*/
bool wantval;
JSBool useful = wantval = !(bce->sc->flags & (TCF_IN_FUNCTION | TCF_NO_SCRIPT_RVAL));
bool wantval = false;
JSBool useful = JS_FALSE;
if (bce->sc->inFunction()) {
JS_ASSERT(!bce->noScriptRval);
} else {
useful = wantval = !bce->noScriptRval;
}
/* Don't eliminate expressions with side effects. */
if (!useful) {

View File

@ -154,7 +154,13 @@ struct BytecodeEmitter
uint16_t typesetCount; /* Number of JOF_TYPESET opcodes generated */
BytecodeEmitter(Parser *parser, SharedContext *sc, unsigned lineno);
/* These two should only be true if sc->inFunction() is false. */
const bool noScriptRval:1; /* The caller is JS_Compile*Script*. */
const bool needScriptGlobal:1; /* API caller does not want result value
from global script. */
BytecodeEmitter(Parser *parser, SharedContext *sc, unsigned lineno,
bool noScriptRval, bool needScriptGlobal);
bool init();
/*

View File

@ -76,15 +76,12 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
// script can optimize name references based on scope chain
TCF_COMPILE_N_GO = 0x20,
// API caller does not want result value from global script
TCF_NO_SCRIPT_RVAL = 0x40,
// This function/global/eval code body contained a Use Strict Directive.
// Treat certain strict warnings as errors, and forbid the use of 'with'.
// See also TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and
// JSREPORT_STRICT_ERROR.
//
TCF_STRICT_MODE_CODE = 0x80,
TCF_STRICT_MODE_CODE = 0x40,
// The (static) bindings of this script need to support dynamic name
// read/write access. Here, 'dynamic' means dynamic dictionary lookup on
@ -106,17 +103,17 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
// taken not to turn off the whole 'arguments' optimization). To answer the
// more general "is this argument aliased" question, script->needsArgsObj
// should be tested (see JSScript::argIsAlised).
TCF_BINDINGS_ACCESSED_DYNAMICALLY = 0x100,
TCF_BINDINGS_ACCESSED_DYNAMICALLY = 0x80,
// The function or a function that encloses it may define new local names
// at runtime through means other than calling eval.
TCF_FUN_MIGHT_ALIAS_LOCALS = 0x200,
TCF_FUN_MIGHT_ALIAS_LOCALS = 0x100,
// The script contains singleton initialiser JSOP_OBJECT.
TCF_HAS_SINGLETONS = 0x400,
TCF_HAS_SINGLETONS = 0x200,
// Some enclosing scope is a with-statement or E4X filter-expression.
TCF_IN_WITH = 0x800,
TCF_IN_WITH = 0x400,
// This function does something that can extend the set of bindings in its
// call objects --- it does a direct eval in non-strict code, or includes a
@ -125,10 +122,7 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
// This flag is *not* inherited by enclosed or enclosing functions; it
// applies only to the function in whose flags it appears.
//
TCF_FUN_EXTENSIBLE_SCOPE = 0x1000,
// The caller is JS_Compile*Script*.
TCF_NEED_SCRIPT_GLOBAL = 0x2000,
TCF_FUN_EXTENSIBLE_SCOPE = 0x800,
// Technically, every function has a binding named 'arguments'. Internally,
// this binding is only added when 'arguments' is mentioned by the function
@ -151,7 +145,7 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
// have no special semantics: the initial value is unconditionally the
// actual argument (or undefined if nactual < nformal).
//
TCF_ARGUMENTS_HAS_LOCAL_BINDING = 0x4000,
TCF_ARGUMENTS_HAS_LOCAL_BINDING = 0x1000,
// In many cases where 'arguments' has a local binding (as described above)
// we do not need to actually create an arguments object in the function
@ -162,7 +156,7 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
// be unsound in several cases. The frontend filters out such cases by
// setting this flag which eagerly sets script->needsArgsObj to true.
//
TCF_DEFINITELY_NEEDS_ARGS_OBJ = 0x8000
TCF_DEFINITELY_NEEDS_ARGS_OBJ = 0x2000
} JS_ENUM_FOOTER(TreeContextFlags);

View File

@ -4798,13 +4798,6 @@ struct AutoLastFrameCheck {
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
inline static uint32_t
JS_OPTIONS_TO_TCFLAGS(JSContext *cx)
{
return (cx->hasRunOption(JSOPTION_COMPILE_N_GO) ? TCF_COMPILE_N_GO : 0) |
(cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0);
}
static JSScript *
CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
JSPrincipals *principals, JSPrincipals *originPrincipals,
@ -4817,8 +4810,11 @@ CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
assertSameCompartment(cx, obj, principals);
AutoLastFrameCheck lfc(cx);
uint32_t tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_SCRIPT_GLOBAL;
return frontend::CompileScript(cx, obj, NULL, principals, originPrincipals, tcflags,
bool compileAndGo = cx->hasRunOption(JSOPTION_COMPILE_N_GO);
bool noScriptRval = cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL);
bool needScriptGlobal = true;
return frontend::CompileScript(cx, obj, NULL, principals, originPrincipals,
compileAndGo, noScriptRval, needScriptGlobal,
chars, length, filename, lineno, version);
}
@ -5012,10 +5008,12 @@ CompileUTF8FileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
size_t decodelen = len;
jschar *decodebuf = (jschar *)cx->malloc_(decodelen * sizeof(jschar));
if (JS_DecodeUTF8(cx, buf, len, decodebuf, &decodelen)) {
uint32_t tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_SCRIPT_GLOBAL;
bool compileAndGo = cx->hasRunOption(JSOPTION_COMPILE_N_GO);
bool noScriptRval = cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL);
bool needScriptGlobal = true;
script = frontend::CompileScript(cx, obj, NULL, principals, NULL,
tcflags, decodebuf, decodelen,
filename, 1, cx->findVersion());
compileAndGo, noScriptRval, needScriptGlobal,
decodebuf, decodelen, filename, 1, cx->findVersion());
} else {
script = NULL;
}
@ -5306,15 +5304,15 @@ EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj_,
RootedVarObject obj(cx, obj_);
uint32_t flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL;
if (!rval)
flags |= TCF_NO_SCRIPT_RVAL;
bool compileAndGo = true;
bool noScriptRval = !rval;
bool needScriptGlobal = true;
CHECK_REQUEST(cx);
AutoLastFrameCheck lfc(cx);
JSScript *script = frontend::CompileScript(cx, obj, NULL, principals, originPrincipals,
flags, chars, length, filename, lineno,
compileVersion);
compileAndGo, noScriptRval, needScriptGlobal,
chars, length, filename, lineno, compileVersion);
if (!script)
return false;

View File

@ -1055,10 +1055,14 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c
CurrentScriptFileLineOrigin(cx, &filename, &lineno, &originPrincipals,
evalType == DIRECT_EVAL ? CALLED_FROM_JSOP_EVAL
: NOT_CALLED_FROM_JSOP_EVAL);
uint32_t tcflags = TCF_COMPILE_N_GO;
bool compileAndGo = true;
bool noScriptRval = false;
bool needScriptGlobal = false;
JSScript *compiled = frontend::CompileScript(cx, scopeobj, caller,
principals, originPrincipals,
tcflags, chars, length, filename,
compileAndGo, noScriptRval, needScriptGlobal,
chars, length, filename,
lineno, cx->findVersion(), linearStr,
staticLevel);
if (!compiled)

View File

@ -1329,8 +1329,6 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
bce->regexpList.finish(script->regexps());
if (bce->constList.length() != 0)
bce->constList.finish(script->consts());
if (bce->sc->flags & TCF_NO_SCRIPT_RVAL)
script->noScriptRval = true;
if (bce->sc->flags & TCF_STRICT_MODE_CODE)
script->strictModeCode = true;
if (bce->sc->flags & TCF_COMPILE_N_GO) {
@ -1361,6 +1359,8 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
fun = NULL;
if (bce->sc->inFunction()) {
JS_ASSERT(!bce->noScriptRval);
JS_ASSERT(!bce->needScriptGlobal);
/*
* We initialize fun->script() to be the script constructed above
* so that the debugger has a valid fun->script().
@ -1389,8 +1389,10 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
* Initialize script->object, if necessary, so that the debugger has a
* valid holder object.
*/
if (bce->sc->flags & TCF_NEED_SCRIPT_GLOBAL)
if (bce->needScriptGlobal)
script->globalObject = GetCurrentGlobal(cx);
script->noScriptRval = bce->noScriptRval;
}
/* Tell the debugger about this compiled script. */

View File

@ -3399,12 +3399,14 @@ EvaluateInEnv(JSContext *cx, Handle<Env*> env, StackFrame *fp, const jschar *cha
* variable references made by this frame.
*/
JSPrincipals *prin = fp->scopeChain()->principals(cx);
bool compileAndGo = true;
bool noScriptRval = false;
bool needScriptGlobal = true;
JSScript *script = frontend::CompileScript(cx, env, fp, prin, prin,
TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL,
compileAndGo, noScriptRval, needScriptGlobal,
chars, length, filename, lineno,
cx->findVersion(), NULL,
UpvarCookie::UPVAR_LEVEL_LIMIT);
if (!script)
return false;