diff --git a/mozilla/js/src/jsapi.c b/mozilla/js/src/jsapi.c index fd2b2e41bd1..14a557f42d2 100644 --- a/mozilla/js/src/jsapi.c +++ b/mozilla/js/src/jsapi.c @@ -4318,51 +4318,6 @@ JS_DefineUCFunction(JSContext *cx, JSObject *obj, return js_DefineFunction(cx, obj, atom, call, nargs, attrs); } -static JSScript * -CompileTokenStream(JSContext *cx, JSObject *obj, JSTokenStream *ts, - void *tempMark, JSBool *eofp) -{ - JSBool eof; - JSArenaPool codePool, notePool; - JSParseContext pc; - JSCodeGenerator cg; - JSScript *script; - - eof = JS_FALSE; - JS_INIT_ARENA_POOL(&codePool, "code", 1024, sizeof(jsbytecode), - &cx->scriptStackQuota); - JS_INIT_ARENA_POOL(¬ePool, "note", 1024, sizeof(jssrcnote), - &cx->scriptStackQuota); - js_InitParseContext(cx, &pc); - JS_ASSERT(!ts->parseContext); - ts->parseContext = &pc; - if (!js_InitCodeGenerator(cx, &cg, &pc, &codePool, ¬ePool, - ts->filename, ts->lineno, - ts->principals)) { - script = NULL; - } else if (!js_CompileTokenStream(cx, obj, ts, &cg)) { - script = NULL; - eof = (ts->flags & TSF_EOF) != 0; - } else { - script = js_NewScriptFromCG(cx, &cg, NULL); - } - if (eofp) - *eofp = eof; - if (!js_CloseTokenStream(cx, ts)) { - if (script) - js_DestroyScript(cx, script); - script = NULL; - } - - js_FinishCodeGenerator(cx, &cg); - JS_ASSERT(ts->parseContext == &pc); - js_FinishParseContext(cx, &pc); - JS_FinishArenaPool(&codePool); - JS_FinishArenaPool(¬ePool); - JS_ARENA_RELEASE(&cx->tempPool, tempMark); - return script; -} - JS_PUBLIC_API(JSScript *) JS_CompileScript(JSContext *cx, JSObject *obj, const char *bytes, size_t length, @@ -4429,16 +4384,15 @@ JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, const jschar *chars, size_t length, const char *filename, uintN lineno) { - void *mark; - JSTokenStream *ts; + JSParseContext pc; JSScript *script; CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals); - if (!ts) + if (!js_InitParseContext(cx, &pc, chars, length, NULL, filename, lineno)) return NULL; - script = CompileTokenStream(cx, obj, ts, mark, NULL); + js_InitCompilePrincipals(cx, &pc, principals); + script = js_CompileScript(cx, obj, &pc); + js_FinishParseContext(cx, &pc); LAST_FRAME_CHECKS(cx, script); return script; } @@ -4450,8 +4404,6 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, jschar *chars; JSBool result; JSExceptionState *exnState; - void *tempMark; - JSTokenStream *ts; JSParseContext pc; JSErrorReporter older; @@ -4466,15 +4418,10 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, */ result = JS_TRUE; exnState = JS_SaveExceptionState(cx); - tempMark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, chars, length, NULL, 0, NULL); - if (ts) { + if (js_InitParseContext(cx, &pc, chars, length, NULL, NULL, 1)) { older = JS_SetErrorReporter(cx, NULL); - js_InitParseContext(cx, &pc); - JS_ASSERT(!ts->parseContext); - ts->parseContext = &pc; - if (!js_ParseTokenStream(cx, obj, ts) && - (ts->flags & TSF_UNEXPECTED_EOF)) { + if (!js_ParseScript(cx, obj, &pc) && + (pc.tokenStream.flags & TSF_UNEXPECTED_EOF)) { /* * We ran into an error. If it was because we ran out of source, * we return false, so our caller will know to try to collect more @@ -4482,14 +4429,9 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, */ result = JS_FALSE; } - - JS_ASSERT(ts->parseContext == &pc); - js_FinishParseContext(cx, &pc); JS_SetErrorReporter(cx, older); - js_CloseTokenStream(cx, ts); + js_FinishParseContext(cx, &pc); } - - JS_ARENA_RELEASE(&cx->tempPool, tempMark); JS_free(cx, chars); JS_RestoreExceptionState(cx, exnState); return result; @@ -4498,16 +4440,30 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, JS_PUBLIC_API(JSScript *) JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename) { - void *mark; - JSTokenStream *ts; + FILE *fp; + JSParseContext pc; JSScript *script; CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewFileTokenStream(cx, filename, stdin); - if (!ts) - return NULL; - script = CompileTokenStream(cx, obj, ts, mark, NULL); + if (!filename || strcmp(filename, "-") == 0) { + fp = stdin; + } else { + fp = fopen(filename, "r"); + if (!fp) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN, + filename, "No such file or directory"); + return NULL; + } + } + + if (!js_InitParseContext(cx, &pc, NULL, 0, fp, filename, 1)) { + script = NULL; + } else { + script = js_CompileScript(cx, obj, &pc); + js_FinishParseContext(cx, &pc); + } + if (fp != stdin) + fclose(fp); LAST_FRAME_CHECKS(cx, script); return script; } @@ -4524,22 +4480,15 @@ JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj, const char *filename, FILE *file, JSPrincipals *principals) { - void *mark; - JSTokenStream *ts; + JSParseContext pc; JSScript *script; CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewFileTokenStream(cx, NULL, file); - if (!ts) + if (!js_InitParseContext(cx, &pc, NULL, 0, file, filename, 1)) return NULL; - ts->filename = filename; - /* XXXshaver js_NewFileTokenStream should do this, because it drops */ - if (principals) { - ts->principals = principals; - JSPRINCIPALS_HOLD(cx, ts->principals); - } - script = CompileTokenStream(cx, obj, ts, mark, NULL); + js_InitCompilePrincipals(cx, &pc, principals); + script = js_CompileScript(cx, obj, &pc); + js_FinishParseContext(cx, &pc); LAST_FRAME_CHECKS(cx, script); return script; } @@ -4634,19 +4583,13 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, const jschar *chars, size_t length, const char *filename, uintN lineno) { - void *mark; - JSTokenStream *ts; JSFunction *fun; JSAtom *funAtom, *argAtom; uintN i; + JSParseContext pc; + JSBool ok; CHECK_REQUEST(cx); - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, chars, length, filename, lineno, principals); - if (!ts) { - fun = NULL; - goto out; - } if (!name) { funAtom = NULL; } else { @@ -4662,36 +4605,41 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj, if (nargs) { for (i = 0; i < nargs; i++) { argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0); - if (!argAtom) - break; + if (!argAtom) { + fun = NULL; + goto out; + } if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(argAtom), js_GetArgument, js_SetArgument, SPROP_INVALID_SLOT, JSPROP_PERMANENT | JSPROP_SHARED, SPROP_HAS_SHORTID, i)) { - break; + fun = NULL; + goto out; } } - if (i < nargs) { - fun = NULL; - goto out; - } } - if (!js_CompileFunctionBody(cx, ts, fun)) { + + ok = js_InitParseContext(cx, &pc, chars, length, NULL, filename, lineno); + if (ok) { + js_InitCompilePrincipals(cx, &pc, principals); + ok = js_CompileFunctionBody(cx, &pc, fun); + js_FinishParseContext(cx, &pc); + } + if (!ok) { fun = NULL; goto out; } - if (obj && funAtom) { - if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom), - OBJECT_TO_JSVAL(fun->object), - NULL, NULL, JSPROP_ENUMERATE, NULL)) { - return NULL; - } + + if (obj && + funAtom && + !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom), + OBJECT_TO_JSVAL(fun->object), + NULL, NULL, JSPROP_ENUMERATE, NULL)) { + fun = NULL; } -out: - if (ts) - js_CloseTokenStream(cx, ts); - JS_ARENA_RELEASE(&cx->tempPool, mark); + + out: LAST_FRAME_CHECKS(cx, fun); return fun; } diff --git a/mozilla/js/src/jsemit.c b/mozilla/js/src/jsemit.c index 098cd9145d8..0f6fd66c8fd 100644 --- a/mozilla/js/src/jsemit.c +++ b/mozilla/js/src/jsemit.c @@ -79,11 +79,10 @@ static JSBool NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind, uintN stackDepth, size_t start, size_t end); -JS_FRIEND_API(JSBool) +JS_FRIEND_API(void) js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc, JSArenaPool *codePool, JSArenaPool *notePool, - const char *filename, uintN lineno, - JSPrincipals *principals) + uintN lineno) { memset(cg, 0, sizeof *cg); TREE_CONTEXT_INIT(&cg->treeContext, pc); @@ -93,13 +92,10 @@ js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc, cg->codeMark = JS_ARENA_MARK(codePool); cg->noteMark = JS_ARENA_MARK(notePool); cg->current = &cg->main; - cg->filename = filename; cg->firstLine = cg->prolog.currentLine = cg->main.currentLine = lineno; - cg->principals = principals; ATOM_LIST_INIT(&cg->atomList); cg->prolog.noteMask = cg->main.noteMask = SRCNOTE_CHUNK - 1; ATOM_LIST_INIT(&cg->constList); - return JS_TRUE; } JS_FRIEND_API(void) @@ -180,11 +176,14 @@ UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target) JS_ASSERT(cg->stackDepth >= 0); if (cg->stackDepth < 0) { char numBuf[12]; + JSTokenStream *ts; + JS_snprintf(numBuf, sizeof numBuf, "%d", target); + ts = &cg->treeContext.parseContext->tokenStream; JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, js_GetErrorMessage, NULL, JSMSG_STACK_UNDERFLOW, - cg->filename ? cg->filename : "stdin", + ts->filename ? ts->filename : "stdin", numBuf); } cg->stackDepth += cs->ndefs; @@ -4021,12 +4020,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ReportOutOfMemory(cx); return JS_FALSE; } - if (!js_InitCodeGenerator(cx, cg2, cg->treeContext.parseContext, - cg->codePool, cg->notePool, - cg->filename, pn->pn_pos.begin.lineno, - cg->principals)) { - return JS_FALSE; - } + js_InitCodeGenerator(cx, cg2, cg->treeContext.parseContext, + cg->codePool, cg->notePool, + pn->pn_pos.begin.lineno); cg2->treeContext.flags = (uint16) (pn->pn_flags | TCF_IN_FUNCTION); cg2->parent = cg; fun = (JSFunction *) OBJ_GET_PRIVATE(cx, pn->pn_funpob->object); @@ -5275,8 +5271,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) cg->treeContext.topStmt->type != STMT_LABEL || cg->treeContext.topStmt->update < CG_OFFSET(cg))) { CG_CURRENT_LINE(cg) = pn2->pn_pos.begin.lineno; - if (!js_ReportCompileErrorNumber(cx, cg, - JSREPORT_CG | + if (!js_ReportCompileErrorNumber(cx, pn2, + JSREPORT_PN | JSREPORT_WARNING | JSREPORT_STRICT, JSMSG_USELESS_EXPR)) { @@ -6298,22 +6294,21 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) ok = EmitNumberOp(cx, pn->pn_dval, cg); break; - case TOK_OBJECT: - if (pn->pn_op == JSOP_REGEXP) { - /* - * cx->fp->varobj cannot be a Call object here, because that - * implies we are compiling eval code, in which case - * (cx->fp->flags & JSFRAME_EVAL) is true, and js_GetToken will - * have already selected JSOP_OBJECT instead of JSOP_REGEXP, to - * avoid all this RegExp object cloning business. - */ - JS_ASSERT(!(cx->fp->flags & (JSFRAME_EVAL | JSFRAME_COMPILE_N_GO))); - ok = EmitIndexOp(cx, PN_OP(pn), + case TOK_REGEXP: + /* + * If the regexp's script is one-shot, we can avoid the extra + * fork-on-exec costs of JSOP_REGEXP by selecting JSOP_OBJECT. + * Otherwise, to avoid incorrect proto, parent, and lastIndex + * sharing among threads and sequentially across re-execution, + * select JSOP_REGEXP. + */ + JS_ASSERT(pn->pn_op == JSOP_REGEXP); + if (cx->fp->flags & (JSFRAME_EVAL | JSFRAME_COMPILE_N_GO)) { + ok = EmitObjectOp(cx, pn->pn_pob, JSOP_OBJECT, cg); + } else { + ok = EmitIndexOp(cx, JSOP_REGEXP, IndexParsedObject(pn->pn_pob, &cg->regexpList), cg); - } else { - JS_ASSERT(pn->pn_op == JSOP_OBJECT); - ok = EmitObjectOp(cx, pn->pn_pob, PN_OP(pn), cg); } break; diff --git a/mozilla/js/src/jsemit.h b/mozilla/js/src/jsemit.h index 27ee5da8f92..9efc3df1efb 100644 --- a/mozilla/js/src/jsemit.h +++ b/mozilla/js/src/jsemit.h @@ -295,9 +295,7 @@ struct JSCodeGenerator { uintN currentLine; /* line number for tree-based srcnote gen */ } prolog, main, *current; - const char *filename; /* null or weak link to source filename */ uintN firstLine; /* first line, for js_NewScriptFromCG */ - JSPrincipals *principals; /* principals for constant folding eval */ JSAtomList atomList; /* literals indexed for mapping */ intN stackDepth; /* current stack depth in script frame */ @@ -351,14 +349,11 @@ struct JSCodeGenerator { /* * Initialize cg to allocate bytecode space from codePool, source note space * from notePool, and all other arena-allocated temporaries from cx->tempPool. - * Return true on success. Report an error and return false if the initial - * code segment can't be allocated. */ -extern JS_FRIEND_API(JSBool) +extern JS_FRIEND_API(void) js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc, JSArenaPool *codePool, JSArenaPool *notePool, - const char *filename, uintN lineno, - JSPrincipals *principals); + uintN lineno); /* * Release cg->codePool, cg->notePool, and cx->tempPool to marks set by diff --git a/mozilla/js/src/jsfun.c b/mozilla/js/src/jsfun.c index 8f02424e9d2..227f8395a02 100644 --- a/mozilla/js/src/jsfun.c +++ b/mozilla/js/src/jsfun.c @@ -1805,10 +1805,10 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) JSProperty *prop; JSScopeProperty *sprop; JSString *str, *arg; - void *mark; - JSTokenStream *ts; + JSParseContext pc; JSPrincipals *principals; jschar *collected_args, *cp; + void *mark; size_t arg_length, args_length, old_args_length; JSTokenType tt; JSBool ok; @@ -1869,6 +1869,8 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) n = argc ? argc - 1 : 0; if (n > 0) { + enum { OK, BAD, BAD_FORMAL } state; + /* * Collect the function-argument arguments into one string, separated * by commas, then make a tokenstream from that string, and scan it to @@ -1879,6 +1881,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * compiler, but doing it this way is less of a delta from the old * code. See ECMA 15.3.2.1. */ + state = BAD_FORMAL; args_length = 0; for (i = 0; i < n; i++) { /* Collect the lengths for all the function-argument arguments. */ @@ -1935,19 +1938,15 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) *cp++ = (i + 1 < n) ? ',' : 0; } - /* - * Make a tokenstream (allocated from cx->tempPool) that reads from - * the given string. - */ - ts = js_NewTokenStream(cx, collected_args, args_length, filename, - lineno, principals); - if (!ts) { + /* Initialize a tokenstream that reads from the given string. */ + if (!js_InitTokenStream(cx, &pc.tokenStream, collected_args, + args_length, NULL, filename, lineno)) { JS_ARENA_RELEASE(&cx->tempPool, mark); return JS_FALSE; } /* The argument string may be empty or contain no tokens. */ - tt = js_GetToken(cx, ts); + tt = js_GetToken(cx, &pc.tokenStream); if (tt != TOK_EOF) { for (;;) { /* @@ -1955,16 +1954,16 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * TOK_ERROR, which was already reported. */ if (tt != TOK_NAME) - goto bad_formal; + goto after_args; /* * Get the atom corresponding to the name from the tokenstream; * we're assured at this point that it's a valid identifier. */ - atom = CURRENT_TOKEN(ts).t_atom; + atom = CURRENT_TOKEN(&pc.tokenStream).t_atom; if (!js_LookupHiddenProperty(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop)) { - goto bad_formal; + goto after_args; } sprop = (JSScopeProperty *) prop; dupflag = 0; @@ -1981,7 +1980,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) */ JS_ASSERT(sprop->getter == js_GetArgument); ok = name && - js_ReportCompileErrorNumber(cx, ts, + js_ReportCompileErrorNumber(cx, &pc.tokenStream, JSREPORT_TS | JSREPORT_WARNING | JSREPORT_STRICT, @@ -1992,7 +1991,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) } OBJ_DROP_PROPERTY(cx, obj2, prop); if (!ok) - goto bad_formal; + goto after_args; sprop = NULL; } if (!js_AddHiddenProperty(cx, fun->object, ATOM_TO_JSID(atom), @@ -2001,12 +2000,13 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) JSPROP_PERMANENT | JSPROP_SHARED, dupflag | SPROP_HAS_SHORTID, fun->nargs)) { - goto bad_formal; + goto after_args; } if (fun->nargs == JS_BITMASK(16)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_MANY_FUN_ARGS); - goto bad; + state = BAD; + goto after_args; } fun->nargs++; @@ -2014,19 +2014,28 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * Get the next token. Stop on end of stream. Otherwise * insist on a comma, get another name, and iterate. */ - tt = js_GetToken(cx, ts); + tt = js_GetToken(cx, &pc.tokenStream); if (tt == TOK_EOF) break; if (tt != TOK_COMMA) - goto bad_formal; - tt = js_GetToken(cx, ts); + goto after_args; + tt = js_GetToken(cx, &pc.tokenStream); } } - /* Clean up. */ - ok = js_CloseTokenStream(cx, ts); + state = OK; + after_args: + if (state == BAD_FORMAL && !(pc.tokenStream.flags & TSF_ERROR)) { + /* + * Report "malformed formal parameter" iff no illegal char or + * similar scanner error was already reported. + */ + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_BAD_FORMAL); + } + js_CloseTokenStream(cx, &pc.tokenStream); JS_ARENA_RELEASE(&cx->tempPool, mark); - if (!ok) + if (state != OK) return JS_FALSE; } @@ -2039,35 +2048,14 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) str = cx->runtime->emptyString; } - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewTokenStream(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str), - filename, lineno, principals); - if (!ts) { - ok = JS_FALSE; - } else { - /* Note: We must *always* close ts. */ - ok = js_CompileFunctionBody(cx, ts, fun); - ok &= js_CloseTokenStream(cx, ts); + ok = js_InitParseContext(cx, &pc, JSSTRING_CHARS(str), JSSTRING_LENGTH(str), + NULL, filename, lineno); + if (ok) { + js_InitCompilePrincipals(cx, &pc, principals); + ok = js_CompileFunctionBody(cx, &pc, fun); + js_FinishParseContext(cx, &pc); } - JS_ARENA_RELEASE(&cx->tempPool, mark); return ok; - -bad_formal: - /* - * Report "malformed formal parameter" iff no illegal char or similar - * scanner error was already reported. - */ - if (!(ts->flags & TSF_ERROR)) - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_FORMAL); - -bad: - /* - * Clean up the arguments string and tokenstream if we failed to parse - * the arguments. - */ - (void)js_CloseTokenStream(cx, ts); - JS_ARENA_RELEASE(&cx->tempPool, mark); - return JS_FALSE; } JSObject * diff --git a/mozilla/js/src/jsparse.c b/mozilla/js/src/jsparse.c index 5dafc0ce8a3..322080a439f 100644 --- a/mozilla/js/src/jsparse.c +++ b/mozilla/js/src/jsparse.c @@ -158,23 +158,46 @@ static uint32 maxparsenodes = 0; static uint32 recyclednodes = 0; #endif -void -js_InitParseContext(JSContext *cx, JSParseContext *pc) +JS_FRIEND_API(JSBool) +js_InitParseContext(JSContext *cx, JSParseContext *pc, + const jschar *base, size_t length, + FILE *fp, const char *filename, uintN lineno) { + pc->tempPoolMark = JS_ARENA_MARK(&cx->tempPool); + if (!js_InitTokenStream(cx, TS(pc), base, length, fp, filename, lineno)) { + JS_ARENA_RELEASE(&cx->tempPool, pc->tempPoolMark); + return JS_FALSE; + } + pc->principals = NULL; pc->nodeList = NULL; pc->traceListHead = NULL; /* Root atoms and objects allocated for the parsed tree. */ JS_KEEP_ATOMS(cx->runtime); JS_PUSH_TEMP_ROOT_PARSE_CONTEXT(cx, pc, &pc->tempRoot); + return JS_TRUE; } -void +JS_FRIEND_API(void) js_FinishParseContext(JSContext *cx, JSParseContext *pc) { + if (pc->principals) + JSPRINCIPALS_DROP(cx, pc->principals); JS_ASSERT(pc->tempRoot.u.parseContext == pc); JS_POP_TEMP_ROOT(cx, &pc->tempRoot); JS_UNKEEP_ATOMS(cx->runtime); + js_CloseTokenStream(cx, TS(pc)); + JS_ARENA_RELEASE(&cx->tempPool, pc->tempPoolMark); +} + +void +js_InitCompilePrincipals(JSContext *cx, JSParseContext *pc, + JSPrincipals *principals) +{ + JS_ASSERT(!pc->principals); + if (principals) + JSPRINCIPALS_HOLD(cx, principals); + pc->principals = principals; } JSParsedObjectBox * @@ -496,7 +519,7 @@ MaybeSetupFrame(JSContext *cx, JSObject *chain, JSStackFrame *oldfp, * Parse a top-level JS script. */ JS_FRIEND_API(JSParseNode *) -js_ParseTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts) +js_ParseScript(JSContext *cx, JSObject *chain, JSParseContext *pc) { JSStackFrame *fp, frame; JSTreeContext tc; @@ -518,11 +541,12 @@ js_ParseTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts) * an object lock before it finishes generating bytecode into a script * protected from the GC by a root or a stack frame reference. */ - TREE_CONTEXT_INIT(&tc, ts->parseContext); - pn = Statements(cx, ts, &tc); + TREE_CONTEXT_INIT(&tc, pc); + pn = Statements(cx, TS(pc), &tc); if (pn) { - if (!js_MatchToken(cx, ts, TOK_EOF)) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, + if (!js_MatchToken(cx, TS(pc), TOK_EOF)) { + js_ReportCompileErrorNumber(cx, TS(pc), + JSREPORT_TS | JSREPORT_ERROR, JSMSG_SYNTAX_ERROR); pn = NULL; } else { @@ -540,14 +564,15 @@ js_ParseTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts) /* * Compile a top-level script. */ -JS_FRIEND_API(JSBool) -js_CompileTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, - JSCodeGenerator *cg) +JS_FRIEND_API(JSScript *) +js_CompileScript(JSContext *cx, JSObject *chain, JSParseContext *pc) { JSStackFrame *fp, frame; uint32 flags; + JSArenaPool codePool, notePool; + JSCodeGenerator cg; JSParseNode *pn; - JSBool ok; + JSScript *script; #ifdef METER_PARSENODES void *sbrk(ptrdiff_t), *before = sbrk(0); #endif @@ -565,40 +590,48 @@ js_CompileTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, ? JSFRAME_COMPILING | JSFRAME_COMPILE_N_GO : JSFRAME_COMPILING); - /* Prevent GC activation while compiling. */ - JS_KEEP_ATOMS(cx->runtime); + JS_INIT_ARENA_POOL(&codePool, "code", 1024, sizeof(jsbytecode), + &cx->scriptStackQuota); + JS_INIT_ARENA_POOL(¬ePool, "note", 1024, sizeof(jssrcnote), + &cx->scriptStackQuota); + js_InitCodeGenerator(cx, &cg, pc, &codePool, ¬ePool, TS(pc)->lineno); - pn = Statements(cx, ts, &cg->treeContext); + /* From this point the control must flow via the label out. */ + pn = Statements(cx, TS(pc), &cg.treeContext); if (!pn) { - ok = JS_FALSE; - } else if (!js_MatchToken(cx, ts, TOK_EOF)) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, + script = NULL; + goto out; + } + if (!js_MatchToken(cx, TS(pc), TOK_EOF)) { + js_ReportCompileErrorNumber(cx, TS(pc), JSREPORT_TS | JSREPORT_ERROR, JSMSG_SYNTAX_ERROR); - ok = JS_FALSE; - } else { + script = NULL; + goto out; + } #ifdef METER_PARSENODES - printf("Parser growth: %d (%u nodes, %u max, %u unrecycled)\n", - (char *)sbrk(0) - (char *)before, - parsenodes, - maxparsenodes, - parsenodes - recyclednodes); - before = sbrk(0); + printf("Parser growth: %d (%u nodes, %u max, %u unrecycled)\n", + (char *)sbrk(0) - (char *)before, + parsenodes, + maxparsenodes, + parsenodes - recyclednodes); + before = sbrk(0); #endif - /* - * No need to emit bytecode here -- Statements already has, for each - * statement in turn. Search for TCF_COMPILING in Statements, below. - * That flag is set for every tc == &cg->treeContext, and it implies - * that the tc can be downcast to a cg and used to emit code during - * parsing, rather than at the end of the parse phase. - * - * Nowadays the threaded interpreter needs a stop instruction, so we - * do have to emit that here. - */ - JS_ASSERT(cg->treeContext.flags & TCF_COMPILING); - ok = js_Emit1(cx, cg, JSOP_STOP) >= 0; + /* + * No need to emit bytecode here -- Statements already has, for each + * statement in turn. Search for TCF_COMPILING in Statements, below. + * That flag is set for every tc == &cg->treeContext, and it implies + * that the tc can be downcast to a cg and used to emit code during + * parsing, rather than at the end of the parse phase. + * + * Nowadays the threaded interpreter needs a stop instruction, so we + * do have to emit that here. + */ + JS_ASSERT(cg.treeContext.flags & TCF_COMPILING); + if (js_Emit1(cx, &cg, JSOP_STOP) < 0) { + script = NULL; + goto out; } - #ifdef METER_PARSENODES printf("Code-gen growth: %d (%u bytecodes, %u srcnotes)\n", (char *)sbrk(0) - (char *)before, CG_OFFSET(cg), cg->noteCount); @@ -606,10 +639,16 @@ js_CompileTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, #ifdef JS_ARENAMETER JS_DumpArenaStats(stdout); #endif - JS_UNKEEP_ATOMS(cx->runtime); + script = js_NewScriptFromCG(cx, &cg, NULL); + + out: + js_FinishCodeGenerator(cx, &cg); + JS_FinishArenaPool(&codePool); + JS_FinishArenaPool(¬ePool); + cx->fp->flags = flags; cx->fp = fp; - return ok; + return script; } /* @@ -870,10 +909,9 @@ FunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun, * handler attribute in an HTML tag. */ JSBool -js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun) +js_CompileFunctionBody(JSContext *cx, JSParseContext *pc, JSFunction *fun) { JSArenaPool codePool, notePool; - JSParseContext pc; JSCodeGenerator funcg; JSStackFrame *fp, frame; JSObject *funobj; @@ -883,14 +921,7 @@ js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun) &cx->scriptStackQuota); JS_INIT_ARENA_POOL(¬ePool, "note", 1024, sizeof(jssrcnote), &cx->scriptStackQuota); - js_InitParseContext(cx, &pc); - JS_ASSERT(!ts->parseContext); - ts->parseContext = &pc; - if (!js_InitCodeGenerator(cx, &funcg, &pc, &codePool, ¬ePool, - ts->filename, ts->lineno, - ts->principals)) { - return JS_FALSE; - } + js_InitCodeGenerator(cx, &funcg, pc, &codePool, ¬ePool, TS(pc)->lineno); /* Push a JSStackFrame for use by FunctionBody. */ fp = cx->fp; @@ -918,11 +949,12 @@ js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun) * Therefore we must fold constants, allocate try notes, and generate code * for this function, including a stop opcode at the end. */ - CURRENT_TOKEN(ts).type = TOK_LC; - pn = FunctionBody(cx, ts, fun, &funcg.treeContext); + CURRENT_TOKEN(TS(pc)).type = TOK_LC; + pn = FunctionBody(cx, TS(pc), fun, &funcg.treeContext); if (pn) { - if (!js_MatchToken(cx, ts, TOK_EOF)) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, + if (!js_MatchToken(cx, TS(pc), TOK_EOF)) { + js_ReportCompileErrorNumber(cx, TS(pc), + JSREPORT_TS | JSREPORT_ERROR, JSMSG_SYNTAX_ERROR); pn = NULL; } else { @@ -934,7 +966,6 @@ js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun) /* Restore saved state and release code generation arenas. */ cx->fp = fp; js_FinishCodeGenerator(cx, &funcg); - js_FinishParseContext(cx, &pc); JS_FinishArenaPool(&codePool); JS_FinishArenaPool(¬ePool); return pn != NULL; @@ -5452,8 +5483,8 @@ XMLElementOrListRoot(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, } JS_FRIEND_API(JSParseNode *) -js_ParseXMLTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, - JSBool allowList) +js_ParseXMLText(JSContext *cx, JSObject *chain, JSParseContext *pc, + JSBool allowList) { JSStackFrame *fp, frame; JSParseNode *pn; @@ -5467,22 +5498,22 @@ js_ParseXMLTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, */ fp = cx->fp; MaybeSetupFrame(cx, chain, fp, &frame); - TREE_CONTEXT_INIT(&tc, ts->parseContext); + TREE_CONTEXT_INIT(&tc, pc); /* Set XML-only mode to turn off special treatment of {expr} in XML. */ - ts->flags |= TSF_OPERAND | TSF_XMLONLYMODE; - tt = js_GetToken(cx, ts); - ts->flags &= ~TSF_OPERAND; + TS(pc)->flags |= TSF_OPERAND | TSF_XMLONLYMODE; + tt = js_GetToken(cx, TS(pc)); + TS(pc)->flags &= ~TSF_OPERAND; if (tt != TOK_XMLSTAGO) { - js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, + js_ReportCompileErrorNumber(cx, TS(pc), JSREPORT_TS | JSREPORT_ERROR, JSMSG_BAD_XML_MARKUP); pn = NULL; } else { - pn = XMLElementOrListRoot(cx, ts, &tc, allowList); + pn = XMLElementOrListRoot(cx, TS(pc), &tc, allowList); } - ts->flags &= ~TSF_XMLONLYMODE; + TS(pc)->flags &= ~TSF_XMLONLYMODE; TREE_CONTEXT_FINISH(&tc); cx->fp = fp; return pn; @@ -5907,14 +5938,10 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, case TOK_XMLPI: #endif case TOK_NAME: - case TOK_OBJECT: pn = NewParseNode(cx, ts, PN_NULLARY, tc); if (!pn) return NULL; - if (tt == TOK_OBJECT) - pn->pn_pob = CURRENT_TOKEN(ts).t_pob; - else - pn->pn_atom = CURRENT_TOKEN(ts).t_atom; + pn->pn_atom = CURRENT_TOKEN(ts).t_atom; #if JS_HAS_XML_SUPPORT if (tt == TOK_XMLPI) pn->pn_atom2 = CURRENT_TOKEN(ts).t_atom2; @@ -5979,6 +6006,31 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, } break; + case TOK_REGEXP: + { + JSObject *obj; + + pn = NewParseNode(cx, ts, PN_NULLARY, tc); + if (!pn) + return NULL; + + /* Token stream ensures that tokenbuf is NUL-terminated. */ + JS_ASSERT(*ts->tokenbuf.ptr == (jschar) 0); + obj = js_NewRegExpObject(cx, ts, + ts->tokenbuf.base, + ts->tokenbuf.ptr - ts->tokenbuf.base, + CURRENT_TOKEN(ts).t_reflags); + if (!obj) + return NULL; + + pn->pn_pob = js_NewParsedObjectBox(cx, tc->parseContext, obj); + if (!pn->pn_pob) + return NULL; + + pn->pn_op = JSOP_REGEXP; + break; + } + case TOK_NUMBER: pn = NewParseNode(cx, ts, PN_NULLARY, tc); if (!pn) diff --git a/mozilla/js/src/jsparse.h b/mozilla/js/src/jsparse.h index 212abcf129b..c8334db4155 100644 --- a/mozilla/js/src/jsparse.h +++ b/mozilla/js/src/jsparse.h @@ -185,7 +185,7 @@ JS_BEGIN_EXTERN_C * TOK_NAME, name pn_atom: name, string, or object atom * TOK_STRING, pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or * JSOP_REGEXP - * TOK_OBJECT If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR + * TOK_REGEXP If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR * with pn_slot >= 0 and pn_attrs telling const-ness * TOK_NUMBER dval pn_dval: double value of numeric literal * TOK_PRIMARY nullary pn_op: JSOp bytecode @@ -425,8 +425,10 @@ struct JSParsedObjectBox { JSObject *object; }; - struct JSParseContext { + JSTokenStream tokenStream; + void *tempPoolMark; /* initial JSContext.tempPool mark */ + JSPrincipals *principals; /* principals associated with source */ JSParseNode *nodeList; /* list of recyclable parse-node structs */ JSParsedObjectBox *traceListHead; /* list of parsed object for GC @@ -442,33 +444,51 @@ struct JSParseContext { #endif }; +/* + * Convenience macro to access JSParseContext.tokenStream as a pointer. + */ +#define TS(pc) (&(pc)->tokenStream) + /* * Parse a top-level JS script. */ extern JS_FRIEND_API(JSParseNode *) -js_ParseTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts); +js_ParseScript(JSContext *cx, JSObject *chain, JSParseContext *pc); -extern JS_FRIEND_API(JSBool) -js_CompileTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, - JSCodeGenerator *cg); +extern JS_FRIEND_API(JSScript *) +js_CompileScript(JSContext *cx, JSObject *chain, JSParseContext *pc); extern JSBool -js_CompileFunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun); +js_CompileFunctionBody(JSContext *cx, JSParseContext *pc, JSFunction *fun); extern JSBool js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc); #if JS_HAS_XML_SUPPORT JS_FRIEND_API(JSParseNode *) -js_ParseXMLTokenStream(JSContext *cx, JSObject *chain, JSTokenStream *ts, - JSBool allowList); +js_ParseXMLText(JSContext *cx, JSObject *chain, JSParseContext *pc, + JSBool allowList); #endif -extern void -js_InitParseContext(JSContext *cx, JSParseContext *pc); +/* + * Initialize a parse context. All parameters after pc are passed to + * js_InitTokenStream. + * + * The parse context owns the arena pool "tops-of-stack" space above the + * current JSContext.tempPool mark. This means you cannot allocate from + * tempPool and save the pointer beyond the next js_FinishParseContext. + */ +extern JS_FRIEND_API(JSBool) +js_InitParseContext(JSContext *cx, JSParseContext *pc, + const jschar *base, size_t length, FILE *fp, + const char *filename, uintN lineno); + +extern JS_FRIEND_API(void) +js_FinishParseContext(JSContext *cx, JSParseContext *pc); extern void -js_FinishParseContext(JSContext *cx, JSParseContext *pc); +js_InitCompilePrincipals(JSContext *cx, JSParseContext *pc, + JSPrincipals *principals); /* * Allocate a new parseed object node from cx->tempPool. diff --git a/mozilla/js/src/jsscan.c b/mozilla/js/src/jsscan.c index 8bc756273bb..133c01efd45 100644 --- a/mozilla/js/src/jsscan.c +++ b/mozilla/js/src/jsscan.c @@ -172,24 +172,6 @@ js_IsIdentifier(JSString *str) return JS_TRUE; } -JSTokenStream * -js_NewTokenStream(JSContext *cx, const jschar *base, size_t length, - const char *filename, uintN lineno, - JSPrincipals *principals) -{ - JSTokenStream *ts; - - ts = js_NewBufferTokenStream(cx, base, length); - if (!ts) - return NULL; - ts->filename = filename; - ts->lineno = lineno; - if (principals) - JSPRINCIPALS_HOLD(cx, principals); - ts->principals = principals; - return ts; -} - #define TBMIN 64 static JSBool @@ -230,69 +212,50 @@ GrowTokenBuf(JSStringBuffer *sb, size_t newlength) return JS_TRUE; } -JS_FRIEND_API(JSTokenStream *) -js_NewBufferTokenStream(JSContext *cx, const jschar *base, size_t length) +JS_FRIEND_API(JSBool) +js_InitTokenStream(JSContext *cx, JSTokenStream *ts, + const jschar *base, size_t length, + FILE *fp, const char *filename, uintN lineno) { + jschar *buf; size_t nb; - JSTokenStream *ts; - nb = sizeof(JSTokenStream) + JS_LINE_LIMIT * sizeof(jschar); - JS_ARENA_ALLOCATE_CAST(ts, JSTokenStream *, &cx->tempPool, nb); + JS_ASSERT_IF(fp, !base); + JS_ASSERT_IF(!base, length == 0); + nb = fp + ? 2 * JS_LINE_LIMIT * sizeof(jschar) + : JS_LINE_LIMIT * sizeof(jschar); + JS_ARENA_ALLOCATE_CAST(buf, jschar *, &cx->tempPool, nb); if (!ts) { JS_ReportOutOfMemory(cx); - return NULL; + return JS_FALSE; + } + memset(buf, 0, nb); + memset(ts, 0, sizeof(*ts)); + ts->filename = filename; + ts->lineno = lineno; + ts->linebuf.base = ts->linebuf.limit = ts->linebuf.ptr = buf; + if (fp) { + ts->file = fp; + ts->userbuf.base = buf + JS_LINE_LIMIT; + ts->userbuf.ptr = ts->userbuf.limit = ts->userbuf.base + JS_LINE_LIMIT; + } else { + ts->userbuf.base = (jschar *)base; + ts->userbuf.limit = (jschar *)base + length; + ts->userbuf.ptr = (jschar *)base; } - memset(ts, 0, nb); - ts->lineno = 1; - ts->linebuf.base = ts->linebuf.limit = ts->linebuf.ptr = (jschar *)(ts + 1); - ts->userbuf.base = (jschar *)base; - ts->userbuf.limit = (jschar *)base + length; - ts->userbuf.ptr = (jschar *)base; ts->tokenbuf.grow = GrowTokenBuf; ts->tokenbuf.data = cx; ts->listener = cx->debugHooks->sourceHandler; ts->listenerData = cx->debugHooks->sourceHandlerData; - return ts; + return JS_TRUE; } -JS_FRIEND_API(JSTokenStream *) -js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp) -{ - jschar *base; - JSTokenStream *ts; - FILE *file; - - JS_ARENA_ALLOCATE_CAST(base, jschar *, &cx->tempPool, - JS_LINE_LIMIT * sizeof(jschar)); - if (!base) - return NULL; - ts = js_NewBufferTokenStream(cx, base, JS_LINE_LIMIT); - if (!ts) - return NULL; - if (!filename || strcmp(filename, "-") == 0) { - file = defaultfp; - } else { - file = fopen(filename, "r"); - if (!file) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN, - filename, "No such file or directory"); - return NULL; - } - } - ts->userbuf.ptr = ts->userbuf.limit; - ts->file = file; - ts->filename = filename; - return ts; -} - -JS_FRIEND_API(JSBool) +JS_FRIEND_API(void) js_CloseTokenStream(JSContext *cx, JSTokenStream *ts) { if (ts->flags & TSF_OWNFILENAME) JS_free(cx, (void *) ts->filename); - if (ts->principals) - JSPRINCIPALS_DROP(cx, ts->principals); - return !ts->file || fclose(ts->file) == 0; } JS_FRIEND_API(int) @@ -554,7 +517,6 @@ ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags, jschar *linechars = NULL; char *linebytes = NULL; JSTokenStream *ts = NULL; - JSCodeGenerator *cg = NULL; JSParseNode *pn = NULL; JSErrorReporter onError; JSTokenPos *tp; @@ -574,27 +536,20 @@ ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags, return JS_FALSE; } - switch (flags & JSREPORT_HANDLE) { - case JSREPORT_TS: + if ((flags & JSREPORT_HANDLE) == JSREPORT_TS) { ts = (JSTokenStream *) handle; - break; - case JSREPORT_CG: - cg = (JSCodeGenerator *) handle; - break; - case JSREPORT_PN: + } else { + JS_ASSERT((flags & JSREPORT_HANDLE) == JSREPORT_PN); pn = (JSParseNode *) handle; ts = pn->pn_ts; - break; } - JS_ASSERT(!ts || ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT); - /* - * We are typically called with non-null ts and null cg from jsparse.c. - * We can be called with null ts from the regexp compilation functions. - * The code generator (jsemit.c) may pass null ts and non-null cg. + * The regexp parser calls us with null ts when the regexp is constructed + * at runtime and does not come from a literal embedded in a script. */ if (ts) { + JS_ASSERT(ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT); report->filename = ts->filename; if (pn) { report->lineno = pn->pn_pos.begin.lineno; @@ -639,9 +594,6 @@ ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags, report->tokenptr = report->linebuf + index; report->uclinebuf = linechars; report->uctokenptr = report->uclinebuf + index; - } else if (cg) { - report->filename = cg->filename; - report->lineno = CG_CURRENT_LINE(cg); } else { /* * If we can't find out where the error was based on the current @@ -1908,10 +1860,8 @@ skipline: } if (ts->flags & TSF_OPERAND) { - JSObject *obj; uintN flags; JSBool inCharClass = JS_FALSE; - JSParsedObjectBox *regexpPob; INIT_TOKENBUF(); for (;;) { @@ -1963,29 +1913,8 @@ skipline: if (!TOKENBUF_OK()) goto error; NUL_TERM_TOKENBUF(); - obj = js_NewRegExpObject(cx, ts, - TOKENBUF_BASE(), - TOKENBUF_LENGTH(), - flags); - if (!obj) - goto error; - - regexpPob = js_NewParsedObjectBox(cx, ts->parseContext, obj); - if (!regexpPob) - goto error; - - /* - * If the regexp's script is one-shot, we can avoid the extra - * fork-on-exec costs of JSOP_REGEXP by selecting JSOP_OBJECT. - * Otherwise, to avoid incorrect proto, parent, and lastIndex - * sharing among threads and sequentially across re-execution, - * select JSOP_REGEXP. - */ - tp->t_op = (cx->fp->flags & (JSFRAME_EVAL | JSFRAME_COMPILE_N_GO)) - ? JSOP_OBJECT - : JSOP_REGEXP; - tp->t_pob = regexpPob; - tt = TOK_OBJECT; + tp->t_reflags = flags; + tt = TOK_REGEXP; break; } diff --git a/mozilla/js/src/jsscan.h b/mozilla/js/src/jsscan.h index 152b2de33b8..de349d610c1 100644 --- a/mozilla/js/src/jsscan.h +++ b/mozilla/js/src/jsscan.h @@ -84,7 +84,7 @@ typedef enum JSTokenType { TOK_NAME = 29, /* identifier */ TOK_NUMBER = 30, /* numeric constant */ TOK_STRING = 31, /* string constant */ - TOK_OBJECT = 32, /* RegExp or other object constant */ + TOK_REGEXP = 32, /* RegExp constant */ TOK_PRIMARY = 33, /* true, false, null, this, super */ TOK_FUNCTION = 34, /* function keyword */ TOK_EXPORT = 35, /* export keyword */ @@ -204,10 +204,8 @@ struct JSToken { JSOp op; /* operator, for minimal parser */ JSAtom *atom; /* atom table entry */ } s; - struct { /* object literal */ - JSOp op; /* operator, for minimal parser */ - JSParsedObjectBox *pob; /* object literal node */ - } o; + uintN reflags; /* regexp flags, use tokenbuf to access + regexp chars */ struct { /* atom pair, for XML PIs */ JSAtom *atom2; /* auxiliary atom table entry */ JSAtom *atom; /* main atom table entry */ @@ -217,7 +215,7 @@ struct JSToken { }; #define t_op u.s.op -#define t_pob u.o.pob +#define t_reflags u.reflags #define t_atom u.s.atom #define t_atom2 u.p.atom2 #define t_dval u.dval @@ -248,13 +246,11 @@ struct JSTokenStream { JSStringBuffer tokenbuf; /* current token string buffer */ const char *filename; /* input filename or null */ FILE *file; /* stdio stream if reading from file */ - JSPrincipals *principals; /* principals associated with source */ JSSourceHandler listener; /* callback for source; eg debugger */ void *listenerData; /* listener 'this' data */ void *listenerTSData;/* listener data for this TokenStream */ jschar *saveEOL; /* save next end of line in userbuf, to optimize for very long lines */ - JSParseContext *parseContext; }; #define CURRENT_TOKEN(ts) ((ts)->tokens[(ts)->cursor]) @@ -308,21 +304,16 @@ struct JSTokenStream { * Create a new token stream, either from an input buffer or from a file. * Return null on file-open or memory-allocation failure. * - * NB: All of js_New{,Buffer,File}TokenStream() return a pointer to transient - * memory in the current context's temp pool. This memory is deallocated via - * JS_ARENA_RELEASE() after parsing is finished. + * The function uses JSContext.tempPool to allocate internal buffers. The + * caller should release them using JS_ARENA_RELEASE after it has finished + * with the token stream and has called js_CloseTokenStream. */ -extern JSTokenStream * -js_NewTokenStream(JSContext *cx, const jschar *base, size_t length, - const char *filename, uintN lineno, JSPrincipals *principals); +extern JSBool +js_InitTokenStream(JSContext *cx, JSTokenStream *ts, + const jschar *base, size_t length, + FILE *fp, const char *filename, uintN lineno); -extern JS_FRIEND_API(JSTokenStream *) -js_NewBufferTokenStream(JSContext *cx, const jschar *base, size_t length); - -extern JS_FRIEND_API(JSTokenStream *) -js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp); - -extern JS_FRIEND_API(JSBool) +extern void js_CloseTokenStream(JSContext *cx, JSTokenStream *ts); extern JS_FRIEND_API(int) @@ -361,11 +352,10 @@ extern JSBool js_ReportCompileErrorNumberUC(JSContext *cx, void *handle, uintN flags, uintN errorNumber, ...); -/* Steal some JSREPORT_* bits (see jsapi.h) to tell handle's type. */ -#define JSREPORT_HANDLE 0x300 +/* Steal one JSREPORT_* bit (see jsapi.h) to tell handle's type. */ +#define JSREPORT_HANDLE 0x100 #define JSREPORT_TS 0x000 -#define JSREPORT_CG 0x100 -#define JSREPORT_PN 0x200 +#define JSREPORT_PN 0x100 /* * Look ahead one token and return its type. diff --git a/mozilla/js/src/jsscript.c b/mozilla/js/src/jsscript.c index 5719f4715af..32a72f1a96c 100644 --- a/mozilla/js/src/jsscript.c +++ b/mozilla/js/src/jsscript.c @@ -57,6 +57,7 @@ #include "jslock.h" #include "jsnum.h" #include "jsopcode.h" +#include "jsparse.h" #include "jsscript.h" #if JS_HAS_XDR #include "jsxdrapi.h" @@ -1415,7 +1416,7 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg, JSFunction *fun) js_InitAtomMap(cx, &script->atomMap, &cg->atomList); - filename = cg->filename; + filename = cg->treeContext.parseContext->tokenStream.filename; if (filename) { script->filename = js_SaveScriptFilename(cx, filename); if (!script->filename) @@ -1423,10 +1424,9 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg, JSFunction *fun) } script->lineno = cg->firstLine; script->depth = cg->maxStackDepth; - if (cg->principals) { - script->principals = cg->principals; + script->principals = cg->treeContext.parseContext->principals; + if (script->principals) JSPRINCIPALS_HOLD(cx, script->principals); - } if (!js_FinishTakingSrcNotes(cx, cg, SCRIPT_NOTES(script))) goto bad; diff --git a/mozilla/js/src/jsxml.c b/mozilla/js/src/jsxml.c index bdf5b584ca7..9230b8e9046 100644 --- a/mozilla/js/src/jsxml.c +++ b/mozilla/js/src/jsxml.c @@ -1956,12 +1956,11 @@ ParseXMLSource(JSContext *cx, JSString *src) jschar *chars; const jschar *srcp, *endp; JSXML *xml; - void *mark; - JSTokenStream *ts; + JSParseContext pc; + const char *filename; uintN lineno; JSStackFrame *fp; JSOp op; - JSParseContext pc; JSParseNode *pn; JSXMLArray nsarray; uintN flags; @@ -2003,28 +2002,25 @@ ParseXMLSource(JSContext *cx, JSString *src) chars [offset + dstlen] = 0; xml = NULL; - mark = JS_ARENA_MARK(&cx->tempPool); - ts = js_NewBufferTokenStream(cx, chars, length); - if (!ts) - goto out; for (fp = cx->fp; fp && !fp->pc; fp = fp->down) JS_ASSERT(!fp->script); + filename = NULL; + lineno = 1; if (fp) { op = (JSOp) *fp->pc; if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) { - ts->filename = fp->script->filename; + filename = fp->script->filename; lineno = js_PCToLineNumber(cx, fp->script, fp->pc); - for (endp = srcp + srclen; srcp < endp; srcp++) + for (endp = srcp + srclen; srcp < endp; srcp++) { if (*srcp == '\n') --lineno; - ts->lineno = lineno; + } } } - js_InitParseContext(cx, &pc); - JS_ASSERT(!ts->parseContext); - ts->parseContext = &pc; - pn = js_ParseXMLTokenStream(cx, cx->fp->scopeChain, ts, JS_FALSE); + if (!js_InitParseContext(cx, &pc, chars, length, NULL, filename, lineno)) + goto out; + pn = js_ParseXMLText(cx, cx->fp->scopeChain, &pc, JS_FALSE); if (pn && XMLArrayInit(cx, &nsarray, 1)) { if (GetXMLSettingFlags(cx, &flags)) xml = ParseNodeToXML(cx, pn, &nsarray, flags); @@ -2034,7 +2030,6 @@ ParseXMLSource(JSContext *cx, JSString *src) js_FinishParseContext(cx, &pc); out: - JS_ARENA_RELEASE(&cx->tempPool, mark); JS_free(cx, chars); return xml;