📄 jsopcode.c
字号:
return JS_FALSE; RETRACT(&ss->sprinter, rval); jp->indent += 2; js_printf(jp, "\tcase %s:\n", rval); } jp->indent += 2; if (off <= defaultOffset && defaultOffset < off2) { diff = defaultOffset - off; if (diff != 0) { if (!Decompile(ss, pc + off, diff)) return JS_FALSE; off = defaultOffset; } 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;}#endifstatic 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 JSBoolDecompile(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; static const char catch_cookie[] = "/*CATCH*/"; static const char with_cookie[] = "/*WITH*/";/* * 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/* * Callers know that ATOM_IS_STRING(atom), and we leave it to the optimizer to * common ATOM_TO_STRING(atom) here and near the call sites. */#define ATOM_IS_IDENTIFIER(atom) \ (!ATOM_KEYWORD(atom) && js_IsIdentifier(ATOM_TO_STRING(atom)))/* * 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_IS_IDENTIFIER(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_printf(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; todo = Sprint(&ss->sprinter, catch_cookie); 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*/";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -