📄 jsopcode.c
字号:
todo = -2;
break;
}
case JSOP_SWAP:
/*
* We don't generate this opcode currently, and previously we
* did not need to decompile it. If old, serialized bytecode
* uses it still, we should fall through and set todo = -2.
*/
/* FALL THROUGH */
case JSOP_GOSUB:
case JSOP_GOSUBX:
/*
* JSOP_GOSUB and GOSUBX have no effect on the decompiler's
* string stack because the next op in bytecode order finds
* the stack balanced by a JSOP_RETSUB executed elsewhere.
*/
todo = -2;
break;
case JSOP_SETSP:
/*
* The compiler models operand stack depth and fixes the stack
* pointer on entry to a catch clause based on its depth model.
* The decompiler must match the code generator's model, which
* is why JSOP_FINALLY pushes a cookie that JSOP_RETSUB pops.
*/
ss->top = (uintN) GET_ATOM_INDEX(pc);
break;
case JSOP_EXCEPTION:
/*
* The only other JSOP_EXCEPTION case occurs as part of a code
* sequence that follows a SRC_CATCH-annotated JSOP_NOP.
*/
sn = js_GetSrcNote(jp->script, pc);
LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_HIDDEN);
todo = -2;
break;
#endif /* JS_HAS_EXCEPTIONS */
case JSOP_POP:
case JSOP_POPV:
sn = js_GetSrcNote(jp->script, pc);
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
case SRC_FOR:
rval = POP_STR();
todo = -2;
goto do_forloop;
case SRC_PCDELTA:
/* Pop and save to avoid blowing stack depth budget. */
lval = JS_strdup(cx, POP_STR());
if (!lval)
return JS_FALSE;
/*
* The offset tells distance to the end of the right-hand
* operand of the comma operator.
*/
done = pc + len;
pc += js_GetSrcNoteOffset(sn, 0);
len = 0;
if (!Decompile(ss, done, pc - done)) {
JS_free(cx, (char *)lval);
return JS_FALSE;
}
/* Pop Decompile result and print comma expression. */
rval = POP_STR();
todo = Sprint(&ss->sprinter, "%s, %s", lval, rval);
JS_free(cx, (char *)lval);
break;
case SRC_HIDDEN:
/* Hide this pop, it's from a goto in a with or for/in. */
todo = -2;
break;
default:
rval = POP_STR();
if (*rval != '\0')
js_printf(jp, "\t%s;\n", rval);
todo = -2;
break;
}
break;
case JSOP_POP2:
(void) PopOff(ss, op);
(void) PopOff(ss, op);
todo = -2;
break;
{
static const char with_cookie[] = "with-cookie";
case JSOP_ENTERWITH:
sn = js_GetSrcNote(jp->script, pc);
if (sn && SN_TYPE(sn) == SRC_HIDDEN) {
todo = -2;
break;
}
rval = POP_STR();
js_printf(jp, "\twith (%s) {\n", rval);
jp->indent += 4;
todo = Sprint(&ss->sprinter, with_cookie);
break;
case JSOP_LEAVEWITH:
sn = js_GetSrcNote(jp->script, pc);
todo = -2;
if (sn && SN_TYPE(sn) == SRC_HIDDEN)
break;
rval = POP_STR();
LOCAL_ASSERT(strcmp(rval, with_cookie) == 0);
jp->indent -= 4;
js_printf(jp, "\t}\n");
break;
}
case JSOP_SETRVAL:
case JSOP_RETURN:
rval = POP_STR();
if (*rval != '\0')
js_printf(jp, "\t%s %s;\n", cs->name, rval);
else
js_printf(jp, "\t%s;\n", cs->name);
todo = -2;
break;
#if JS_HAS_EXCEPTIONS
case JSOP_THROW:
sn = js_GetSrcNote(jp->script, pc);
todo = -2;
if (sn && SN_TYPE(sn) == SRC_HIDDEN)
break;
rval = POP_STR();
js_printf(jp, "\t%s %s;\n", cs->name, rval);
break;
#endif /* JS_HAS_EXCEPTIONS */
case JSOP_GOTO:
case JSOP_GOTOX:
sn = js_GetSrcNote(jp->script, pc);
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
case SRC_CONT2LABEL:
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, "\tcontinue %s;\n", rval);
break;
case SRC_CONTINUE:
js_printf(jp, "\tcontinue;\n");
break;
case SRC_BREAK2LABEL:
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, "\tbreak %s;\n", rval);
break;
case SRC_HIDDEN:
break;
default:
js_printf(jp, "\tbreak;\n");
break;
}
todo = -2;
break;
case JSOP_IFEQ:
case JSOP_IFEQX:
len = GetJumpOffset(pc, pc);
sn = js_GetSrcNote(jp->script, pc);
switch (sn ? SN_TYPE(sn) : SRC_NULL) {
case SRC_IF:
case SRC_IF_ELSE:
rval = POP_STR();
js_printf(jp, "\tif (%s) {\n", rval);
jp->indent += 4;
if (SN_TYPE(sn) == SRC_IF) {
DECOMPILE_CODE(pc + oplen, len - oplen);
} else {
len = js_GetSrcNoteOffset(sn, 0);
DECOMPILE_CODE(pc + oplen, len - oplen);
jp->indent -= 4;
pc += len;
LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
oplen = js_CodeSpec[*pc].length;
len = GetJumpOffset(pc, pc);
js_printf(jp, "\t} else {\n");
jp->indent += 4;
DECOMPILE_CODE(pc + oplen, len - oplen);
}
jp->indent -= 4;
js_printf(jp, "\t}\n");
todo = -2;
break;
case SRC_WHILE:
rval = POP_STR();
js_printf(jp, "\twhile (%s) {\n", rval);
jp->indent += 4;
tail = js_GetSrcNoteOffset(sn, 0);
DECOMPILE_CODE(pc + oplen, tail - oplen);
jp->indent -= 4;
js_printf(jp, "\t}\n");
todo = -2;
break;
case SRC_COND:
xval = JS_strdup(cx, POP_STR());
if (!xval)
return JS_FALSE;
len = js_GetSrcNoteOffset(sn, 0);
DECOMPILE_CODE(pc + oplen, len - oplen);
lval = JS_strdup(cx, POP_STR());
if (!lval) {
JS_free(cx, (void *)xval);
return JS_FALSE;
}
pc += len;
LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
oplen = js_CodeSpec[*pc].length;
len = GetJumpOffset(pc, pc);
DECOMPILE_CODE(pc + oplen, len - oplen);
rval = POP_STR();
todo = Sprint(&ss->sprinter, "%s ? %s : %s",
xval, lval, rval);
JS_free(cx, (void *)xval);
JS_free(cx, (void *)lval);
break;
default:
break;
}
break;
case JSOP_IFNE:
case JSOP_IFNEX:
#if JS_HAS_DO_WHILE_LOOP
/* Currently, this must be a do-while loop's upward branch. */
jp->indent -= 4;
js_printf(jp, "\t} while (%s);\n", POP_STR());
todo = -2;
#else
JS_ASSERT(0);
#endif /* JS_HAS_DO_WHILE_LOOP */
break;
case JSOP_OR:
case JSOP_ORX:
xval = "||";
do_logical_connective:
/* Top of stack is the first clause in a disjunction (||). */
lval = JS_strdup(cx, POP_STR());
if (!lval)
return JS_FALSE;
done = pc + GetJumpOffset(pc, pc);
pc += len;
len = PTRDIFF(done, pc, jsbytecode);
DECOMPILE_CODE(pc, len);
rval = POP_STR();
if (jp->pretty &&
jp->indent + 4 + strlen(lval) + 4 + strlen(rval) > 75) {
rval = JS_strdup(cx, rval);
if (!rval) {
tail = -1;
} else {
todo = Sprint(&ss->sprinter, "%s %s\n", lval, xval);
tail = Sprint(&ss->sprinter, "%*s%s",
jp->indent + 4, "", rval);
JS_free(cx, (char *)rval);
}
if (tail < 0)
todo = -1;
} else {
todo = Sprint(&ss->sprinter, "%s %s %s", lval, xval, rval);
}
JS_free(cx, (char *)lval);
break;
case JSOP_AND:
case JSOP_ANDX:
xval = "&&";
goto do_logical_connective;
case JSOP_FORARG:
atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));
LOCAL_ASSERT(atom);
goto do_fornameinloop;
case JSOP_FORVAR:
atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));
LOCAL_ASSERT(atom);
goto do_fornameinloop;
case JSOP_FORNAME:
atom = GET_ATOM(cx, jp->script, pc);
do_fornameinloop:
sn = js_GetSrcNote(jp->script, pc);
xval = NULL;
lval = "";
goto do_forinloop;
case JSOP_FORPROP:
xval = NULL;
atom = GET_ATOM(cx, jp->script, pc);
if (ATOM_KEYWORD(atom)) {
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
(jschar)'\'');
if (!xval)
return JS_FALSE;
atom = NULL;
}
lval = POP_STR();
sn = NULL;
do_forinloop:
pc += oplen;
LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
oplen = js_CodeSpec[*pc].length;
len = GetJumpOffset(pc, pc);
sn2 = js_GetSrcNote(jp->script, pc);
tail = js_GetSrcNoteOffset(sn2, 0);
do_forinbody:
js_printf(jp, "\tfor (%s%s", VarPrefix(sn), lval);
if (atom) {
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!xval)
return JS_FALSE;
RETRACT(&ss->sprinter, xval);
js_printf(jp, *lval ? ".%s" : "%s", xval);
} else if (xval) {
js_printf(jp, "[%s]", xval);
}
rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]);
js_printf(jp, " in %s) {\n", rval);
jp->indent += 4;
DECOMPILE_CODE(pc + oplen, tail - oplen);
jp->indent -= 4;
js_printf(jp, "\t}\n");
todo = -2;
break;
case JSOP_FORELEM:
pc++;
LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
len = js_CodeSpec[*pc].length;
/*
* Arrange for the JSOP_ENUMELEM case to set tail for use by
* do_forinbody: code that uses on it to find the loop-closing
* jump (whatever its format, normal or extended), in order to
* bound the recursively decompiled loop body.
*/
sn = js_GetSrcNote(jp->script, pc);
JS_ASSERT(!forelem_tail);
forelem_tail = pc + js_GetSrcNoteOffset(sn, 0);
/*
* This gets a little wacky. Only the length of the for loop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -