📄 jsopcode.c
字号:
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); 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. */ LOCAL_ASSERT(ss->top >= (uintN) GET_ATOM_INDEX(pc)); 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; case JSOP_ENTERWITH: JS_ASSERT(!js_GetSrcNote(jp->script, pc)); 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(); if (sn && SN_TYPE(sn) == SRC_CATCH) { LOCAL_ASSERT(strcmp(rval, catch_cookie) == 0); LOCAL_ASSERT((uintN) js_GetSrcNoteOffset(sn, 0) == ss->top); break; } LOCAL_ASSERT(strcmp(rval, with_cookie) == 0); jp->indent -= 4; js_printf(jp, "\t}\n"); break; case JSOP_SETRVAL: case JSOP_RETURN: lval = js_CodeSpec[JSOP_RETURN].name; rval = POP_STR(); if (*rval != '\0') js_printf(jp, "\t%s %s;\n", lval, rval); else js_printf(jp, "\t%s;\n", lval); 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_IS_IDENTIFIER(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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -