📄 jsemit.h
字号:
* A source note is a uint8 with 5 bits of type and 3 of offset from the pc of * 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 * immediately after them, in note bytes or byte-triples. * * Source Note Extended Delta * +7-6-5-4-3+2-1-0+ +7-6-5+4-3-2-1-0+ * |note-type|delta| |1 1| ext-delta | * +---------+-----+ +---+-----------+ * * 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. * * NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its * initializers need to match the order here. * * Note on adding new source notes: every pair of bytecodes (A, B) where A and * B have disjoint sets of source notes that could apply to each bytecode may * reuse the same note type value for two notes (snA, snB) that have the same * arity, offsetBias, and isSpanDep initializers in js_SrcNoteSpec. This is * why SRC_IF and SRC_INITPROP have the same value below. For bad historical * reasons, some bytecodes below that could be overlayed have not been, but * before using SRC_EXTENDED, consider compressing the existing note types. * * Don't forget to update JSXDR_BYTECODE_VERSION in jsxdrapi.h for all such * incompatible source note or other bytecode changes. */typedef enum JSSrcNoteType { SRC_NULL = 0, /* terminates a note vector */ SRC_IF = 1, /* JSOP_IFEQ bytecode is from an if-then */ SRC_INITPROP = 1, /* disjoint meaning applied to JSOP_INITELEM or to an index label in a regular (structuring) or a destructuring object initialiser */ SRC_IF_ELSE = 2, /* JSOP_IFEQ bytecode is from an if-then-else */ SRC_WHILE = 3, /* JSOP_IFEQ is from a while loop */ SRC_FOR = 4, /* JSOP_NOP or JSOP_POP in for loop head */ SRC_CONTINUE = 5, /* JSOP_GOTO is a continue, not a break; also used on JSOP_ENDINIT if extra comma at end of array literal: [1,2,,] */ SRC_DECL = 6, /* type of a declaration (var, const, let*) */ SRC_DESTRUCT = 6, /* JSOP_DUP starting a destructuring assignment operation, with SRC_DECL_* offset operand */ SRC_PCDELTA = 7, /* distance forward from comma-operator to next POP, or from CONDSWITCH to first CASE opcode, etc. -- always a forward delta */ SRC_GROUPASSIGN = 7, /* SRC_DESTRUCT variant for [a, b] = [c, d] */ SRC_ASSIGNOP = 8, /* += or another assign-op follows */ SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */ SRC_BRACE = 10, /* mandatory brace, for scope or to avoid dangling else */ SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */ SRC_PCBASE = 12, /* distance back from annotated getprop or setprop op to left-most obj.prop.subprop bytecode -- always a backward delta */ SRC_METHODBASE = 13, /* SRC_PCBASE variant for obj.function::foo gets and sets; disjoint from SRC_LABEL by bytecode to which it applies */ SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */ SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */ 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, 2nd off to first JSOP_CASE if condswitch */ SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */ SRC_CATCH = 20, /* catch block has guard */ SRC_EXTENDED = 21, /* extended source note, 32-159, in next byte */ SRC_NEWLINE = 22, /* bytecode follows a source newline */ SRC_SETLINE = 23, /* a file-absolute source line number note */ SRC_XDELTA = 24 /* 24-31 are for extended delta notes */} JSSrcNoteType;/* * Constants for the SRC_DECL source note. Note that span-dependent bytecode * selection means that any SRC_DECL offset greater than SRC_DECL_LET may need * to be adjusted, but these "offsets" are too small to span a span-dependent * instruction, so can be used to denote distinct declaration syntaxes to the * decompiler. * * NB: the var_prefix array in jsopcode.c depends on these dense indexes from * SRC_DECL_VAR through SRC_DECL_LET. */#define SRC_DECL_VAR 0#define SRC_DECL_CONST 1#define SRC_DECL_LET 2#define SRC_DECL_NONE 3#define SN_TYPE_BITS 5#define SN_DELTA_BITS 3#define SN_XDELTA_BITS 6#define SN_TYPE_MASK (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS)#define SN_DELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS))#define SN_XDELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS))#define SN_MAKE_NOTE(sn,t,d) (*(sn) = (jssrcnote) \ (((t) << SN_DELTA_BITS) \ | ((d) & SN_DELTA_MASK)))#define SN_MAKE_XDELTA(sn,d) (*(sn) = (jssrcnote) \ ((SRC_XDELTA << SN_DELTA_BITS) \ | ((d) & SN_XDELTA_MASK)))#define SN_IS_XDELTA(sn) ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA)#define SN_TYPE(sn) (SN_IS_XDELTA(sn) ? SRC_XDELTA \ : *(sn) >> SN_DELTA_BITS)#define SN_SET_TYPE(sn,type) SN_MAKE_NOTE(sn, type, SN_DELTA(sn))#define SN_IS_GETTABLE(sn) (SN_TYPE(sn) < SRC_NEWLINE)#define SN_DELTA(sn) ((ptrdiff_t)(SN_IS_XDELTA(sn) \ ? *(sn) & SN_XDELTA_MASK \ : *(sn) & SN_DELTA_MASK))#define SN_SET_DELTA(sn,delta) (SN_IS_XDELTA(sn) \ ? SN_MAKE_XDELTA(sn, delta) \ : SN_MAKE_NOTE(sn, SN_TYPE(sn), delta))#define SN_DELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_DELTA_BITS))#define SN_XDELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS))/* * Offset fields follow certain notes and are frequency-encoded: an offset in * [0,0x7f] consumes one byte, an offset in [0x80,0x7fffff] takes three, and * the high bit of the first byte is set. */#define SN_3BYTE_OFFSET_FLAG 0x80#define SN_3BYTE_OFFSET_MASK 0x7ftypedef struct JSSrcNoteSpec { const char *name; /* name for disassembly/debugging output */ uint8 arity; /* number of offset operands */ uint8 offsetBias; /* bias of offset(s) from annotated pc */ int8 isSpanDep; /* 1 or -1 if offsets could span extended ops, 0 otherwise; sign tells span direction */} JSSrcNoteSpec;extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[];extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn);#define SN_LENGTH(sn) ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \ : js_SrcNoteLength(sn))#define SN_NEXT(sn) ((sn) + SN_LENGTH(sn))/* A source note array is terminated by an all-zero element. */#define SN_MAKE_TERMINATOR(sn) (*(sn) = SRC_NULL)#define SN_IS_TERMINATOR(sn) (*(sn) == SRC_NULL)/* * Append a new source note of the given type (and therefore size) to cg's * notes dynamic array, updating cg->noteCount. Return the new note's index * within the array pointed at by cg->current->notes. Return -1 if out of * memory. */extern intNjs_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type);extern intNjs_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, ptrdiff_t offset);extern intNjs_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, ptrdiff_t offset1, ptrdiff_t offset2);/* * NB: this function can add at most one extra extended delta note. */extern jssrcnote *js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn, ptrdiff_t delta);/* * Get and set the offset operand identified by which (0 for the first, etc.). */extern JS_FRIEND_API(ptrdiff_t)js_GetSrcNoteOffset(jssrcnote *sn, uintN which);extern JSBooljs_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index, uintN which, ptrdiff_t offset);/* * Finish taking source notes in cx's notePool, copying final notes to the new * stable store allocated by the caller and passed in via notes. Return false * on malloc failure, which means this function reported an error. * * To compute the number of jssrcnotes to allocate and pass in via notes, use * the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of * js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes * FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES! */#define CG_COUNT_FINAL_SRCNOTES(cg, cnt) \ JS_BEGIN_MACRO \ ptrdiff_t diff_ = CG_PROLOG_OFFSET(cg) - (cg)->prolog.lastNoteOffset; \ cnt = (cg)->prolog.noteCount + (cg)->main.noteCount + 1; \ if ((cg)->prolog.noteCount && \ (cg)->prolog.currentLine != (cg)->firstLine) { \ if (diff_ > SN_DELTA_MASK) \ cnt += JS_HOWMANY(diff_ - SN_DELTA_MASK, SN_XDELTA_MASK); \ cnt += 2 + (((cg)->firstLine > SN_3BYTE_OFFSET_MASK) << 1); \ } else if (diff_ > 0) { \ if (cg->main.noteCount) { \ jssrcnote *sn_ = (cg)->main.notes; \ diff_ -= SN_IS_XDELTA(sn_) \ ? SN_XDELTA_MASK - (*sn_ & SN_XDELTA_MASK) \ : SN_DELTA_MASK - (*sn_ & SN_DELTA_MASK); \ } \ if (diff_ > 0) \ cnt += JS_HOWMANY(diff_, SN_XDELTA_MASK); \ } \ JS_END_MACROextern JSBooljs_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes);/* * Allocate cg->treeContext.tryCount notes (plus one for the end sentinel) * from cx->tempPool and set up cg->tryBase/tryNext for exactly tryCount * js_NewTryNote calls. The storage is freed by js_FinishCodeGenerator. */extern JSBooljs_AllocTryNotes(JSContext *cx, JSCodeGenerator *cg);/* * Grab the next trynote slot in cg, filling it in appropriately. */extern JSTryNote *js_NewTryNote(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t start, ptrdiff_t end, ptrdiff_t catchStart);/* * Finish generating exception information into the space at notes. As with * js_FinishTakingSrcNotes, the caller must use CG_COUNT_FINAL_TRYNOTES(cg) to * preallocate enough space in a JSTryNote[] to pass as the notes parameter of * js_FinishTakingTryNotes. */#define CG_COUNT_FINAL_TRYNOTES(cg, cnt) \ JS_BEGIN_MACRO \ cnt = ((cg)->tryNext > (cg)->tryBase) \ ? PTRDIFF(cg->tryNext, cg->tryBase, JSTryNote) + 1 \ : 0; \ JS_END_MACROextern voidjs_FinishTakingTryNotes(JSContext *cx, JSCodeGenerator *cg, JSTryNote *notes);JS_END_EXTERN_C#endif /* jsemit_h___ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -