js.c jsemit.c jsemit.h jsgc.c jsinterp.c jsopcode.c jsopcode.def

- Switch improvements:
  - JSOP_CONDSWITCH is a 1 byte nop, not variable length with the same kind
    of immediate operand as JSOP_LOOKUPSWITCH (which is useless except for
    decompilation).  New scheme uses SRC_COMMA notes on each JSOP_CASE opcode,
    usually 2 bytes per note, and a typically-1-byte 2nd offset on SRC_SWITCH:
      1 + 2 * ncases
    vs. the previous JSOP_LOOKUPSWITCH immediate, which consumed:
      4 * ncases
    bytes after the switch opcode just for decompilation.
  - SRC_SWITCH has two offsets, first to end of switch as before, the second
    to first case if JSOP_CONDSWITCH, for decompilation.
  - Optimize switches with all-constant cases using JSOP_TABLESWITH, or if
    that can't be used, JSOP_LOOKUPSWITCH, before falling back on ECMAv2's
    JSOP_CONDSWITCH.
  - Use cx->gcDisabled when evaluating case exprs at compile time for old,
    pre-ECMAv2 switches, to prevent branch-callback-based GC invocations
    from ripping apart the unrooted temporary script for each case expr.
  - Fixed up stale SRC_SWITCH comments in jsemit.h.

jsemit.c jsemit.h
  - TREE_CONTEXT_INIT to match ATOM_LIST_INIT, not English word order.
  - Reorganized JSCodeGenerator to sort of match argument order to
    js_InitCodeGenerator.
  - Got rid of confusing CG_RESET* macros and used memset(cg, 0, sizeof *cg)
    and non-zero-default init in js_InitCodeGenerator.  js_ResetCodeGenerator
    just releases the code and temp arena pools and leaves the cg in a state
    where it must be re-initialized (as before, but more obvious).
  - In the same spirit, don't do partial "resets" or src and trynotes in their
    js_FinishTaking*Notes functions -- those are friends of jsscript.c and are
    not general, idempotent functions.

jsapi.c jsapi.h jsarray.c jsatom.c jsatom.h jscntxt.c jsemit.c jsmsg.def
jsnum.c jsobj.c jsopcode.c jsregexp.c jsscan.c jsstr.c jsxdrapi.
  - Use PR_snprintf rather than sprintf always, so we don't have to worry
    about systems with 64-bit longs that overflow 12-byte buffers and open
    Morris-Worm-type security holes.
  - Trim extra spaces, fix hanging indentation, and similar anal retention.
  - Renamed JSMSG_BAD_PROTO_SORT to JSMSG_BAD_SORT_ARG cuz that's what it
    is complaining about.
  - SRC_CATCHGUARD still lived in comments, but it's SRC_CATCH in code.

jscntxt.c jscntxt.h jsinterp.c
  - Packed nearby JSPackedBools and added a new one: gcDisabled, for use by
    jsemit.c's pre-ECMAv2 switch case expr eval.
  - Rip out old js_InterpreterHooks stuff from original liveconnect (moja).
  - Remove javaData and savedErrors from JSContext.  Leaving it to fur or
    shaver to remove javaData from jsscript.h.
This commit is contained in:
brendan%netscape.com 1998-09-08 05:39:51 +00:00
Родитель cb5493bab6
Коммит 347aaac8d3
36 изменённых файлов: 5894 добавлений и 5812 удалений

Просмотреть файл

@ -539,7 +539,7 @@ PCToLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
static void
SrcNotes(JSContext *cx, JSFunction *fun )
{
uintN offset, delta;
uintN offset, delta, caseOff;
jssrcnote *notes, *sn;
JSSrcNoteType type;
jsatomid atomIndex;
@ -578,6 +578,12 @@ SrcNotes(JSContext *cx, JSFunction *fun )
atom = js_GetAtom(cx, &fun->script->atomMap, atomIndex);
printf(" atom %u (%s)", (uintN)atomIndex, ATOM_BYTES(atom));
break;
case SRC_SWITCH:
printf(" length %u", (uintN) js_GetSrcNoteOffset(sn, 0));
caseOff = (uintN) js_GetSrcNoteOffset(sn, 1);
if (caseOff)
printf(" first case offset %u", caseOff);
break;
case SRC_CATCH:
delta = (uintN) js_GetSrcNoteOffset(sn, 0);
if (delta)
@ -723,6 +729,7 @@ DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
fclose(file);
}
return JS_TRUE;
#undef LINE_BUF_LEN
}
static JSBool

Просмотреть файл

@ -28,6 +28,7 @@
#include "prarena.h"
#include "prassert.h"
#include "prclist.h"
#include "prprintf.h"
#include "jsapi.h"
#include "jsarray.h"
#include "jsatom.h"
@ -115,11 +116,10 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
fun = js_ValueToFunction(cx, &argv[-2], JS_FALSE);
if (fun) {
char numBuf[12];
sprintf(numBuf, "%u", argc);
PR_snprintf(numBuf, sizeof numBuf, "%u", argc);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_MORE_ARGS_NEEDED,
JS_GetFunctionName(fun),
numBuf,
JS_GetFunctionName(fun), numBuf,
(argc == 1) ? "" : "s");
}
return JS_FALSE;
@ -191,8 +191,8 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
default: {
char charBuf[2] = " ";
charBuf[0] = *cp;
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_CHAR, charBuf);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR,
charBuf);
return JS_FALSE;
}
}
@ -249,13 +249,13 @@ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
break;
default: {
char numBuf[12];
sprintf(numBuf, "%d", (int)type);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_TYPE, numBuf);
PR_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE,
numBuf);
ok = JS_FALSE;
}
break;
}
}
return ok;
}
@ -1704,7 +1704,7 @@ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
if (obj2 != obj || !OBJ_IS_NATIVE(obj2)) {
char numBuf[12];
OBJ_DROP_PROPERTY(cx, obj2, prop);
sprintf(numBuf, "%ld", (long)alias);
PR_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
return JS_FALSE;

Просмотреть файл

@ -949,12 +949,11 @@ JS_ReportOutOfMemory(JSContext *cx);
struct JSErrorReport {
const char *filename; /* source file name, URL, etc., or null */
uintN lineno; /* source line number */
const char *linebuf; /* offending source line without final '\n' */
const char *linebuf; /* offending source line without final \n */
const char *tokenptr; /* pointer to error token in linebuf */
const jschar *uclinebuf; /* unicode (original) line buffer */
const jschar *uctokenptr;/* unicode (original) token pointer */
const jschar *uctokenptr; /* unicode (original) token pointer */
uintN flags; /* error/warning, etc. */
uintN errorNumber; /* the error number, e.g. see jsmsg.def */
JSString *ucmessage; /* the (default) error message */
JSString **messageArgs; /* arguments for the error message */

Просмотреть файл

@ -24,7 +24,6 @@
#include <string.h>
#include "prtypes.h"
#include "prassert.h"
#include "prprintf.h"
#include "jsapi.h"
#include "jsarray.h"
#include "jsatom.h"
@ -699,7 +698,7 @@ array_sort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (argc > 0) {
if (JSVAL_IS_PRIMITIVE(argv[0])) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_PROTO_SORT);
JSMSG_BAD_SORT_ARG);
return JS_FALSE;
}
fval = argv[0];

Просмотреть файл

@ -25,6 +25,7 @@
#include "prtypes.h"
#include "prassert.h"
#include "prhash.h"
#include "prprintf.h"
#include "jsapi.h"
#include "jsatom.h"
#include "jscntxt.h"
@ -606,7 +607,7 @@ js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i)
PR_ASSERT(map->vector && i < map->length);
if (!map->vector || i >= map->length) {
char numBuf[12];
sprintf(numBuf, "%s", (long)i);
PR_snprintf(numBuf, sizeof numBuf, "%lu", (unsigned long)i);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_ATOMIC_NUMBER, numBuf);
return NULL;

Просмотреть файл

@ -40,14 +40,6 @@
#include "jsscan.h"
#include "jsscript.h"
JSInterpreterHooks *js_InterpreterHooks = NULL;
JS_FRIEND_API(void)
js_SetInterpreterHooks(JSInterpreterHooks *hooks)
{
js_InterpreterHooks = hooks;
}
JSContext *
js_NewContext(JSRuntime *rt, size_t stacksize)
{
@ -103,11 +95,6 @@ js_DestroyContext(JSContext *cx)
rtempty = (rt->contextList.next == (PRCList *)&rt->contextList);
JS_UNLOCK_RUNTIME(rt);
if (js_InterpreterHooks && js_InterpreterHooks->destroyContext) {
/* This is a stub, but in case it removes roots, call it now. */
js_InterpreterHooks->destroyContext(cx);
}
if (rtempty) {
/* Unpin all pinned atoms before final GC. */
js_UnpinPinnedAtoms(&rt->atomState);
@ -209,14 +196,14 @@ js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
*/
JSBool
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
void *userRef, const uintN errorNumber, char **message,
JSErrorReport *reportp, va_list ap)
void *userRef, const uintN errorNumber,
char **messagep, JSErrorReport *reportp, va_list ap)
{
const JSErrorFormatString *fmtData;
int i;
int argCount;
*message = NULL;
*messagep = NULL;
if (callback) {
fmtData = (*callback)(userRef, "Mountain View", errorNumber);
if (fmtData != NULL) {
@ -250,7 +237,7 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
expandedLength
+= strlen((char *)reportp->messageArgs[i]);
}
*message = out = malloc(expandedLength + 1);
*messagep = out = malloc(expandedLength + 1);
if (!out) {
if (reportp->messageArgs) {
free(reportp->messageArgs);
@ -285,20 +272,21 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
JS_NewStringCopyZ(cx, (char *)reportp->messageArgs[i]);
}
} else {
*message = JS_strdup(cx, fmtData->format);
*messagep = JS_strdup(cx, fmtData->format);
}
/*
* And finally convert the message.
*/
reportp->ucmessage = JS_NewStringCopyZ(cx, *message);
reportp->ucmessage = JS_NewStringCopyZ(cx, *messagep);
}
}
if (*message == NULL) {
if (*messagep == NULL) {
/* where's the right place for this ??? */
const char *defaultErrorMessage
= "No error message available for error number %d";
*message = (char *)malloc(strlen(defaultErrorMessage) + 16);
sprintf(*message, defaultErrorMessage, errorNumber);
size_t nbytes = strlen(defaultErrorMessage) + 16;
*messagep = (char *)malloc(nbytes);
PR_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber);
}
return JS_TRUE;
}
@ -308,7 +296,7 @@ js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
void *userRef, const uintN errorNumber, va_list ap)
{
JSStackFrame *fp;
JSErrorReport report, *reportp;
JSErrorReport report;
char *message;
report.messageArgs = NULL;
@ -319,22 +307,19 @@ js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
if (fp && fp->script && fp->pc) {
report.filename = fp->script->filename;
report.lineno = js_PCToLineNumber(fp->script, fp->pc);
}
else {
} else {
report.filename = NULL;
report.lineno = 0;
}
/* XXX should fetch line somehow */
report.linebuf = NULL;
report.tokenptr = NULL;
report.flags = flags;
report.errorNumber = errorNumber;
reportp = &report;
if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
&message, reportp, ap))
&message, &report, ap))
return;
#if JS_HAS_ERROR_EXCEPTIONS
@ -344,10 +329,10 @@ js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
* exception is thrown, then the JSREPORT_EXCEPTION flag will be set
* on the error report, and exception-aware hosts should ignore it.
*/
js_ErrorToException(cx, reportp, message);
js_ErrorToException(cx, &report, message);
#endif
js_ReportErrorAgain(cx, message, reportp);
js_ReportErrorAgain(cx, message, &report);
if (message)
free(message);

Просмотреть файл

@ -150,31 +150,20 @@ struct JSContext {
/* Client opaque pointer */
void *data;
/* Java environment and JS errors to throw as exceptions. */
void *javaEnv;
void *savedErrors;
/* GC and thread-safe state. */
JSStackFrame *dormantFrameChain; /* dormant stack frame to scan */
uint32 gcDisabled; /* XXX for pre-ECMAv2 switch */
#ifdef JS_THREADSAFE
prword thread;
JSPackedBool gcActive;
jsrefcount requestDepth;
JSPackedBool gcActive;
#endif
JSStackFrame *dormantFrameChain; /* dormant frame chains */
/* Exception state (NB: throwing is packed with gcActive above). */
JSPackedBool throwing; /* is there a pending exception? */
jsval exception; /* most-recently-thrown exceptin */
};
typedef struct JSInterpreterHooks {
void (*destroyContext)(JSContext *cx);
void (*destroyScript)(JSContext *cx, JSScript *script);
void (*destroyFrame)(JSContext *cx, JSStackFrame *frame);
} JSInterpreterHooks;
extern JSInterpreterHooks *js_InterpreterHooks;
extern JS_FRIEND_API(void)
js_SetInterpreterHooks(JSInterpreterHooks *hooks);
extern JSContext *
js_NewContext(JSRuntime *rt, size_t stacksize);

Просмотреть файл

@ -21,12 +21,11 @@
*/
#include "jsstddef.h"
#include <memory.h>
#include <string.h>
#include "prtypes.h"
#include "prarena.h"
#include "prassert.h"
#include "prprintf.h"
#include "jsapi.h"
#include "jscntxt.h"
#include "jsconfig.h"
@ -45,6 +44,7 @@ js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg,
const char *filename, uintN lineno,
JSPrincipals *principals)
{
memset(cx, 0, sizeof *cg);
cg->codeMark = PR_ARENA_MARK(&cx->codePool);
cg->tempMark = PR_ARENA_MARK(&cx->tempPool);
PR_ARENA_ALLOCATE(cg->base, &cx->codePool, CGINCR);
@ -52,12 +52,13 @@ js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg,
JS_ReportOutOfMemory(cx);
return JS_FALSE;
}
cg->next = cg->base;
cg->limit = CG_CODE(cg, CGINCR);
cg->filename = filename;
cg->firstLine = lineno;
cg->firstLine = cg->currentLine = lineno;
cg->principals = principals;
cg->tryBase = cg->tryLimit = NULL;
CG_RESET(cg);
TREE_CONTEXT_INIT(&cg->treeContext);
ATOM_LIST_INIT(&cg->atomList);
return JS_TRUE;
}
@ -66,7 +67,6 @@ js_ResetCodeGenerator(JSContext *cx, JSCodeGenerator *cg)
{
PR_ARENA_RELEASE(&cx->codePool, cg->codeMark);
PR_ARENA_RELEASE(&cx->tempPool, cg->tempMark);
CG_RESET(cg);
}
static ptrdiff_t
@ -77,8 +77,6 @@ EmitCheck(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t delta)
PR_ASSERT(delta < CGINCR);
offset = CG_OFFSET(cg);
if (op != JSOP_NOP)
cg->lastCodeOffset = offset;
if ((pruword)cg->next + delta >= (pruword)cg->limit) {
length = PTRDIFF(cg->limit, cg->base, jsbytecode);
cgsize = length * sizeof(jsbytecode);
@ -108,7 +106,7 @@ UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
cg->stackDepth -= nuses;
if (cg->stackDepth < 0) {
char numBuf[12];
sprintf(numBuf, "%d", target);
PR_snprintf(numBuf, sizeof numBuf, "%d", target);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_STACK_UNDERFLOW,
cg->filename ? cg->filename : "stdin", numBuf);
@ -201,8 +199,8 @@ StatementName(JSCodeGenerator *cg)
static void
ReportStatementTooLarge(JSContext *cx, JSCodeGenerator *cg)
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_NEED_DIET, StatementName(cg));
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEED_DIET,
StatementName(cg));
}
JSBool
@ -242,8 +240,9 @@ EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
case STMT_FINALLY:
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||
js_Emit3(cx, cg, JSOP_GOSUB, JUMP_OFFSET_HI(finallyIndex),
JUMP_OFFSET_LO(finallyIndex)) < 0)
JUMP_OFFSET_LO(finallyIndex)) < 0) {
return -1;
}
finallyIndex--;
break;
case STMT_WITH:
@ -446,6 +445,8 @@ js_EmitFunctionBody(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body,
}
#if JS_HAS_EXCEPTIONS
/* XXX use PatchGotos-style back-patch chaining, not bytecode-linear search */
#define BYTECODE_ITER(pc, max, body) \
while (pc < max) { \
JSCodeSpec *cs = &js_CodeSpec[(JSOp)*pc]; \
@ -495,7 +496,7 @@ FixupCatchJumps(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t tryStart,
return JS_TRUE;
}
#endif
#endif /* JS_HAS_EXCEPTIONS */
JSBool
js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
@ -664,6 +665,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
uint32 ncases, tablen;
JSScript *script;
jsint i, low, high;
jsdouble d;
size_t switchsize, tablesize;
void *mark;
JSParseNode **table;
@ -671,9 +673,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
JSBool hasDefault = JS_FALSE;
JSBool isEcmaSwitch = cx->version == JSVERSION_DEFAULT ||
cx->version >= JSVERSION_1_4;
ptrdiff_t defaultOpPc = -1;
ptrdiff_t defaultOffset = -1;
switchop = isEcmaSwitch ? JSOP_CONDSWITCH : JSOP_TABLESWITCH;
/* Try for most optimal, fall back if not dense ints, and per ECMAv2. */
switchop = JSOP_TABLESWITCH;
/* Emit code for the discriminant first. */
if (!js_EmitTree(cx, cg, pn->pn_kid1))
@ -701,8 +704,41 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
continue;
}
PR_ASSERT(pn3->pn_type == TOK_CASE);
pn4 = pn3->pn_left;
if (isEcmaSwitch) {
if (switchop == JSOP_CONDSWITCH)
continue;
switch (pn4->pn_type) {
case TOK_NUMBER:
d = pn4->pn_dval;
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
pn3->pn_val = INT_TO_JSVAL(i);
} else {
atom = js_AtomizeDouble(cx, d, 0);
if (!atom)
return JS_FALSE;
pn3->pn_val = ATOM_KEY(atom);
}
break;
case TOK_STRING:
pn3->pn_val = ATOM_KEY(pn4->pn_atom);
break;
case TOK_PRIMARY:
if (pn4->pn_op == JSOP_TRUE) {
pn3->pn_val = JSVAL_TRUE;
break;
}
if (pn4->pn_op == JSOP_FALSE) {
pn3->pn_val = JSVAL_FALSE;
break;
}
/* FALL THROUGH */
default:
switchop = JSOP_CONDSWITCH;
continue;
}
} else {
/* Pre-ECMAv2 switch evals case exprs at compile time. */
if (!cg2.base) {
if (!js_InitCodeGenerator(cx, &cg2, cg->filename,
pn3->pn_pos.begin.lineno,
@ -712,7 +748,6 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
} else {
js_ResetCodeGenerator(cx, &cg2);
}
pn4 = pn3->pn_left;
cg2.currentLine = pn4->pn_pos.begin.lineno;
if (!js_EmitTree(cx, &cg2, pn4))
return JS_FALSE;
@ -723,29 +758,31 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
return JS_FALSE;
/*
* The GC must not run during this case expression
* evaluation. It won't if it runs only from the
* branch callback (because the only branches possible
* in a case expression come from ?: expressions,
* and those generate downward branches, while the
* branch callback runs only for upward branches).
* XXX - but function calls are possible!
* XXX The GC must not run during this case expr eval, so
* kludge cx->gcDisabled to keep it at bay. The current GC
* rules say that the GC can run only when no requests are
* active, or when the only active request explicitly calls
* JS_GC or JS_MaybeGC from its branch callback.
*/
cx->gcDisabled++;
ok = js_Execute(cx, cx->fp->scopeChain, script, NULL,
cx->fp, JS_FALSE, &pn3->pn_val);
cx->gcDisabled--;
js_DestroyScript(cx, script);
if (!ok)
return JS_FALSE;
}
if (!JSVAL_IS_NUMBER(pn3->pn_val) &&
!JSVAL_IS_STRING(pn3->pn_val) &&
!JSVAL_IS_BOOLEAN(pn3->pn_val)) {
char numBuf[12];
sprintf(numBuf, "%u", pn4->pn_pos.begin.lineno);
PR_snprintf(numBuf, sizeof numBuf, "%u",
pn4->pn_pos.begin.lineno);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_CASE,
cg2.filename ? cg2.filename : "stdin",
numBuf);
return JS_FALSE;
}
@ -765,7 +802,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (high < i)
high = i;
}
if (switchop != JSOP_CONDSWITCH && cg2.base)
if (switchop == JSOP_CONDSWITCH) {
PR_ASSERT(!cg2.base);
} else {
if (cg2.base)
js_ResetCodeGenerator(cx, &cg2);
if (switchop == JSOP_TABLESWITCH) {
tablen = (uint32)(high - low + 1);
@ -773,19 +813,29 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
switchop = JSOP_LOOKUPSWITCH;
}
}
}
/* Emit a note with an offset telling total switch code length. */
noteIndex = js_NewSrcNote2(cx, cg, SRC_SWITCH, 0);
/*
* Emit a note with two offsets: first tells total switch code length,
* second tells offset to first JSOP_CASE if condswitch.
*/
noteIndex = js_NewSrcNote3(cx, cg, SRC_SWITCH, 0, 0);
if (noteIndex < 0)
return JS_FALSE;
if (switchop == JSOP_TABLESWITCH) {
if (switchop == JSOP_CONDSWITCH) {
/*
* 0 bytes of immediate for unoptimized ECMAv2 switch.
*/
switchsize = 0;
} else if (switchop == JSOP_TABLESWITCH) {
/*
* 3 offsets (len, low, high) before the table, 1 per entry.
*/
switchsize = (size_t)(6 + 2 * tablen);
} else {
/*
* JSOP_LOOKUPSWITCH:
* 1 offset (len) and 1 atom index (npairs) before the table,
* 1 atom index and 1 jump offset per entry.
*/
@ -797,24 +847,39 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
return JS_FALSE;
if (switchop == JSOP_CONDSWITCH) {
intN caseNoteIndex = -1;
/* Emit code for evaluating cases and jumping to case statements. */
if (!js_SetJumpOffset(cx, cg, CG_CODE(cg, top),
CG_OFFSET(cg) - top))
return JS_FALSE;
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
pn4 = pn3->pn_left;
if (pn4 && !js_EmitTree(cx, cg, pn4))
return JS_FALSE;
if (caseNoteIndex >= 0) {
/* off is the previous JSOP_CASE's bytecode offset. */
if (!js_SetSrcNoteOffset(cx, cg, caseNoteIndex, 0,
CG_OFFSET(cg) - off)) {
return JS_FALSE;
}
}
if (pn3->pn_type == TOK_DEFAULT)
continue;
pn4 = pn3->pn_left;
if (!js_EmitTree(cx, cg, pn4))
caseNoteIndex = js_NewSrcNote2(cx, cg, SRC_COMMA, 0);
if (caseNoteIndex < 0)
return JS_FALSE;
pn3->pn_offset = js_Emit3(cx, cg, JSOP_CASE, 0, 0);
if (pn3->pn_offset < 0)
off = js_Emit3(cx, cg, JSOP_CASE, 0, 0);
if (off < 0)
return JS_FALSE;
pn3->pn_offset = off;
if (pn3 == pn2->pn_head) {
/* Switch note's second offset is to first JSOP_CASE. */
if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 1, off - top))
return JS_FALSE;
pn3->pn_offset;
}
}
/* Emit default even if no explicit default statement. */
defaultOpPc = js_Emit3(cx, cg, JSOP_DEFAULT, 0, 0);
if (defaultOpPc < 0)
defaultOffset = js_Emit3(cx, cg, JSOP_DEFAULT, 0, 0);
if (defaultOffset < 0)
return JS_FALSE;
}
@ -833,30 +898,31 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
if (!hasDefault) {
/* If no default case, offset for default is to end of switch */
/* If no default case, offset for default is to end of switch. */
off = CG_OFFSET(cg) - top;
}
/* Set the default offset (to end of switch if no default). */
if (switchop == JSOP_CONDSWITCH) {
PR_ASSERT(defaultOffset != -1);
if (!js_SetJumpOffset(cx, cg, CG_CODE(cg, defaultOffset),
off - (defaultOffset - top))) {
return JS_FALSE;
}
} else {
pc = CG_CODE(cg, top);
if (switchop != JSOP_CONDSWITCH) {
if (!js_SetJumpOffset(cx, cg, pc, off))
return JS_FALSE;
}
if (defaultOpPc != -1) {
if (!js_SetJumpOffset(cx, cg, CG_CODE(cg, defaultOpPc),
off - (defaultOpPc - top)))
return JS_FALSE;
}
pc += 2;
}
/* Set the SRC_SWITCH note's offset operand to tell end of switch. */
off = CG_OFFSET(cg) - top;
if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, (ptrdiff_t)off))
if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, off))
return JS_FALSE;
/* Fill in jump or lookup table. */
if (switchop == JSOP_TABLESWITCH) {
/* Fill in jump table. */
if (!js_SetJumpOffset(cx, cg, pc, low))
return JS_FALSE;
pc += 2;
@ -890,7 +956,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
PR_ARENA_RELEASE(&cx->tempPool, mark);
}
} else {
} else if (switchop == JSOP_LOOKUPSWITCH) {
/* Fill in lookup table. */
SET_ATOM_INDEX(pc, ncases);
pc += 2;
@ -1193,7 +1260,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (!js_Emit3(cx, cg, JSOP_GOSUB, 0, 0)) \
return JS_FALSE; \
PR_END_MACRO
;
/*
* When a finally block is `active' (STMT_FINALLY on the treeContext),
* non-local jumps result in a GOSUB being written into the bytecode
@ -1213,9 +1280,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
/*
* About SETSP:
* An exception can be thrown while the stack is in an
* unbalanced state, and this causes problems with things like
* function invocation later on.
* An exception can be thrown while the stack is in an unbalanced
* state, and this causes problems with things like function invocation
* later on.
*
* To fix this, we compute the `balanced' stack depth upon try entry,
* and then restore the stack to this depth when we hit the first catch
@ -1256,7 +1323,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* pushobj
* newinit
* exception
* initprop <atom> maybe marked SRC_CATCHGUARD
* initprop <atom> marked SRC_CATCH
* enterwith
* [< catchguard code >] if there's a catchguard
* ifeq <offset to next catch block>
@ -1402,9 +1469,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
return JS_FALSE;
}
/* if we've got a finally, it goes here, and we have to fix up
the gosubs that might have been emitted before non-local jumps */
/*
* If we've got a finally, it goes here, and we have to fix up
* the gosubs that might have been emitted before non-local jumps.
*/
if (pn->pn_kid3) {
ptrdiff_t finallyIndex;
finallyIndex = CG_OFFSET(cg);
@ -2140,10 +2208,10 @@ uint8 js_SrcNoteArity[] = {
0, /* SRC_ENDBRACE */
1, /* SRC_BREAK2LABEL */
1, /* SRC_CONT2LABEL */
1, /* SRC_SWITCH */
2, /* SRC_SWITCH */
1, /* SRC_FUNCDEF */
1, /* SRC_TRYFIN */
1, /* SRC_CATCHGUARD */
1, /* SRC_CATCH */
0, /* SRC_NEWLINE */
1, /* SRC_SETLINE */
0 /* SRC_XDELTA */
@ -2181,7 +2249,7 @@ js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type)
{
intN index, n;
jssrcnote *sn;
ptrdiff_t offset, saveOffset, delta, xdelta;
ptrdiff_t offset, delta, xdelta;
/*
* Claim a note slot in cg->notes by growing it if necessary and then
@ -2195,8 +2263,7 @@ js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type)
* big to fit in sn, allocate one or more xdelta notes and reset sn.
*/
offset = CG_OFFSET(cg);
saveOffset = cg->lastNoteOffset;
delta = offset - saveOffset;
delta = offset - cg->lastNoteOffset;
cg->lastNoteOffset = offset;
if (delta >= SN_DELTA_LIMIT) {
do {
@ -2281,7 +2348,7 @@ js_SrcNoteLength(jssrcnote *sn)
return 1;
for (base = sn++; --arity >= 0; sn++) {
if (*sn & SN_3BYTE_OFFSET_FLAG)
sn +=2 ;
sn +=2;
}
return sn - base;
}
@ -2296,8 +2363,10 @@ js_GetSrcNoteOffset(jssrcnote *sn, uintN which)
if (*sn & SN_3BYTE_OFFSET_FLAG)
sn += 2;
}
if (*sn & SN_3BYTE_OFFSET_FLAG)
return (ptrdiff_t)((((uint32)(*sn & SN_3BYTE_OFFSET_MASK)) << 16) | (sn[1] << 8) | sn[2]);
if (*sn & SN_3BYTE_OFFSET_FLAG) {
return (ptrdiff_t)((((uint32)(sn[0] & SN_3BYTE_OFFSET_MASK)) << 16)
| (sn[1] << 8) | sn[2]);
}
return (ptrdiff_t)*sn;
}
@ -2365,7 +2434,6 @@ js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg)
return NULL;
memcpy(final, tmp, count * sizeof(jssrcnote));
SN_MAKE_TERMINATOR(&final[count]);
CG_RESET_NOTES(cg);
return final;
}
@ -2373,32 +2441,16 @@ JSBool
js_AllocTryNotes(JSContext *cx, JSCodeGenerator *cg)
{
size_t size;
if (!cg->treeContext.tryCount)
return JS_TRUE;
if (!cg->tryBase) {
PR_ASSERT(!cg->tryBase);
size = (cg->treeContext.tryCount + 1) * sizeof(JSTryNote);
PR_ARENA_ALLOCATE(cg->tryBase, &cx->tempPool, size);
if (!cg->tryBase)
return JS_FALSE;
cg->tryNext = cg->tryBase;
} else {
/* already have some TryNotes here, so extend them. */
ptrdiff_t nextOffset = cg->tryNext - cg->tryBase;
size_t oldsize = (char *)cg->tryLimit - (char *)cg->tryBase;
size = oldsize + cg->treeContext.tryCount * sizeof(JSTryNote);
PR_ARENA_GROW(cg->tryBase, &cx->tempPool, oldsize, size);
if (!cg->tryBase)
return JS_FALSE;
/* need to reset tryNext because GROW may relocate the block */
cg->tryNext = (JSTryNote *)((char *)cg->tryBase + nextOffset);
}
cg->tryLimit = (JSTryNote *)((char *)cg->tryBase + size);
/* reset tryCount */
cg->treeContext.tryCount = 0;
return JS_TRUE;
}
@ -2408,7 +2460,7 @@ js_NewTryNote(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t start,
{
JSTryNote *tn;
PR_ASSERT(cg->tryNext < cg->tryLimit);
PR_ASSERT(cg->tryBase <= cg->tryNext && cg->tryNext < cg->tryLimit);
tn = cg->tryNext++;
tn->start = start;
tn->length = end - start;

Просмотреть файл

@ -75,7 +75,7 @@ struct JSTreeContext { /* tree context for semantic checks */
#define TCF_RETURN_VOID 0x04 /* function has 'return;' */
#define TCF_IN_FOR_INIT 0x08 /* parsing init expr of for; exclude 'in' */
#define INIT_TREE_CONTEXT(tc) \
#define TREE_CONTEXT_INIT(tc) \
((tc)->flags = 0, (tc)->tryCount = 0, (tc)->topStmt = NULL)
struct JSCodeGenerator {
@ -84,37 +84,24 @@ struct JSCodeGenerator {
jsbytecode *base; /* base of JS bytecode vector */
jsbytecode *limit; /* one byte beyond end of bytecode */
jsbytecode *next; /* pointer to next free bytecode */
JSAtomList atomList; /* literals indexed for mapping */
ptrdiff_t lastCodeOffset; /* offset of last non-nop opcode */
intN stackDepth; /* current stack depth in basic block */
uintN maxStackDepth; /* maximum stack depth so far */
jssrcnote *notes; /* source notes, see below */
uintN noteCount; /* number of source notes so far */
ptrdiff_t lastNoteOffset; /* code offset for last source note */
const char *filename; /* null or weak link to source filename */
uintN firstLine; /* first line, for js_NewScriptFromCG */
uintN currentLine; /* line number for tree-based srcnote gen */
JSPrincipals *principals; /* principals for constant folding eval */
JSTreeContext treeContext; /* for break/continue code generation */
JSTryNote *tryBase; /* first exception handling block */
JSTryNote *tryNext; /* next avail block */
JSTryNote *tryLimit; /* pointer to one-past-end block */
JSAtomList atomList; /* literals indexed for mapping */
intN stackDepth; /* current stack depth in basic block */
uintN maxStackDepth; /* maximum stack depth so far */
jssrcnote *notes; /* source notes, see below */
uintN noteCount; /* number of source notes so far */
ptrdiff_t lastNoteOffset; /* code offset for last source note */
JSTryNote *tryBase; /* first exception handling note */
JSTryNote *tryLimit; /* pointer to one-past-end note */
JSTryNote *tryNext; /* next available note */
};
#define CG_CODE(cg,offset) ((cg)->base + (offset))
#define CG_OFFSET(cg) PTRDIFF((cg)->next, (cg)->base, jsbytecode)
#define CG_RESET(cg) ((cg)->next = (cg)->base, \
ATOM_LIST_INIT(&(cg)->atomList), \
(cg)->lastCodeOffset = 0, \
(cg)->stackDepth = (cg)->maxStackDepth = 0, \
(cg)->currentLine = (cg)->firstLine, \
INIT_TREE_CONTEXT(&(cg)->treeContext), \
(cg)->tryNext = (cg)->tryBase, \
CG_RESET_NOTES(cg))
#define CG_RESET_NOTES(cg) ((cg)->notes = NULL, (cg)->noteCount = 0, \
(cg)->lastNoteOffset = 0)
#define CG_PUSH(cg, newcg) ((newcg)->atomList = (cg)->atomList)
#define CG_POP(cg, newcg) ((cg)->atomList = (newcg)->atomList)
/*
* Initialize cg to allocate bytecode space from cx->codePool, and srcnote
@ -228,7 +215,7 @@ js_EmitFunctionBody(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body,
* the previous note. If 3 bits of offset aren't enough, extended delta notes
* (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
* are emitted before the next note. Some notes have operand offsets encoded
* in note bytes or byte-pairs.
* immediately after them, in note bytes or byte-triples.
*
* At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE,
* SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
@ -255,9 +242,10 @@ typedef enum JSSrcNoteType {
SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */
SRC_BREAK2LABEL = 16, /* JSOP_GOTO for 'break label' with atomid */
SRC_CONT2LABEL = 17, /* JSOP_GOTO for 'continue label' with atomid */
SRC_SWITCH = 18, /* JSOP_*SWITCH with offset to end of switch */
SRC_SWITCH = 18, /* JSOP_*SWITCH with offset to end of switch,
2nd off to first JSOP_CASE if condswitch */
SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */
SRC_TRYFIN = 20, /* JSOP_NOP for try{} or finally{} section */
SRC_TRYFIN = 20, /* JSOP_NOP for try or finally section */
SRC_CATCH = 21, /* catch block has guard */
SRC_NEWLINE = 22, /* bytecode follows a source newline */
SRC_SETLINE = 23, /* a file-absolute source line number note */
@ -351,8 +339,7 @@ js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg);
/*
* Allocate cg->treeContext.tryCount notes (plus one for the end sentinel)
* from cx->tempPool and set cg->tryBase/tryNext/tryLimit for exactly tryCount
* js_NewTryNote calls. The storage is freed in one fell swoop by JS_Compile*
* API entry points at the end of compilation.
* js_NewTryNote calls. The storage is freed by js_ResetCodeGenerator.
*/
extern JSBool
js_AllocTryNotes(JSContext *cx, JSCodeGenerator *cg);

Просмотреть файл

@ -383,7 +383,8 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
}
JSErrorReport *
js_GetErrorFromException(JSContext *cx, JSObject *errobj) {
js_GetErrorFromException(JSContext *cx, JSObject *errobj)
{
JSExnPrivate *privateData;
#if 0
{
@ -419,7 +420,8 @@ static struct exnname { char *name; char *exception; } errortoexnname[] = {
#endif /* DEBUG */
JSBool
js_ErrorToException(JSContext *cx, JSErrorReport *reportp, const char *message) {
js_ErrorToException(JSContext *cx, JSErrorReport *reportp, const char *message)
{
JSErrNum errorNumber;
JSObject *errobj;
JSExnType exn;

Просмотреть файл

@ -891,8 +891,8 @@ fun_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
_readonly:
if (JSVERSION_IS_ECMA(cx->version))
return fun_getProperty(cx, obj, id, vp);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_READ_ONLY, js_arguments_str);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_READ_ONLY,
js_arguments_str);
return JS_FALSE;
}
@ -1482,8 +1482,8 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
#ifdef CHECK_ARGUMENT_HIDING
PR_ASSERT(sprop->getter == js_GetArgument);
OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);
JS_ReportErrorNumber(cx, JSREPORT_WARNING, JSMSG_SAME_FORMAL,
ATOM_BYTES(atom));
JS_ReportErrorNumber(cx, JSREPORT_WARNING,
JSMSG_SAME_FORMAL, ATOM_BYTES(atom));
goto badargs;
#else
/*

Просмотреть файл

@ -624,6 +624,13 @@ js_GC(JSContext *cx)
GCFinalizeOp finalizer;
JSBool a_all_clear, f_all_clear;
/*
* XXX kludge for pre-ECMAv2 compile-time switch case expr eval, see
* jsemit.c:js_EmitTree, under case TOK_SWITCH: (look for XXX).
*/
if (cx->gcDisabled)
return;
rt = cx->runtime;
#ifdef JS_THREADSAFE
/* Avoid deadlock. */

Просмотреть файл

@ -26,6 +26,7 @@
#include "prtypes.h"
#include "prarena.h"
#include "prassert.h"
#include "prprintf.h"
#include "jsapi.h"
#include "jsarray.h"
#include "jsatom.h"
@ -656,17 +657,6 @@ have_fun:
}
out:
/*
* Checking frame.annotation limits the use of this hook for uses other
* than releasing annotations, but avoids one C function call for every
* JS function call.
*/
if (frame.annotation &&
js_InterpreterHooks &&
js_InterpreterHooks->destroyFrame) {
js_InterpreterHooks->destroyFrame(cx, &frame);
}
#if JS_HAS_CALL_OBJECT
/* If frame has a call object, sync values and clear back-pointer. */
if (frame.callobj)
@ -849,7 +839,8 @@ ImportProperty(JSContext *cx, JSObject *obj, jsid id)
str = js_DecompileValueGenerator(cx, js_IdToValue(id), NULL);
if (str) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_NOT_EXPORTED, JS_GetStringBytes(str));
JSMSG_NOT_EXPORTED,
JS_GetStringBytes(str));
}
return JS_FALSE;
}
@ -1941,7 +1932,8 @@ js_Interpret(JSContext *cx, jsval *result)
str = js_ValueToString(cx, rval);
if (str) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_NEW_RESULT, JS_GetStringBytes(str));
JSMSG_BAD_NEW_RESULT,
JS_GetStringBytes(str));
}
ok = JS_FALSE;
goto out;
@ -2253,8 +2245,9 @@ js_Interpret(JSContext *cx, jsval *result)
* (This opcode is only emitted for all-integer switches.)
*/
if (JSVERSION_IS_ECMAv2(cx->version) &&
!JSVAL_IS_INT(*sp))
!JSVAL_IS_INT(*sp)) {
break;
}
SAVE_SP(fp);
ok = PopInt(cx, &i);
@ -2326,8 +2319,7 @@ js_Interpret(JSContext *cx, jsval *result)
break;
case JSOP_CONDSWITCH:
len = GET_JUMP_OFFSET(pc);
goto advance_pc;
break;
#endif /* JS_HAS_SWITCH_STATEMENT */
@ -2581,7 +2573,7 @@ js_Interpret(JSContext *cx, jsval *result)
rval = sp[-1];
if (JSVAL_IS_PRIMITIVE(rval)) {
char numBuf[12];
sprintf(numBuf, "%u", (unsigned) i);
PR_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_SHARP_DEF, numBuf);
ok = JS_FALSE;
@ -2605,7 +2597,7 @@ js_Interpret(JSContext *cx, jsval *result)
}
if (!JSVAL_IS_OBJECT(rval)) {
char numBuf[12];
sprintf(numBuf, "%u", (unsigned) i);
PR_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_SHARP_USE, numBuf);
ok = JS_FALSE;
@ -2671,8 +2663,8 @@ js_Interpret(JSContext *cx, jsval *result)
str = js_DecompileValueGenerator(cx, rval, NULL);
if (str) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_INSTANCEOF_RHS, JS_GetStringBytes(str));
JSMSG_BAD_INSTANCEOF_RHS,
JS_GetStringBytes(str));
}
ok = JS_FALSE;
goto out;
@ -2715,7 +2707,7 @@ js_Interpret(JSContext *cx, jsval *result)
default: {
char numBuf[12];
sprintf(numBuf, "%d", op);
PR_snprintf(numBuf, sizeof numBuf, "%d", op);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_BYTECODE, numBuf);
ok = JS_FALSE;

Просмотреть файл

@ -68,7 +68,7 @@ MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 8, 3, JSEXN_TARGETERR, "{0}.prototype.{1
MSG_DEF(JSMSG_NO_CONSTRUCTOR, 9, 1, JSEXN_NONE, "{0} has no constructor")
MSG_DEF(JSMSG_CANT_ALIAS, 10, 3, JSEXN_NONE, "can't alias {0} to {1} in class {2}")
MSG_DEF(JSMSG_NO_PROTO, 11, 1, JSEXN_INTERNALERR, "sorry, Array.prototype.{0} is not yet implemented")
MSG_DEF(JSMSG_BAD_PROTO_SORT, 12, 0, JSEXN_ARRAYERR, "invalid Array.prototype.sort argument")
MSG_DEF(JSMSG_BAD_SORT_ARG, 12, 0, JSEXN_ARRAYERR, "invalid Array.prototype.sort argument")
MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 13, 1, JSEXN_INTERNALERR, "internal error: no index for atom {0}")
MSG_DEF(JSMSG_TOO_MANY_LITERALS, 14, 0, JSEXN_INTERNALERR, "too many literals")
MSG_DEF(JSMSG_CANT_WATCH, 15, 1, JSEXN_NONE, "can't watch non-native objects of class {0}")
@ -192,6 +192,3 @@ MSG_DEF(JSMSG_RESERVED_ID, 132, 1, JSEXN_SYNTAXERR, "{0} is a reserve
MSG_DEF(JSMSG_SYNTAX_ERROR, 133, 0, JSEXN_SYNTAXERR, "syntax error")
MSG_DEF(JSMSG_BAD_SHARP_VAR_DEF, 134, 0, JSEXN_SYNTAXERR, "invalid sharp variable definition")
MSG_DEF(JSMSG_BAD_PROTOTYPE, 135, 1, JSEXN_ERR, "'prototype' property of {0} is not an object")

Просмотреть файл

@ -213,9 +213,9 @@ num_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return JS_FALSE;
if (base < 2 || base > 36) {
char numBuf[12];
sprintf(numBuf, "%d", base);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_RADIX, numBuf);
PR_snprintf(numBuf, sizeof numBuf, "%ld", (long) base);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_RADIX,
numBuf);
return JS_FALSE;
}
if (base != 10 && JSDOUBLE_IS_FINITE(d)) {

Просмотреть файл

@ -1943,9 +1943,10 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
return JS_TRUE;
}
str = js_DecompileValueGenerator(cx, js_IdToValue(id), NULL);
if (str)
if (str) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_PERMANENT, JS_GetStringBytes(str));
}
return JS_FALSE;
}
@ -2393,8 +2394,7 @@ js_ValueToNonNullObject(JSContext *cx, jsval v)
str = js_DecompileValueGenerator(cx, v, NULL);
if (str) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_NO_PROPERTIES,
JS_GetStringBytes(str));
JSMSG_NO_PROPERTIES, JS_GetStringBytes(str));
}
}
return obj;
@ -2480,7 +2480,7 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
clasp = JS_FindClassById(xdr, classId);
if (!clasp) {
char numBuf[12];
sprintf(numBuf, "%d", (long)classId);
PR_snprintf(numBuf, sizeof numBuf, "%ld", (long)classId);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CANT_FIND_CLASS, numBuf);
ok = JS_FALSE;

Просмотреть файл

@ -111,10 +111,9 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
op = (JSOp)*pc;
if (op >= JSOP_LIMIT) {
char numBuf1[12];
char numBuf2[12];
sprintf(numBuf1, "%d", op);
sprintf(numBuf2, "%d", JSOP_LIMIT);
char numBuf1[12], numBuf2[12];
PR_snprintf(numBuf1, sizeof numBuf1, "%d", op);
PR_snprintf(numBuf2, sizeof numBuf2, "%d", JSOP_LIMIT);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BYTECODE_TOO_BIG, numBuf1, numBuf2);
return 0;
@ -228,7 +227,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
default: {
char numBuf[12];
sprintf(numBuf, "%x", cs->format);
PR_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_UNKNOWN_FORMAT, numBuf);
return 0;
@ -594,24 +593,39 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
return JS_FALSE;
jp->indent -= 4;
}
caseExprOff = 1 + JUMP_OFFSET_LEN + ATOM_INDEX_LEN +
tableLength * (ATOM_INDEX_LEN + JUMP_OFFSET_LEN);
if (isCondSwitch)
caseExprOff = (ptrdiff_t) js_CodeSpec[JSOP_CONDSWITCH].length;
for (i = 0; i < tableLength; i++) {
off = table[i].offset;
if (i + 1 < tableLength)
off2 = table[i + 1].offset;
else
off2 = switchLength;
key = table[i].key;
if (isCondSwitch) {
uint32 caseLen = js_CodeSpec[JSOP_CASE].length;
ptrdiff_t caseOff = JSVAL_TO_INT(key);
ptrdiff_t nextCaseExprOff;
/*
* key encodes the JSOP_CASE bytecode's offset from switchtop.
* The next case expression follows immediately, unless we are
* at the last case.
*/
nextCaseExprOff = (ptrdiff_t)
(JSVAL_TO_INT(key) + js_CodeSpec[JSOP_CASE].length);
jp->indent += 2;
if (!Decompile(ss, pc + caseExprOff,
caseOff - caseExprOff + caseLen))
nextCaseExprOff - caseExprOff)) {
return JS_FALSE;
caseExprOff = caseOff + caseLen;
}
caseExprOff = nextCaseExprOff;
} else {
/*
* key comes from an atom, not the decompiler, so we need to
* quote it if it's a string literal.
*/
str = js_ValueToString(cx, key);
if (!str)
return JS_FALSE;
@ -625,6 +639,7 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
}
js_printf(jp, "\tcase %s:\n", rval);
}
jp->indent += 2;
if (off <= defaultOffset && defaultOffset < off2) {
diff = defaultOffset - off;
@ -642,6 +657,7 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
jp->indent -= 4;
}
}
if (defaultOffset == switchLength) {
jp->indent += 2;
js_printf(jp, "\tdefault:\n");
@ -1603,9 +1619,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
}
case JSOP_LOOKUPSWITCH:
case JSOP_CONDSWITCH:
{
jsbytecode *pc2 = pc;
jsbytecode *pc2;
ptrdiff_t off, off2;
jsint npairs;
TableEntry *table;
@ -1613,6 +1628,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
sn = js_GetSrcNote(jp->script, pc);
PR_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
len = js_GetSrcNoteOffset(sn, 0);
pc2 = pc;
off = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
npairs = (jsint) GET_ATOM_INDEX(pc2);
@ -1629,21 +1645,81 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
table[i].key = ATOM_KEY(atom);
table[i].offset = off2;
}
if (op == JSOP_CONDSWITCH) {
/*
* Find offset of default code by finding the default
* instruction and adding its offset.
*/
jsbytecode *pc3;
off = JSVAL_TO_INT(table[npairs-1].key) +
js_CodeSpec[JSOP_CASE].length;
pc3 = pc + off;
off += GET_JUMP_OFFSET(pc3);
}
ok = DecompileSwitch(ss, table, (uintN)npairs, pc, len, off,
op == JSOP_CONDSWITCH);
JS_FALSE);
JS_free(cx, table);
if (!ok)
return ok;
todo = -2;
break;
}
case JSOP_CONDSWITCH:
{
jsbytecode *pc2;
ptrdiff_t off, off2, caseOff;
jsint ncases;
TableEntry *table;
sn = js_GetSrcNote(jp->script, pc);
PR_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
len = js_GetSrcNoteOffset(sn, 0);
off = js_GetSrcNoteOffset(sn, 1);
/*
* Count the cases using offsets from switch to first case,
* and case to case, stored in srcnote immediates.
*/
pc2 = pc;
off2 = off;
for (ncases = 0; off2 != 0; ncases++) {
pc2 += off2;
PR_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT);
if (*pc2 == JSOP_DEFAULT) {
/* End of cases, but count default as a case. */
off2 = 0;
} else {
sn = js_GetSrcNote(jp->script, pc2);
PR_ASSERT(sn && SN_TYPE(sn) == SRC_COMMA);
off2 = js_GetSrcNoteOffset(sn, 0);
}
}
/*
* Allocate table and rescan the cases using their srcnotes,
* stashing each case's delta from switch top in table[i].key,
* and the distance to its statements in table[i].offset.
*/
table = JS_malloc(cx, (size_t)ncases * sizeof *table);
if (!table)
return JS_FALSE;
pc2 = pc;
off2 = off;
for (i = 0; i < ncases; i++) {
pc2 += off2;
PR_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT);
caseOff = pc2 - pc;
table[i].key = INT_TO_JSVAL((jsint) caseOff);
table[i].offset = caseOff + GET_JUMP_OFFSET(pc2);
if (*pc2 == JSOP_CASE) {
sn = js_GetSrcNote(jp->script, pc2);
PR_ASSERT(sn && SN_TYPE(sn) == SRC_COMMA);
off2 = js_GetSrcNoteOffset(sn, 0);
}
}
/*
* Find offset of default code by fetching the default offset
* from the end of table. JSOP_CONDSWITCH always has a default
* case at the end.
*/
off = JSVAL_TO_INT(table[ncases-1].key);
pc2 = pc + off;
off += GET_JUMP_OFFSET(pc2);
ok = DecompileSwitch(ss, table, (uintN)ncases, pc, len, off,
JS_TRUE);
JS_free(cx, table);
if (!ok)
return ok;

Просмотреть файл

@ -204,8 +204,9 @@ OPDEF(JSOP_SETSP, 117,"setsp", NULL, 3, 0, 0, 0, JOF_UINT16
/*
* ECMA-compliant switch statement ops.
* "switch" is essentially "nop" and "default" is essentially "pop" + "goto".
* CONDSWITCH is a decompilable NOP; CASE is ===, POP, jump if true, re-push
* lval if false; and DEFAULT is POP lval and GOTO.
*/
OPDEF(JSOP_CONDSWITCH,118,"switch", NULL, -1, 0, 0, 0, JOF_LOOKUPSWITCH)
OPDEF(JSOP_CONDSWITCH,118,"condswitch", NULL, 1, 0, 0, 0, JOF_BYTE)
OPDEF(JSOP_CASE, 119,"case", NULL, 3, 1, 0, 0, JOF_JUMP)
OPDEF(JSOP_DEFAULT, 120,"default", NULL, 3, 1, 0, 0, JOF_JUMP)

Просмотреть файл

@ -38,7 +38,6 @@
#include "prtypes.h"
#include "prarena.h"
#include "prassert.h"
#include "prprintf.h"
#include "jsapi.h"
#include "jsatom.h"
#include "jscntxt.h"
@ -496,7 +495,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
ok = JS_FALSE; goto out);
pn->pn_pos.begin = ts->token.pos.begin;
INIT_TREE_CONTEXT(&funtc);
TREE_CONTEXT_INIT(&funtc);
pn2 = FunctionBody(cx, ts, fun, &funtc);
if (!pn2) {
ok = JS_FALSE;
@ -843,7 +842,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
case TOK_SWITCH:
{
uintN newlines;
JSParseNode *pn5, *pn6;
JSParseNode *pn5;
JSBool seenDefault = JS_FALSE;
pn = NewParseNode(cx, &ts->token, PN_BINARY);
@ -882,17 +881,17 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
/* fall through */
case TOK_CASE:
pn4 = NewParseNode(cx, &ts->token, PN_BINARY);
if (!pn4)
pn3 = NewParseNode(cx, &ts->token, PN_BINARY);
if (!pn3)
goto bad_switch;
if (tt == TOK_DEFAULT) {
pn4->pn_left = NULL;
pn3->pn_left = NULL;
} else {
pn4->pn_left = Expr(cx, ts, tc);
if (!pn4->pn_left)
pn3->pn_left = Expr(cx, ts, tc);
if (!pn3->pn_left)
goto bad_switch;
}
PN_APPEND(pn2, pn4);
PN_APPEND(pn2, pn3);
if (pn2->pn_count == PR_BIT(16)) {
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_TOO_MANY_CASES);
@ -910,23 +909,23 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
}
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
pn5 = NewParseNode(cx, &ts->token, PN_LIST);
if (!pn5)
pn4 = NewParseNode(cx, &ts->token, PN_LIST);
if (!pn4)
goto bad_switch;
pn5->pn_type = TOK_LC;
PN_INIT_LIST(pn5);
pn4->pn_type = TOK_LC;
PN_INIT_LIST(pn4);
while ((tt = js_PeekToken(cx, ts)) != TOK_RC &&
tt != TOK_CASE && tt != TOK_DEFAULT) {
if (tt == TOK_ERROR)
goto bad_switch;
pn6 = Statement(cx, ts, tc);
if (!pn6)
pn5 = Statement(cx, ts, tc);
if (!pn5)
goto bad_switch;
pn5->pn_pos.end = pn6->pn_pos.end;
PN_APPEND(pn5, pn6);
}
pn4->pn_pos.end = pn5->pn_pos.end;
pn4->pn_right = pn5;
PN_APPEND(pn4, pn5);
}
pn3->pn_pos.end = pn4->pn_pos.end;
pn3->pn_right = pn4;
}
if (newlines)

Просмотреть файл

@ -649,8 +649,7 @@ loop:
case '{':
c = *++cp;
if (!JS7_ISDEC(c)) {
JS_ReportErrorNumber(state->context,
js_GetErrorMessage, NULL,
JS_ReportErrorNumber(state->context, js_GetErrorMessage, NULL,
JSMSG_BAD_QUANTIFIER, state->cp);
return NULL;
}
@ -658,8 +657,7 @@ loop:
for (c = *++cp; JS7_ISDEC(c); c = *++cp) {
min = 10 * min + (uint32)JS7_UNDEC(c);
if (min >> 16) {
JS_ReportErrorNumber(state->context,
js_GetErrorMessage, NULL,
JS_ReportErrorNumber(state->context, js_GetErrorMessage, NULL,
JSMSG_MIN_TOO_BIG, state->cp);
return NULL;
}
@ -693,16 +691,14 @@ loop:
/* Exactly n times. */
if (min == 0) {
zero_quant:
JS_ReportErrorNumber(state->context,
js_GetErrorMessage, NULL,
JS_ReportErrorNumber(state->context, js_GetErrorMessage, NULL,
JSMSG_ZERO_QUANTIFIER, state->cp);
return NULL;
}
max = min;
}
if (*cp != '}') {
JS_ReportErrorNumber(state->context,
js_GetErrorMessage, NULL,
JS_ReportErrorNumber(state->context, js_GetErrorMessage, NULL,
JSMSG_UNTERM_QUANTIFIER, state->cp);
return NULL;
}
@ -720,8 +716,7 @@ loop:
case '*':
if (!(ren->flags & RENODE_NONEMPTY)) {
JS_ReportErrorNumber(state->context,
js_GetErrorMessage, NULL,
JS_ReportErrorNumber(state->context, js_GetErrorMessage, NULL,
JSMSG_EMPTY_BEFORE_STAR);
return NULL;
}
@ -731,8 +726,7 @@ loop:
case '+':
if (!(ren->flags & RENODE_NONEMPTY)) {
JS_ReportErrorNumber(state->context,
js_GetErrorMessage, NULL,
JS_ReportErrorNumber(state->context, js_GetErrorMessage, NULL,
JSMSG_EMPTY_BEFORE_PLUS);
return NULL;
}
@ -815,8 +809,7 @@ ParseAtom(CompilerState *state)
return NULL;
cp = state->cp;
if (*cp != ')') {
JS_ReportErrorNumber(state->context,
js_GetErrorMessage, NULL,
JS_ReportErrorNumber(state->context, js_GetErrorMessage, NULL,
JSMSG_MISSING_PAREN, ocp);
return NULL;
}
@ -857,8 +850,7 @@ ParseAtom(CompilerState *state)
while ((c = *++cp) != ']') {
if (c == 0) {
bad_cclass:
JS_ReportErrorNumber(state->context,
js_GetErrorMessage, NULL,
JS_ReportErrorNumber(state->context, js_GetErrorMessage, NULL,
JSMSG_UNTERM_CLASS, ocp);
return NULL;
}
@ -875,8 +867,7 @@ ParseAtom(CompilerState *state)
c = *++cp;
switch (c) {
case 0:
JS_ReportErrorNumber(state->context,
js_GetErrorMessage, NULL,
JS_ReportErrorNumber(state->context, js_GetErrorMessage, NULL,
JSMSG_TRAILING_SLASH);
return NULL;

Просмотреть файл

@ -226,8 +226,8 @@ js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp)
} else {
file = fopen(filename, "r");
if (!file) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CANT_OPEN, filename, strerror(errno));
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN,
filename, strerror(errno));
return NULL;
}
}
@ -785,8 +785,7 @@ retry:
*/
if (c > '7' && JSVERSION_IS_ECMA(cx->version)) {
js_ReportCompileError(cx, ts, JSREPORT_WARNING,
"0%c is not an ECMA-legal numeric constant",
c);
"0%c is not a legal ECMA-262 numeric constant", c);
radix = 10;
} else {
radix = 8;

Просмотреть файл

@ -677,8 +677,6 @@ js_DestroyScript(JSContext *cx, JSScript *script)
JS_ClearScriptTraps(cx, script);
js_FreeAtomMap(cx, &script->atomMap);
if (js_InterpreterHooks && js_InterpreterHooks->destroyScript)
js_InterpreterHooks->destroyScript(cx, script);
JS_free(cx, (void *)script->filename);
JS_free(cx, script->notes);
JS_free(cx, script->trynotes);

Просмотреть файл

@ -53,7 +53,7 @@
/* Contributions from the String class to the set of methods defined for the
* global object. escape and unescape used to be defined in the Mocha library,
* but as ECMA decided to spec them. So they've been moved to the core engine
* but as ECMA decided to spec them, they've been moved to the core engine
* and made ECMA-compliant. (Incomplete escapes are interpreted as literal
* characters by unescape.)
*/
@ -110,7 +110,7 @@ str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH))
{
char numBuf[12];
sprintf(numBuf, "%x", mask);
PR_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) mask);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_STRING_MASK, numBuf);
return JS_FALSE;

Просмотреть файл

@ -20,6 +20,7 @@
#include <string.h>
#include "prtypes.h"
#include "prassert.h"
#include "prprintf.h"
#include "jsapi.h"
#include "jscntxt.h"
#include "jsobj.h" /* js_XDRObject */
@ -176,12 +177,12 @@ mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence)
return JS_TRUE;
default: {
char numBuf[12];
sprintf(numBuf, "%d", whence);
PR_snprintf(numBuf, sizeof numBuf, "%d", whence);
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
JSMSG_WHITHER_WHENCE, numBuf);
}
return JS_FALSE;
}
}
}
static uint32
@ -490,12 +491,12 @@ JS_XDRValue(JSXDRState *xdr, jsval *vp)
*vp = INT_TO_JSVAL(i);
break;
}
sprintf(numBuf, "%#lx", type);
PR_snprintf(numBuf, sizeof numBuf, "%#lx", type);
JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
JSMSG_BAD_JVAL_TYPE, type);
}
return JS_FALSE;
}
}
return JS_TRUE;
}