1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/frontend/SourceNotes.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,172 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef frontend_SourceNotes_h 1.11 +#define frontend_SourceNotes_h 1.12 + 1.13 +#include <stdint.h> 1.14 + 1.15 +#include "jstypes.h" 1.16 + 1.17 +typedef uint8_t jssrcnote; 1.18 + 1.19 +namespace js { 1.20 + 1.21 +/* 1.22 + * Source notes generated along with bytecode for decompiling and debugging. 1.23 + * A source note is a uint8_t with 5 bits of type and 3 of offset from the pc 1.24 + * of the previous note. If 3 bits of offset aren't enough, extended delta 1.25 + * notes (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset 1.26 + * bits are emitted before the next note. Some notes have operand offsets 1.27 + * encoded immediately after them, in note bytes or byte-triples. 1.28 + * 1.29 + * Source Note Extended Delta 1.30 + * +7-6-5-4-3+2-1-0+ +7-6-5+4-3-2-1-0+ 1.31 + * |note-type|delta| |1 1| ext-delta | 1.32 + * +---------+-----+ +---+-----------+ 1.33 + * 1.34 + * At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE, 1.35 + * SRC_COLSPAN, SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode. 1.36 + * 1.37 + * NB: the js_SrcNoteSpec array in BytecodeEmitter.cpp is indexed by this 1.38 + * enum, so its initializers need to match the order here. 1.39 + * 1.40 + * Don't forget to update XDR_BYTECODE_VERSION in vm/Xdr.h for all such 1.41 + * incompatible source note or other bytecode changes. 1.42 + */ 1.43 +#define FOR_EACH_SRC_NOTE_TYPE(M) \ 1.44 + M(SRC_NULL, "null", 0) /* Terminates a note vector. */ \ 1.45 + M(SRC_IF, "if", 0) /* JSOP_IFEQ bytecode is from an if-then. */ \ 1.46 + M(SRC_IF_ELSE, "if-else", 1) /* JSOP_IFEQ bytecode is from an if-then-else. */ \ 1.47 + M(SRC_COND, "cond", 1) /* JSOP_IFEQ is from conditional ?: operator. */ \ 1.48 + M(SRC_FOR, "for", 3) /* JSOP_NOP or JSOP_POP in for(;;) loop head. */ \ 1.49 + M(SRC_WHILE, "while", 1) /* JSOP_GOTO to for or while loop condition from before \ 1.50 + loop, else JSOP_NOP at top of do-while loop. */ \ 1.51 + M(SRC_FOR_IN, "for-in", 1) /* JSOP_GOTO to for-in loop condition from before \ 1.52 + loop. */ \ 1.53 + M(SRC_FOR_OF, "for-of", 1) /* JSOP_GOTO to for-of loop condition from before \ 1.54 + loop. */ \ 1.55 + M(SRC_CONTINUE, "continue", 0) /* JSOP_GOTO is a continue. */ \ 1.56 + M(SRC_BREAK, "break", 0) /* JSOP_GOTO is a break. */ \ 1.57 + M(SRC_BREAK2LABEL, "break2label", 0) /* JSOP_GOTO for 'break label'. */ \ 1.58 + M(SRC_SWITCHBREAK, "switchbreak", 0) /* JSOP_GOTO is a break in a switch. */ \ 1.59 + M(SRC_TABLESWITCH, "tableswitch", 1) /* JSOP_TABLESWITCH; offset points to end of switch. */ \ 1.60 + M(SRC_CONDSWITCH, "condswitch", 2) /* JSOP_CONDSWITCH; 1st offset points to end of switch, \ 1.61 + 2nd points to first JSOP_CASE. */ \ 1.62 + M(SRC_NEXTCASE, "nextcase", 1) /* Distance forward from one CASE in a CONDSWITCH to \ 1.63 + the next. */ \ 1.64 + M(SRC_ASSIGNOP, "assignop", 0) /* += or another assign-op follows. */ \ 1.65 + M(SRC_TRY, "try", 1) /* JSOP_TRY, offset points to goto at the end of the \ 1.66 + try block. */ \ 1.67 + /* All notes below here are "gettable". See SN_IS_GETTABLE below. */ \ 1.68 + M(SRC_COLSPAN, "colspan", 1) /* Number of columns this opcode spans. */ \ 1.69 + M(SRC_NEWLINE, "newline", 0) /* Bytecode follows a source newline. */ \ 1.70 + M(SRC_SETLINE, "setline", 1) /* A file-absolute source line number note. */ \ 1.71 + M(SRC_UNUSED20, "unused20", 0) /* Unused. */ \ 1.72 + M(SRC_UNUSED21, "unused21", 0) /* Unused. */ \ 1.73 + M(SRC_UNUSED22, "unused22", 0) /* Unused. */ \ 1.74 + M(SRC_UNUSED23, "unused23", 0) /* Unused. */ \ 1.75 + M(SRC_XDELTA, "xdelta", 0) /* 24-31 are for extended delta notes. */ 1.76 + 1.77 +enum SrcNoteType { 1.78 +#define DEFINE_SRC_NOTE_TYPE(sym, name, arity) sym, 1.79 + FOR_EACH_SRC_NOTE_TYPE(DEFINE_SRC_NOTE_TYPE) 1.80 +#undef DEFINE_SRC_NOTE_TYPE 1.81 + 1.82 + SRC_LAST, 1.83 + SRC_LAST_GETTABLE = SRC_TRY 1.84 +}; 1.85 + 1.86 +static_assert(SRC_XDELTA == 24, "SRC_XDELTA should be 24"); 1.87 + 1.88 +/* A source note array is terminated by an all-zero element. */ 1.89 +inline void 1.90 +SN_MAKE_TERMINATOR(jssrcnote *sn) 1.91 +{ 1.92 + *sn = SRC_NULL; 1.93 +} 1.94 + 1.95 +inline bool 1.96 +SN_IS_TERMINATOR(jssrcnote *sn) 1.97 +{ 1.98 + return *sn == SRC_NULL; 1.99 +} 1.100 + 1.101 +} // namespace js 1.102 + 1.103 +#define SN_TYPE_BITS 5 1.104 +#define SN_DELTA_BITS 3 1.105 +#define SN_XDELTA_BITS 6 1.106 +#define SN_TYPE_MASK (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS) 1.107 +#define SN_DELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS)) 1.108 +#define SN_XDELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS)) 1.109 + 1.110 +#define SN_MAKE_NOTE(sn,t,d) (*(sn) = (jssrcnote) \ 1.111 + (((t) << SN_DELTA_BITS) \ 1.112 + | ((d) & SN_DELTA_MASK))) 1.113 +#define SN_MAKE_XDELTA(sn,d) (*(sn) = (jssrcnote) \ 1.114 + ((SRC_XDELTA << SN_DELTA_BITS) \ 1.115 + | ((d) & SN_XDELTA_MASK))) 1.116 + 1.117 +#define SN_IS_XDELTA(sn) ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA) 1.118 +#define SN_TYPE(sn) ((js::SrcNoteType)(SN_IS_XDELTA(sn) \ 1.119 + ? SRC_XDELTA \ 1.120 + : *(sn) >> SN_DELTA_BITS)) 1.121 +#define SN_SET_TYPE(sn,type) SN_MAKE_NOTE(sn, type, SN_DELTA(sn)) 1.122 +#define SN_IS_GETTABLE(sn) (SN_TYPE(sn) <= SRC_LAST_GETTABLE) 1.123 + 1.124 +#define SN_DELTA(sn) ((ptrdiff_t)(SN_IS_XDELTA(sn) \ 1.125 + ? *(sn) & SN_XDELTA_MASK \ 1.126 + : *(sn) & SN_DELTA_MASK)) 1.127 +#define SN_SET_DELTA(sn,delta) (SN_IS_XDELTA(sn) \ 1.128 + ? SN_MAKE_XDELTA(sn, delta) \ 1.129 + : SN_MAKE_NOTE(sn, SN_TYPE(sn), delta)) 1.130 + 1.131 +#define SN_DELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_DELTA_BITS)) 1.132 +#define SN_XDELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS)) 1.133 + 1.134 +/* 1.135 + * Offset fields follow certain notes and are frequency-encoded: an offset in 1.136 + * [0,0x7f] consumes one byte, an offset in [0x80,0x7fffffff] takes four, and 1.137 + * the high bit of the first byte is set. 1.138 + */ 1.139 +#define SN_4BYTE_OFFSET_FLAG 0x80 1.140 +#define SN_4BYTE_OFFSET_MASK 0x7f 1.141 + 1.142 +/* 1.143 + * Negative SRC_COLSPAN offsets are rare, but can arise with for(;;) loops and 1.144 + * other constructs that generate code in non-source order. They can also arise 1.145 + * due to failure to update pn->pn_pos.end to be the last child's end -- such 1.146 + * failures are bugs to fix. 1.147 + * 1.148 + * Source note offsets in general must be non-negative and less than 0x800000, 1.149 + * per the above SN_4BYTE_* definitions. To encode negative colspans, we bias 1.150 + * them by the offset domain size and restrict non-negative colspans to less 1.151 + * than half this domain. 1.152 + */ 1.153 +#define SN_COLSPAN_DOMAIN ptrdiff_t(1 << 23) 1.154 + 1.155 +#define SN_MAX_OFFSET ((size_t)((ptrdiff_t)SN_4BYTE_OFFSET_FLAG << 24) - 1) 1.156 + 1.157 +#define SN_LENGTH(sn) ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \ 1.158 + : js_SrcNoteLength(sn)) 1.159 +#define SN_NEXT(sn) ((sn) + SN_LENGTH(sn)) 1.160 + 1.161 +struct JSSrcNoteSpec { 1.162 + const char *name; /* name for disassembly/debugging output */ 1.163 + int8_t arity; /* number of offset operands */ 1.164 +}; 1.165 + 1.166 +extern JS_FRIEND_DATA(const JSSrcNoteSpec) js_SrcNoteSpec[]; 1.167 +extern JS_FRIEND_API(unsigned) js_SrcNoteLength(jssrcnote *sn); 1.168 + 1.169 +/* 1.170 + * Get and set the offset operand identified by which (0 for the first, etc.). 1.171 + */ 1.172 +extern JS_FRIEND_API(ptrdiff_t) 1.173 +js_GetSrcNoteOffset(jssrcnote *sn, unsigned which); 1.174 + 1.175 +#endif /* frontend_SourceNotes_h */