📄 jsopcode.c
字号:
}
jp->indent -= 2;
js_printf(jp, "\tdefault:\n");
jp->indent += 2;
}
if (!Decompile(ss, pc + off, off2 - off))
return JS_FALSE;
jp->indent -= 4;
}
}
if (defaultOffset == switchLength) {
jp->indent += 2;
js_printf(jp, "\tdefault:\n");
jp->indent -= 2;
}
js_printf(jp, "\t}\n");
return JS_TRUE;
}
#endif
static JSAtom *
GetSlotAtom(JSPrinter *jp, JSPropertyOp getter, uintN slot)
{
JSScope *scope;
JSScopeProperty *sprop;
JSObject *obj, *proto;
scope = jp->scope;
while (scope) {
for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
if (sprop->getter != getter)
continue;
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
JS_ASSERT(!JSVAL_IS_INT(sprop->id));
if ((uintN) sprop->shortid == slot)
return (JSAtom *) sprop->id;
}
obj = scope->object;
if (!obj)
break;
proto = OBJ_GET_PROTO(jp->sprinter.context, obj);
if (!proto)
break;
scope = OBJ_SCOPE(proto);
}
return NULL;
}
static const char *
VarPrefix(jssrcnote *sn)
{
const char *kw;
static char buf[8];
kw = NULL;
if (sn) {
if (SN_TYPE(sn) == SRC_VAR)
kw = js_var_str;
else if (SN_TYPE(sn) == SRC_CONST)
kw = js_const_str;
}
if (!kw)
return "";
JS_snprintf(buf, sizeof buf, "%s ", kw);
return buf;
}
static JSBool
Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
{
JSContext *cx;
JSPrinter *jp, *jp2;
jsbytecode *endpc, *done, *forelem_tail, *forelem_done;
ptrdiff_t len, todo, oplen, cond, next, tail;
JSOp op, lastop, saveop;
const JSCodeSpec *cs, *topcs;
jssrcnote *sn, *sn2;
const char *lval, *rval, *xval, *fmt;
jsint i, argc;
char **argv;
JSAtom *atom;
JSObject *obj;
JSFunction *fun;
JSString *str;
JSBool ok;
jsval val;
/*
* Local macros
*/
#define DECOMPILE_CODE(pc,nb) if (!Decompile(ss, pc, nb)) return JS_FALSE
#define POP_STR() OFF2STR(&ss->sprinter, PopOff(ss, op))
#define LOCAL_ASSERT(expr) JS_ASSERT(expr); if (!(expr)) return JS_FALSE
/*
* Get atom from script's atom map, quote/escape its string appropriately into
* rval, and select fmt from the quoted and unquoted alternatives.
*/
#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval) \
JS_BEGIN_MACRO \
jschar quote_; \
atom = GET_ATOM(cx, jp->script, pc); \
if (ATOM_KEYWORD(atom)) { \
quote_ = '\''; \
fmt = qfmt; \
} else { \
quote_ = 0; \
fmt = ufmt; \
} \
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), quote_); \
if (!rval) \
return JS_FALSE; \
JS_END_MACRO
cx = ss->sprinter.context;
jp = ss->printer;
endpc = pc + nb;
forelem_tail = forelem_done = NULL;
todo = -2; /* NB: different from Sprint() error return. */
tail = -1;
op = JSOP_NOP;
sn = NULL;
rval = NULL;
while (pc < endpc) {
lastop = op;
op = saveop = (JSOp) *pc;
if (op >= JSOP_LIMIT) {
switch (op) {
case JSOP_GETPROP2:
saveop = JSOP_GETPROP;
break;
case JSOP_GETELEM2:
saveop = JSOP_GETELEM;
break;
default:;
}
}
cs = &js_CodeSpec[saveop];
len = oplen = cs->length;
if (cs->token) {
switch (cs->nuses) {
case 2:
rval = POP_STR();
lval = POP_STR();
sn = js_GetSrcNote(jp->script, pc);
if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
/* Print only the right operand of the assignment-op. */
todo = SprintPut(&ss->sprinter, rval, strlen(rval));
} else {
todo = Sprint(&ss->sprinter, "%s %s %s",
lval, cs->token, rval);
}
break;
case 1:
rval = POP_STR();
todo = Sprint(&ss->sprinter, "%s%s", cs->token, rval);
break;
case 0:
#if JS_HAS_GETTER_SETTER
if (op == JSOP_GETTER || op == JSOP_SETTER) {
todo = -2;
break;
}
#endif
todo = SprintPut(&ss->sprinter, cs->token, strlen(cs->token));
break;
default:
todo = -2;
break;
}
} else {
switch (op) {
case JSOP_NOP:
/*
* Check for a do-while loop, a for-loop with an empty
* initializer part, a labeled statement, a function
* definition, or try/finally.
*/
sn = js_GetSrcNote(jp->script, pc);
todo = -2;
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
#if JS_HAS_DO_WHILE_LOOP
case SRC_WHILE:
js_printf(jp, "\tdo {\n");
jp->indent += 4;
break;
#endif /* JS_HAS_DO_WHILE_LOOP */
case SRC_FOR:
rval = "";
do_forloop:
/* Skip the JSOP_NOP or JSOP_POP bytecode. */
pc++;
/* Get the cond, next, and loop-closing tail offsets. */
cond = js_GetSrcNoteOffset(sn, 0);
next = js_GetSrcNoteOffset(sn, 1);
tail = js_GetSrcNoteOffset(sn, 2);
LOCAL_ASSERT(tail + GetJumpOffset(pc+tail, pc+tail) == 0);
/* Print the keyword and the possibly empty init-part. */
js_printf(jp, "\tfor (%s;", rval);
if (pc[cond] == JSOP_IFEQ || pc[cond] == JSOP_IFEQX) {
/* Decompile the loop condition. */
DECOMPILE_CODE(pc, cond);
js_printf(jp, " %s", POP_STR());
}
/* Need a semicolon whether or not there was a cond. */
js_puts(jp, ";");
if (pc[next] != JSOP_GOTO && pc[next] != JSOP_GOTOX) {
/* Decompile the loop updater. */
DECOMPILE_CODE(pc + next, tail - next - 1);
js_printf(jp, " %s", POP_STR());
}
/* Do the loop body. */
js_puts(jp, ") {\n");
jp->indent += 4;
oplen = (cond) ? js_CodeSpec[pc[cond]].length : 0;
DECOMPILE_CODE(pc + cond + oplen, next - cond - oplen);
jp->indent -= 4;
js_printf(jp, "\t}\n");
/* Set len so pc skips over the entire loop. */
len = tail + js_CodeSpec[pc[tail]].length;
break;
case SRC_LABEL:
atom = js_GetAtom(cx, &jp->script->atomMap,
(jsatomid) js_GetSrcNoteOffset(sn, 0));
jp->indent -= 4;
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!rval)
return JS_FALSE;
RETRACT(&ss->sprinter, rval);
js_printf(jp, "\t%s:\n", rval);
jp->indent += 4;
break;
case SRC_LABELBRACE:
atom = js_GetAtom(cx, &jp->script->atomMap,
(jsatomid) js_GetSrcNoteOffset(sn, 0));
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!rval)
return JS_FALSE;
RETRACT(&ss->sprinter, rval);
js_printf(jp, "\t%s: {\n", rval);
jp->indent += 4;
break;
case SRC_ENDBRACE:
jp->indent -= 4;
js_printf(jp, "\t}\n");
break;
case SRC_CATCH:
jp->indent -= 4;
sn = js_GetSrcNote(jp->script, pc);
pc += oplen;
js_printf(jp, "\t} catch (");
LOCAL_ASSERT(*pc == JSOP_NAME);
pc += js_CodeSpec[JSOP_NAME].length;
LOCAL_ASSERT(*pc == JSOP_PUSHOBJ);
pc += js_CodeSpec[JSOP_PUSHOBJ].length;
LOCAL_ASSERT(*pc == JSOP_NEWINIT);
pc += js_CodeSpec[JSOP_NEWINIT].length;
LOCAL_ASSERT(*pc == JSOP_EXCEPTION);
pc += js_CodeSpec[JSOP_EXCEPTION].length;
LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
atom = GET_ATOM(cx, jp->script, pc);
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!rval)
return JS_FALSE;
RETRACT(&ss->sprinter, rval);
js_printf(jp, "%s", rval);
pc += js_CodeSpec[JSOP_INITCATCHVAR].length;
LOCAL_ASSERT(*pc == JSOP_ENTERWITH);
pc += js_CodeSpec[JSOP_ENTERWITH].length;
len = js_GetSrcNoteOffset(sn, 0);
if (len) {
js_printf(jp, " if ");
DECOMPILE_CODE(pc, len);
js_printf(jp, "%s", POP_STR());
pc += len;
LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
pc += js_CodeSpec[*pc].length;
}
js_printf(jp, ") {\n");
jp->indent += 4;
len = 0;
break;
case SRC_FUNCDEF:
atom = js_GetAtom(cx, &jp->script->atomMap,
(jsatomid) js_GetSrcNoteOffset(sn, 0));
JS_ASSERT(ATOM_IS_OBJECT(atom));
do_function:
obj = ATOM_TO_OBJECT(atom);
fun = (JSFunction *) JS_GetPrivate(cx, obj);
jp2 = js_NewPrinter(cx, JS_GetFunctionName(fun),
jp->indent, jp->pretty);
if (!jp2)
return JS_FALSE;
jp2->scope = jp->scope;
if (js_DecompileFunction(jp2, fun)) {
str = js_GetPrinterOutput(jp2);
if (str)
js_printf(jp, "%s\n", JS_GetStringBytes(str));
}
js_DestroyPrinter(jp2);
break;
default:;
}
case JSOP_RETRVAL:
break;
case JSOP_GROUP:
/* Use last real op so PopOff adds parens if needed. */
todo = PopOff(ss, lastop);
/* Now add user-supplied parens only if PopOff did not. */
cs = &js_CodeSpec[lastop];
topcs = &js_CodeSpec[ss->opcodes[ss->top]];
if (topcs->prec >= cs->prec) {
todo = Sprint(&ss->sprinter, "(%s)",
OFF2STR(&ss->sprinter, todo));
}
break;
case JSOP_PUSH:
case JSOP_PUSHOBJ:
case JSOP_BINDNAME:
todo = Sprint(&ss->sprinter, "");
break;
#if JS_HAS_EXCEPTIONS
case JSOP_TRY:
js_printf(jp, "\ttry {\n");
jp->indent += 4;
todo = -2;
break;
{
static const char finally_cookie[] = "finally-cookie";
case JSOP_FINALLY:
jp->indent -= 4;
js_printf(jp, "\t} finally {\n");
jp->indent += 4;
/*
* We must push an empty string placeholder for gosub's return
* address, popped by JSOP_RETSUB and counted by script->depth
* but not by ss->top (see JSOP_SETSP, below).
*/
todo = Sprint(&ss->sprinter, finally_cookie);
break;
case JSOP_RETSUB:
rval = POP_STR();
LOCAL_ASSERT(strcmp(rval, finally_cookie) == 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -