js/src/frontend/SourceNotes.h

changeset 0
6474c204b198
     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 */

mercurial