Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions | Variables
jsopcode.h File Reference
#include <stddef.h>
#include "jsprvtd.h"
#include "jspubtd.h"
#include "jsutil.h"
#include "jsopcode.tbl"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  JSCodeSpec

Defines

#define OPDEF(op, val, name, token, length, nuses, ndefs, prec, format)   op = val,
#define OPDEF(op, val, name, token, length, nuses, ndefs, prec, format)   op##_LENGTH = length,
#define JOF_BYTE   0 /* single bytecode, no immediates */
#define JOF_JUMP   1 /* signed 16-bit jump offset immediate */
#define JOF_CONST   2 /* unsigned 16-bit constant pool index */
#define JOF_UINT16   3 /* unsigned 16-bit immediate operand */
#define JOF_TABLESWITCH   4 /* table switch */
#define JOF_LOOKUPSWITCH   5 /* lookup switch */
#define JOF_QARG   6 /* quickened get/set function argument ops */
#define JOF_QVAR   7 /* quickened get/set local variable ops */
#define JOF_INDEXCONST   8 /* uint16 slot index + constant pool index */
#define JOF_JUMPX   9 /* signed 32-bit jump offset immediate */
#define JOF_TABLESWITCHX   10 /* extended (32-bit offset) table switch */
#define JOF_LOOKUPSWITCHX   11 /* extended (32-bit offset) lookup switch */
#define JOF_UINT24   12 /* extended unsigned 24-bit literal (index) */
#define JOF_LITOPX
#define JOF_LOCAL   14 /* block-local operand stack variable */
#define JOF_TYPEMASK   0x000f /* mask for above immediate types */
#define JOF_NAME   0x0010 /* name operation */
#define JOF_PROP   0x0020 /* obj.prop operation */
#define JOF_ELEM   0x0030 /* obj[index] operation */
#define JOF_MODEMASK   0x0030 /* mask for above addressing modes */
#define JOF_SET   0x0040 /* set (i.e., assignment) operation */
#define JOF_DEL   0x0080 /* delete operation */
#define JOF_DEC   0x0100 /* decrement (--, not ++) opcode */
#define JOF_INC   0x0200 /* increment (++, not --) opcode */
#define JOF_INCDEC   0x0300 /* increment or decrement opcode */
#define JOF_POST   0x0400 /* postorder increment or decrement */
#define JOF_IMPORT   0x0800 /* import property op */
#define JOF_FOR   0x1000 /* for-in property op */
#define JOF_ASSIGNING
#define JOF_DETECTING   0x2000 /* object detection flag for JSNewResolveOp */
#define JOF_BACKPATCH   0x4000 /* backpatch placeholder during codegen */
#define JOF_LEFTASSOC   0x8000 /* left-associative operator */
#define JOF_DECLARING   0x10000 /* var, const, or function declaration op */
#define JOF_XMLNAME   0x20000 /* XML name: *, a::b, @a, @a::b, etc. */
#define JOF_TYPE_IS_EXTENDED_JUMP(t)   ((unsigned)((t) - JOF_JUMPX) <= (unsigned)(JOF_LOOKUPSWITCHX - JOF_JUMPX))
#define JUMP_OFFSET_LEN   2
#define JUMP_OFFSET_HI(off)   ((jsbytecode)((off) >> 8))
#define JUMP_OFFSET_LO(off)   ((jsbytecode)(off))
#define GET_JUMP_OFFSET(pc)   ((int16)(((pc)[1] << 8) | (pc)[2]))
#define SET_JUMP_OFFSET(pc, off)
#define JUMP_OFFSET_MIN   ((int16)0x8000)
#define JUMP_OFFSET_MAX   ((int16)0x7fff)
#define GET_SPANDEP_INDEX(pc)   ((uint16)(((pc)[1] << 8) | (pc)[2]))
#define SET_SPANDEP_INDEX(pc, i)
#define SPANDEP_INDEX_MAX   ((uint16)0xfffe)
#define SPANDEP_INDEX_HUGE   ((uint16)0xffff)
#define JUMPX_OFFSET_LEN   4
#define JUMPX_OFFSET_B3(off)   ((jsbytecode)((off) >> 24))
#define JUMPX_OFFSET_B2(off)   ((jsbytecode)((off) >> 16))
#define JUMPX_OFFSET_B1(off)   ((jsbytecode)((off) >> 8))
#define JUMPX_OFFSET_B0(off)   ((jsbytecode)(off))
#define GET_JUMPX_OFFSET(pc)
#define SET_JUMPX_OFFSET(pc, off)
#define JUMPX_OFFSET_MIN   ((int32)0x80000000)
#define JUMPX_OFFSET_MAX   ((int32)0x7fffffff)
#define ATOM_INDEX_LEN   2
#define ATOM_INDEX_HI(i)   ((jsbytecode)((i) >> 8))
#define ATOM_INDEX_LO(i)   ((jsbytecode)(i))
#define GET_ATOM_INDEX(pc)   ((jsatomid)(((pc)[1] << 8) | (pc)[2]))
#define SET_ATOM_INDEX(pc, i)
#define GET_ATOM(cx, script, pc)
#define UINT24_HI(i)   ((jsbytecode)((i) >> 16))
#define UINT24_MID(i)   ((jsbytecode)((i) >> 8))
#define UINT24_LO(i)   ((jsbytecode)(i))
#define GET_UINT24(pc)
#define SET_UINT24(pc, i)
#define LITERAL_INDEX_LEN   3
#define LITERAL_INDEX_HI(i)   UINT24_HI(i)
#define LITERAL_INDEX_MID(i)   UINT24_MID(i)
#define LITERAL_INDEX_LO(i)   UINT24_LO(i)
#define GET_LITERAL_INDEX(pc)   GET_UINT24(pc)
#define SET_LITERAL_INDEX(pc, i)   SET_UINT24(pc,i)
#define ATOM_INDEX_LIMIT_LOG2   23
#define ATOM_INDEX_LIMIT   ((uint32)1 << ATOM_INDEX_LIMIT_LOG2)
#define UINT16_HI(i)   ((jsbytecode)((i) >> 8))
#define UINT16_LO(i)   ((jsbytecode)(i))
#define GET_UINT16(pc)   ((uintN)(((pc)[1] << 8) | (pc)[2]))
#define SET_UINT16(pc, i)   ((pc)[1] = UINT16_HI(i), (pc)[2] = UINT16_LO(i))
#define UINT16_LIMIT   ((uintN)1 << 16)
#define ARGC_HI(argc)   UINT16_HI(argc)
#define ARGC_LO(argc)   UINT16_LO(argc)
#define GET_ARGC(pc)   GET_UINT16(pc)
#define ARGC_LIMIT   UINT16_LIMIT
#define GET_ARGNO(pc)   GET_UINT16(pc)
#define SET_ARGNO(pc, argno)   SET_UINT16(pc,argno)
#define ARGNO_LEN   2
#define ARGNO_LIMIT   UINT16_LIMIT
#define GET_VARNO(pc)   GET_UINT16(pc)
#define SET_VARNO(pc, varno)   SET_UINT16(pc,varno)
#define VARNO_LEN   2
#define VARNO_LIMIT   UINT16_LIMIT
#define JSDVG_IGNORE_STACK   0
#define JSDVG_SEARCH_STACK   1

Typedefs

typedef JS_BEGIN_EXTERN_C enum JSOp JSOp
typedef enum JSOpLength JSOpLength

Enumerations

enum  JSOp { JSOP_LIMIT }
enum  JSOpLength { JSOP_LIMIT_LENGTH }

Functions

 JS_STATIC_ASSERT (sizeof(jsatomid)*JS_BITS_PER_BYTE >=ATOM_INDEX_LIMIT_LOG2+1)
JSStringjs_QuoteString (JSContext *cx, JSString *str, jschar quote)
JSPrinterjs_NewPrinter (JSContext *cx, const char *name, uintN indent, JSBool pretty)
void js_DestroyPrinter (JSPrinter *jp)
JSStringjs_GetPrinterOutput (JSPrinter *jp)
int js_printf (JSPrinter *jp, const char *format,...)
JSBool js_puts (JSPrinter *jp, const char *s)
JSBool js_DecompileCode (JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len, uintN pcdepth)
JSBool js_DecompileScript (JSPrinter *jp, JSScript *script)
JSBool js_DecompileFunctionBody (JSPrinter *jp, JSFunction *fun)
JSBool js_DecompileFunction (JSPrinter *jp, JSFunction *fun)
JSStringjs_DecompileValueGenerator (JSContext *cx, intN spindex, jsval v, JSString *fallback)

Variables

const JSCodeSpec js_CodeSpec []
uintN js_NumCodeSpecs
const jschar js_EscapeMap []

Class Documentation

struct JSCodeSpec

Definition at line 224 of file jsopcode.h.

Class Members
uint32 format
int8 length
const char * name
int8 ndefs
int8 nuses
uint8 prec
const char * token

Define Documentation

#define ARGC_HI (   argc)    UINT16_HI(argc)

Definition at line 208 of file jsopcode.h.

Definition at line 211 of file jsopcode.h.

#define ARGC_LO (   argc)    UINT16_LO(argc)

Definition at line 209 of file jsopcode.h.

#define ARGNO_LEN   2

Definition at line 216 of file jsopcode.h.

Definition at line 217 of file jsopcode.h.

#define ATOM_INDEX_HI (   i)    ((jsbytecode)((i) >> 8))

Definition at line 166 of file jsopcode.h.

Definition at line 165 of file jsopcode.h.

Definition at line 195 of file jsopcode.h.

Definition at line 194 of file jsopcode.h.

#define ATOM_INDEX_LO (   i)    ((jsbytecode)(i))

Definition at line 167 of file jsopcode.h.

#define GET_ARGC (   pc)    GET_UINT16(pc)

Definition at line 210 of file jsopcode.h.

#define GET_ARGNO (   pc)    GET_UINT16(pc)

Definition at line 214 of file jsopcode.h.

#define GET_ATOM (   cx,
  script,
  pc 
)
Value:
js_GetAtom((cx), &(script)->atomMap,          \
                                           GET_ATOM_INDEX(pc))

Definition at line 171 of file jsopcode.h.

#define GET_ATOM_INDEX (   pc)    ((jsatomid)(((pc)[1] << 8) | (pc)[2]))

Definition at line 168 of file jsopcode.h.

#define GET_JUMP_OFFSET (   pc)    ((int16)(((pc)[1] << 8) | (pc)[2]))

Definition at line 120 of file jsopcode.h.

Value:
((int32)(((pc)[1] << 24) | ((pc)[2] << 16)    \
                                         | ((pc)[3] << 8) | (pc)[4]))

Definition at line 149 of file jsopcode.h.

Definition at line 190 of file jsopcode.h.

#define GET_SPANDEP_INDEX (   pc)    ((uint16)(((pc)[1] << 8) | (pc)[2]))

Definition at line 137 of file jsopcode.h.

#define GET_UINT16 (   pc)    ((uintN)(((pc)[1] << 8) | (pc)[2]))

Definition at line 203 of file jsopcode.h.

Value:
((jsatomid)(((pc)[1] << 16) |                 \
                                            ((pc)[2] << 8) |                  \
                                            (pc)[3]))

Definition at line 178 of file jsopcode.h.

#define GET_VARNO (   pc)    GET_UINT16(pc)

Definition at line 219 of file jsopcode.h.

Value:
JOF_SET /* hint for JSClass.resolve, used for ops
                                     that do simplex assignment */

Definition at line 102 of file jsopcode.h.

#define JOF_BACKPATCH   0x4000 /* backpatch placeholder during codegen */

Definition at line 104 of file jsopcode.h.

#define JOF_BYTE   0 /* single bytecode, no immediates */

Definition at line 74 of file jsopcode.h.

#define JOF_CONST   2 /* unsigned 16-bit constant pool index */

Definition at line 76 of file jsopcode.h.

#define JOF_DEC   0x0100 /* decrement (--, not ++) opcode */

Definition at line 96 of file jsopcode.h.

#define JOF_DECLARING   0x10000 /* var, const, or function declaration op */

Definition at line 106 of file jsopcode.h.

#define JOF_DEL   0x0080 /* delete operation */

Definition at line 95 of file jsopcode.h.

#define JOF_DETECTING   0x2000 /* object detection flag for JSNewResolveOp */

Definition at line 103 of file jsopcode.h.

#define JOF_ELEM   0x0030 /* obj[index] operation */

Definition at line 92 of file jsopcode.h.

#define JOF_FOR   0x1000 /* for-in property op */

Definition at line 101 of file jsopcode.h.

#define JOF_IMPORT   0x0800 /* import property op */

Definition at line 100 of file jsopcode.h.

#define JOF_INC   0x0200 /* increment (++, not --) opcode */

Definition at line 97 of file jsopcode.h.

#define JOF_INCDEC   0x0300 /* increment or decrement opcode */

Definition at line 98 of file jsopcode.h.

#define JOF_INDEXCONST   8 /* uint16 slot index + constant pool index */

Definition at line 82 of file jsopcode.h.

#define JOF_JUMP   1 /* signed 16-bit jump offset immediate */

Definition at line 75 of file jsopcode.h.

#define JOF_JUMPX   9 /* signed 32-bit jump offset immediate */

Definition at line 83 of file jsopcode.h.

#define JOF_LEFTASSOC   0x8000 /* left-associative operator */

Definition at line 105 of file jsopcode.h.

Value:
13      /* JOF_UINT24 followed by op being extended,
                                     where op if JOF_CONST has no unsigned 16-
                                     bit immediate operand */

Definition at line 87 of file jsopcode.h.

#define JOF_LOCAL   14 /* block-local operand stack variable */

Definition at line 88 of file jsopcode.h.

#define JOF_LOOKUPSWITCH   5 /* lookup switch */

Definition at line 79 of file jsopcode.h.

#define JOF_LOOKUPSWITCHX   11 /* extended (32-bit offset) lookup switch */

Definition at line 85 of file jsopcode.h.

#define JOF_MODEMASK   0x0030 /* mask for above addressing modes */

Definition at line 93 of file jsopcode.h.

#define JOF_NAME   0x0010 /* name operation */

Definition at line 90 of file jsopcode.h.

#define JOF_POST   0x0400 /* postorder increment or decrement */

Definition at line 99 of file jsopcode.h.

#define JOF_PROP   0x0020 /* obj.prop operation */

Definition at line 91 of file jsopcode.h.

#define JOF_QARG   6 /* quickened get/set function argument ops */

Definition at line 80 of file jsopcode.h.

#define JOF_QVAR   7 /* quickened get/set local variable ops */

Definition at line 81 of file jsopcode.h.

#define JOF_SET   0x0040 /* set (i.e., assignment) operation */

Definition at line 94 of file jsopcode.h.

#define JOF_TABLESWITCH   4 /* table switch */

Definition at line 78 of file jsopcode.h.

#define JOF_TABLESWITCHX   10 /* extended (32-bit offset) table switch */

Definition at line 84 of file jsopcode.h.

#define JOF_TYPE_IS_EXTENDED_JUMP (   t)    ((unsigned)((t) - JOF_JUMPX) <= (unsigned)(JOF_LOOKUPSWITCHX - JOF_JUMPX))

Definition at line 109 of file jsopcode.h.

#define JOF_TYPEMASK   0x000f /* mask for above immediate types */

Definition at line 89 of file jsopcode.h.

#define JOF_UINT16   3 /* unsigned 16-bit immediate operand */

Definition at line 77 of file jsopcode.h.

#define JOF_UINT24   12 /* extended unsigned 24-bit literal (index) */

Definition at line 86 of file jsopcode.h.

#define JOF_XMLNAME   0x20000 /* XML name: *, a::b, @a, @a::b, etc. */

Definition at line 107 of file jsopcode.h.

Definition at line 310 of file jsopcode.h.

Definition at line 311 of file jsopcode.h.

#define JUMP_OFFSET_HI (   off)    ((jsbytecode)((off) >> 8))

Definition at line 118 of file jsopcode.h.

Definition at line 117 of file jsopcode.h.

#define JUMP_OFFSET_LO (   off)    ((jsbytecode)(off))

Definition at line 119 of file jsopcode.h.

#define JUMP_OFFSET_MAX   ((int16)0x7fff)

Definition at line 124 of file jsopcode.h.

#define JUMP_OFFSET_MIN   ((int16)0x8000)

Definition at line 123 of file jsopcode.h.

#define JUMPX_OFFSET_B0 (   off)    ((jsbytecode)(off))

Definition at line 148 of file jsopcode.h.

#define JUMPX_OFFSET_B1 (   off)    ((jsbytecode)((off) >> 8))

Definition at line 147 of file jsopcode.h.

#define JUMPX_OFFSET_B2 (   off)    ((jsbytecode)((off) >> 16))

Definition at line 146 of file jsopcode.h.

#define JUMPX_OFFSET_B3 (   off)    ((jsbytecode)((off) >> 24))

Definition at line 145 of file jsopcode.h.

Definition at line 144 of file jsopcode.h.

#define JUMPX_OFFSET_MAX   ((int32)0x7fffffff)

Definition at line 156 of file jsopcode.h.

#define JUMPX_OFFSET_MIN   ((int32)0x80000000)

Definition at line 155 of file jsopcode.h.

Definition at line 187 of file jsopcode.h.

Definition at line 186 of file jsopcode.h.

Definition at line 189 of file jsopcode.h.

Definition at line 188 of file jsopcode.h.

#define OPDEF (   op,
  val,
  name,
  token,
  length,
  nuses,
  ndefs,
  prec,
  format 
)    op = val,

Definition at line 64 of file jsopcode.h.

#define OPDEF (   op,
  val,
  name,
  token,
  length,
  nuses,
  ndefs,
  prec,
  format 
)    op##_LENGTH = length,

Definition at line 64 of file jsopcode.h.

#define SET_ARGNO (   pc,
  argno 
)    SET_UINT16(pc,argno)

Definition at line 215 of file jsopcode.h.

#define SET_ATOM_INDEX (   pc,
  i 
)
Value:
((pc)[1] = ATOM_INDEX_HI(i),                  \
                                 (pc)[2] = ATOM_INDEX_LO(i))

Definition at line 169 of file jsopcode.h.

#define SET_JUMP_OFFSET (   pc,
  off 
)
Value:
((pc)[1] = JUMP_OFFSET_HI(off),               \
                                 (pc)[2] = JUMP_OFFSET_LO(off))

Definition at line 121 of file jsopcode.h.

#define SET_JUMPX_OFFSET (   pc,
  off 
)
Value:
((pc)[1] = JUMPX_OFFSET_B3(off),              \
                                 (pc)[2] = JUMPX_OFFSET_B2(off),              \
                                 (pc)[3] = JUMPX_OFFSET_B1(off),              \
                                 (pc)[4] = JUMPX_OFFSET_B0(off))

Definition at line 151 of file jsopcode.h.

#define SET_LITERAL_INDEX (   pc,
  i 
)    SET_UINT24(pc,i)

Definition at line 191 of file jsopcode.h.

#define SET_SPANDEP_INDEX (   pc,
  i 
)
Value:
((pc)[1] = JUMP_OFFSET_HI(i),                 \
                                 (pc)[2] = JUMP_OFFSET_LO(i))

Definition at line 138 of file jsopcode.h.

#define SET_UINT16 (   pc,
  i 
)    ((pc)[1] = UINT16_HI(i), (pc)[2] = UINT16_LO(i))

Definition at line 204 of file jsopcode.h.

#define SET_UINT24 (   pc,
  i 
)
Value:
((pc)[1] = UINT24_HI(i),                      \
                                 (pc)[2] = UINT24_MID(i),                     \
                                 (pc)[3] = UINT24_LO(i))

Definition at line 181 of file jsopcode.h.

#define SET_VARNO (   pc,
  varno 
)    SET_UINT16(pc,varno)

Definition at line 220 of file jsopcode.h.

#define SPANDEP_INDEX_HUGE   ((uint16)0xffff)

Definition at line 141 of file jsopcode.h.

#define SPANDEP_INDEX_MAX   ((uint16)0xfffe)

Definition at line 140 of file jsopcode.h.

#define UINT16_HI (   i)    ((jsbytecode)((i) >> 8))

Definition at line 201 of file jsopcode.h.

#define UINT16_LIMIT   ((uintN)1 << 16)

Definition at line 205 of file jsopcode.h.

#define UINT16_LO (   i)    ((jsbytecode)(i))

Definition at line 202 of file jsopcode.h.

#define UINT24_HI (   i)    ((jsbytecode)((i) >> 16))

Definition at line 175 of file jsopcode.h.

#define UINT24_LO (   i)    ((jsbytecode)(i))

Definition at line 177 of file jsopcode.h.

#define UINT24_MID (   i)    ((jsbytecode)((i) >> 8))

Definition at line 176 of file jsopcode.h.

#define VARNO_LEN   2

Definition at line 221 of file jsopcode.h.

Definition at line 222 of file jsopcode.h.


Typedef Documentation

typedef JS_BEGIN_EXTERN_C enum JSOp JSOp
typedef enum JSOpLength JSOpLength

Enumeration Type Documentation

enum JSOp
Enumerator:
JSOP_LIMIT 

Definition at line 55 of file jsopcode.h.

                  {
#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
    op = val,
#include "jsopcode.tbl"
#undef OPDEF
    JSOP_LIMIT
} JSOp;
enum JSOpLength
Enumerator:
JSOP_LIMIT_LENGTH 

Definition at line 63 of file jsopcode.h.

                        {
#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
    op##_LENGTH = length,
#include "jsopcode.tbl"
#undef OPDEF
    JSOP_LIMIT_LENGTH
} JSOpLength;

Function Documentation

JSBool js_DecompileCode ( JSPrinter jp,
JSScript script,
jsbytecode pc,
uintN  len,
uintN  pcdepth 
)

Definition at line 4137 of file jsopcode.c.

{
    uintN depth, i;
    SprintStack ss;
    JSContext *cx;
    void *mark;
    JSBool ok;
    JSScript *oldscript;
    char *last;

    depth = script->depth;
    JS_ASSERT(pcdepth <= depth);

    /* Initialize a sprinter for use with the offset stack. */
    cx = jp->sprinter.context;
    mark = JS_ARENA_MARK(&cx->tempPool);
    ok = InitSprintStack(cx, &ss, jp, depth);
    if (!ok)
        goto out;

    /*
     * If we are called from js_DecompileValueGenerator with a portion of
     * script's bytecode that starts with a non-zero model stack depth given
     * by pcdepth, attempt to initialize the missing string offsets in ss to
     * |spindex| negative indexes from fp->sp for the activation fp in which
     * the error arose.
     *
     * See js_DecompileValueGenerator for how its |spindex| parameter is used,
     * and see also GetOff, which makes use of the ss.offsets[i] < -1 that are
     * potentially stored below.
     */
    ss.top = pcdepth;
    if (pcdepth != 0) {
        JSStackFrame *fp;
        ptrdiff_t top;

        for (fp = cx->fp; fp && !fp->script; fp = fp->down)
            continue;
        top = fp ? fp->sp - fp->spbase : 0;
        for (i = 0; i < pcdepth; i++) {
            ss.offsets[i] = -1;
            ss.opcodes[i] = JSOP_NOP;
        }
        if (fp && fp->pc == pc && (uintN)top == pcdepth) {
            for (i = 0; i < pcdepth; i++) {
                ptrdiff_t off;
                jsbytecode *genpc;

                off = (intN)i - (intN)depth;
                genpc = (jsbytecode *) fp->spbase[off];
                if (JS_UPTRDIFF(genpc, script->code) < script->length) {
                    ss.offsets[i] += (ptrdiff_t)i - top;
                    ss.opcodes[i] = *genpc;
                }
            }
        }
    }

    /* Call recursive subroutine to do the hard work. */
    oldscript = jp->script;
    jp->script = script;
    ok = Decompile(&ss, pc, len) != NULL;
    jp->script = oldscript;

    /* If the given code didn't empty the stack, do it now. */
    if (ok && ss.top) {
        do {
            last = OFF2STR(&ss.sprinter, PopOff(&ss, JSOP_POP));
        } while (ss.top > pcdepth);
        js_printf(jp, "%s", last);
    }

out:
    /* Free all temporary stuff allocated under this call. */
    JS_ARENA_RELEASE(&cx->tempPool, mark);
    return ok;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4245 of file jsopcode.c.

{
    JSContext *cx;
    uintN i, nargs, indent;
    void *mark;
    JSAtom **params;
    JSScope *scope, *oldscope;
    JSScopeProperty *sprop;
    jsbytecode *pc, *endpc;
    ptrdiff_t len;
    JSBool ok;

    /*
     * If pretty, conform to ECMA-262 Edition 3, 15.3.4.2, by decompiling a
     * FunctionDeclaration.  Otherwise, check the JSFUN_LAMBDA flag and force
     * an expression by parenthesizing.
     */
    if (jp->pretty) {
        js_printf(jp, "\t");
    } else {
        if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
            js_puts(jp, "(");
    }
    if (JSFUN_GETTER_TEST(fun->flags))
        js_printf(jp, "%s ", js_getter_str);
    else if (JSFUN_SETTER_TEST(fun->flags))
        js_printf(jp, "%s ", js_setter_str);

    js_printf(jp, "%s ", js_function_str);
    if (fun->atom && !QuoteString(&jp->sprinter, ATOM_TO_STRING(fun->atom), 0))
        return JS_FALSE;
    js_puts(jp, "(");

    if (FUN_INTERPRETED(fun) && fun->object) {
        size_t paramsize;
#ifdef JS_HAS_DESTRUCTURING
        SprintStack ss;
        JSScript *oldscript;
#endif

        /*
         * Print the parameters.
         *
         * This code is complicated by the need to handle duplicate parameter
         * names, as required by ECMA (bah!).  A duplicate parameter is stored
         * as another node with the same id (the parameter name) but different
         * shortid (the argument index) along the property tree ancestor line
         * starting at SCOPE_LAST_PROP(scope).  Only the last duplicate param
         * is mapped by the scope's hash table.
         */
        cx = jp->sprinter.context;
        nargs = fun->nargs;
        mark = JS_ARENA_MARK(&cx->tempPool);
        paramsize = nargs * sizeof(JSAtom *);
        JS_ARENA_ALLOCATE_CAST(params, JSAtom **, &cx->tempPool, paramsize);
        if (!params) {
            JS_ReportOutOfMemory(cx);
            return JS_FALSE;
        }

        memset(params, 0, paramsize);
        scope = OBJ_SCOPE(fun->object);
        for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
            if (sprop->getter != js_GetArgument)
                continue;
            JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
            JS_ASSERT((uint16) sprop->shortid < nargs);
            JS_ASSERT(JSID_IS_ATOM(sprop->id));
            params[(uint16) sprop->shortid] = JSID_TO_ATOM(sprop->id);
        }

        pc = fun->u.i.script->main;
        endpc = pc + fun->u.i.script->length;
        ok = JS_TRUE;

#ifdef JS_HAS_DESTRUCTURING
        /* Skip JSOP_GENERATOR in case of destructuring parameters. */
        if (*pc == JSOP_GENERATOR)
            pc += JSOP_GENERATOR_LENGTH;

        ss.printer = NULL;
        oldscript = jp->script;
        jp->script = fun->u.i.script;
        oldscope = jp->scope;
        jp->scope = scope;
#endif

        for (i = 0; i < nargs; i++) {
            if (i > 0)
                js_puts(jp, ", ");

#if JS_HAS_DESTRUCTURING
#define LOCAL_ASSERT(expr)      LOCAL_ASSERT_RV(expr, JS_FALSE)

            if (!params[i]) {
                ptrdiff_t todo;
                const char *lval;

                LOCAL_ASSERT(*pc == JSOP_GETARG);
                pc += JSOP_GETARG_LENGTH;
                LOCAL_ASSERT(*pc == JSOP_DUP);
                if (!ss.printer) {
                    ok = InitSprintStack(cx, &ss, jp, fun->u.i.script->depth);
                    if (!ok)
                        break;
                }
                pc = DecompileDestructuring(&ss, pc, endpc);
                if (!pc) {
                    ok = JS_FALSE;
                    break;
                }
                LOCAL_ASSERT(*pc == JSOP_POP);
                pc += JSOP_POP_LENGTH;
                lval = PopStr(&ss, JSOP_NOP);
                todo = SprintCString(&jp->sprinter, lval);
                if (todo < 0) {
                    ok = JS_FALSE;
                    break;
                }
                continue;
            }

#undef LOCAL_ASSERT
#endif

            if (!QuoteString(&jp->sprinter, ATOM_TO_STRING(params[i]), 0)) {
                ok = JS_FALSE;
                break;
            }
        }

#ifdef JS_HAS_DESTRUCTURING
        jp->script = oldscript;
        jp->scope = oldscope;
#endif
        JS_ARENA_RELEASE(&cx->tempPool, mark);
        if (!ok)
            return JS_FALSE;
#ifdef __GNUC__
    } else {
        scope = NULL;
        pc = NULL;
#endif
    }

    js_printf(jp, ") {\n");
    indent = jp->indent;
    jp->indent += 4;
    if (FUN_INTERPRETED(fun) && fun->object) {
        oldscope = jp->scope;
        jp->scope = scope;
        len = fun->u.i.script->code + fun->u.i.script->length - pc;
        ok = js_DecompileCode(jp, fun->u.i.script, pc, (uintN)len, 0);
        jp->scope = oldscope;
        if (!ok) {
            jp->indent = indent;
            return JS_FALSE;
        }
    } else {
        js_printf(jp, native_code_str);
    }
    jp->indent -= 4;
    js_printf(jp, "\t}");

    if (!jp->pretty) {
        if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
            js_puts(jp, ")");
    }
    return JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4225 of file jsopcode.c.

{
    JSScript *script;
    JSScope *scope, *save;
    JSBool ok;

    if (!FUN_INTERPRETED(fun)) {
        js_printf(jp, native_code_str);
        return JS_TRUE;
    }
    script = fun->u.i.script;
    scope = fun->object ? OBJ_SCOPE(fun->object) : NULL;
    save = jp->scope;
    jp->scope = scope;
    ok = js_DecompileCode(jp, script, script->code, (uintN)script->length, 0);
    jp->scope = save;
    return ok;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool js_DecompileScript ( JSPrinter jp,
JSScript script 
)

Definition at line 4217 of file jsopcode.c.

{
    return js_DecompileCode(jp, script, script->code, (uintN)script->length, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSString* js_DecompileValueGenerator ( JSContext cx,
intN  spindex,
jsval  v,
JSString fallback 
)

Definition at line 4419 of file jsopcode.c.

{
    JSStackFrame *fp, *down;
    jsbytecode *pc, *begin, *end;
    jsval *sp, *spbase, *base, *limit;
    intN depth, pcdepth;
    JSScript *script;
    JSOp op;
    const JSCodeSpec *cs;
    jssrcnote *sn;
    ptrdiff_t len, oplen;
    JSPrinter *jp;
    JSString *name;

    JS_ASSERT(spindex < 0 ||
              spindex == JSDVG_IGNORE_STACK ||
              spindex == JSDVG_SEARCH_STACK);

    for (fp = cx->fp; fp && !fp->script; fp = fp->down)
        continue;
    if (!fp)
        goto do_fallback;

    /* Try to find sp's generating pc depth slots under it on the stack. */
    pc = fp->pc;
    sp = fp->sp;
    spbase = fp->spbase;
    if ((uintN)(sp - spbase) > fp->script->depth) {
        /*
         * Preparing to make an internal invocation, using an argv stack
         * segment pushed just above fp's operand stack space.  Such an argv
         * stack has no generating pc "basement", so we must fall back.
         */
        goto do_fallback;
    }

    if (spindex == JSDVG_SEARCH_STACK) {
        if (!pc) {
            /*
             * Current frame is native: look under it for a scripted call
             * in which a decompilable bytecode string that generated the
             * value as an actual argument might exist.
             */
            JS_ASSERT(!fp->script && !(fp->fun && FUN_INTERPRETED(fp->fun)));
            down = fp->down;
            if (!down)
                goto do_fallback;
            script = down->script;
            spbase = down->spbase;
            base = fp->argv;
            limit = base + fp->argc;
        } else {
            /*
             * This should be a script activation, either a top-level
             * script or a scripted function.  But be paranoid about calls
             * to js_DecompileValueGenerator from code that hasn't fully
             * initialized a (default-all-zeroes) frame.
             */
            script = fp->script;
            spbase = base = fp->spbase;
            limit = fp->sp;
        }

        /*
         * Pure paranoia about default-zeroed frames being active while
         * js_DecompileValueGenerator is called.  It can't hurt much now;
         * error reporting performance is not an issue.
         */
        if (!script || !base || !limit)
            goto do_fallback;

        /*
         * Try to find operand-generating pc depth slots below sp.
         *
         * In the native case, we know the arguments have generating pc's
         * under them, on account of fp->down->script being non-null: all
         * compiled scripts get depth slots for generating pc's allocated
         * upon activation, at the top of js_Interpret.
         *
         * In the script or scripted function case, the same reasoning
         * applies to fp rather than to fp->down.
         *
         * We search from limit to base to find the most recently calculated
         * value matching v under assumption that it is it that caused
         * exception, see bug 328664.
         */
        for (sp = limit;;) {
            if (sp <= base)
                goto do_fallback;
            --sp;
            if (*sp == v) {
                depth = (intN)script->depth;
                sp -= depth;
                pc = (jsbytecode *) *sp;
                break;
            }
        }
    } else {
        /*
         * At this point, pc may or may not be null, i.e., we could be in
         * a script activation, or we could be in a native frame that was
         * called by another native function.  Check pc and script.
         */
        if (!pc)
            goto do_fallback;
        script = fp->script;
        if (!script)
            goto do_fallback;

        if (spindex != JSDVG_IGNORE_STACK) {
            JS_ASSERT(spindex < 0);
            depth = (intN)script->depth;
#if !JS_HAS_NO_SUCH_METHOD
            JS_ASSERT(-depth <= spindex);
#endif
            sp = fp->sp + spindex;
            if ((jsuword) (sp - fp->spbase) < (jsuword) depth)
                pc = (jsbytecode *) *(sp - depth);

        }
    }

    /*
     * Again, be paranoid, this time about possibly loading an invalid pc
     * from fp->sp[spindex - script->depth)].
     */
    if (JS_UPTRDIFF(pc, script->code) >= (jsuword)script->length) {
        pc = fp->pc;
        if (!pc)
            goto do_fallback;
    }
    op = (JSOp) *pc;
    if (op == JSOP_TRAP)
        op = JS_GetTrapOpcode(cx, script, pc);

    /* None of these stack-writing ops generates novel values. */
    JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX &&
              op != JSOP_DUP && op != JSOP_DUP2 &&
              op != JSOP_SWAP);

    /*
     * |this| could convert to a very long object initialiser, so cite it by
     * its keyword name instead.
     */
    if (op == JSOP_THIS)
        return JS_NewStringCopyZ(cx, js_this_str);

    /*
     * JSOP_BINDNAME is special: it generates a value, the base object of a
     * reference.  But if it is the generating op for a diagnostic produced by
     * js_DecompileValueGenerator, the name being bound is irrelevant.  Just
     * fall back to the base object.
     */
    if (op == JSOP_BINDNAME)
        goto do_fallback;

    /* NAME ops are self-contained, others require left or right context. */
    cs = &js_CodeSpec[op];
    begin = pc;
    end = pc + cs->length;
    if ((cs->format & JOF_MODEMASK) != JOF_NAME) {
        JSSrcNoteType noteType;

        sn = js_GetSrcNote(script, pc);
        if (!sn)
            goto do_fallback;
        noteType = SN_TYPE(sn);
        if (noteType == SRC_PCBASE) {
            begin -= js_GetSrcNoteOffset(sn, 0);
        } else if (noteType == SRC_PCDELTA) {
            end = begin + js_GetSrcNoteOffset(sn, 0);
            begin += cs->length;
        } else {
            goto do_fallback;
        }
    }
    len = PTRDIFF(end, begin, jsbytecode);
    if (len <= 0)
        goto do_fallback;

    /*
     * Walk forward from script->main and compute starting stack depth.
     * FIXME: Code to compute oplen copied from js_Disassemble1 and reduced.
     * FIXME: Optimize to use last empty-stack sequence point.
     */
    pcdepth = 0;
    for (pc = script->main; pc < begin; pc += oplen) {
        jsbytecode *pc2;
        uint32 type;
        intN nuses, ndefs;

        /* Let pc2 be non-null only for JSOP_LITOPX. */
        pc2 = NULL;
        op = (JSOp) *pc;
        if (op == JSOP_TRAP)
            op = JS_GetTrapOpcode(cx, script, pc);
        cs = &js_CodeSpec[op];
        oplen = cs->length;

        if (op == JSOP_SETSP) {
            pcdepth = GET_UINT16(pc);
            continue;
        }

        /*
         * A (C ? T : E) expression requires skipping either T (if begin is in
         * E) or both T and E (if begin is after the whole expression) before
         * adjusting pcdepth based on the JSOP_IFEQ or JSOP_IFEQX at pc that
         * tests condition C.  We know that the stack depth can't change from
         * what it was with C on top of stack.
         */
        sn = js_GetSrcNote(script, pc);
        if (sn && SN_TYPE(sn) == SRC_COND) {
            ptrdiff_t jmpoff, jmplen;

            jmpoff = js_GetSrcNoteOffset(sn, 0);
            if (pc + jmpoff < begin) {
                pc += jmpoff;
                op = *pc;
                JS_ASSERT(op == JSOP_GOTO || op == JSOP_GOTOX);
                cs = &js_CodeSpec[op];
                oplen = cs->length;
                jmplen = GetJumpOffset(pc, pc);
                if (pc + jmplen < begin) {
                    oplen = (uintN) jmplen;
                    continue;
                }

                /*
                 * Ok, begin lies in E.  Manually pop C off the model stack,
                 * since we have moved beyond the IFEQ now.
                 */
                --pcdepth;
            }
        }

        type = cs->format & JOF_TYPEMASK;
        switch (type) {
          case JOF_TABLESWITCH:
          case JOF_TABLESWITCHX:
          {
            jsint jmplen, i, low, high;

            jmplen = (type == JOF_TABLESWITCH) ? JUMP_OFFSET_LEN
                                               : JUMPX_OFFSET_LEN;
            pc2 = pc;
            pc2 += jmplen;
            low = GET_JUMP_OFFSET(pc2);
            pc2 += JUMP_OFFSET_LEN;
            high = GET_JUMP_OFFSET(pc2);
            pc2 += JUMP_OFFSET_LEN;
            for (i = low; i <= high; i++)
                pc2 += jmplen;
            oplen = 1 + pc2 - pc;
            break;
          }

          case JOF_LOOKUPSWITCH:
          case JOF_LOOKUPSWITCHX:
          {
            jsint jmplen;
            jsbytecode *pc2;
            jsatomid npairs;

            jmplen = (type == JOF_LOOKUPSWITCH) ? JUMP_OFFSET_LEN
                                                : JUMPX_OFFSET_LEN;
            pc2 = pc;
            pc2 += jmplen;
            npairs = GET_ATOM_INDEX(pc2);
            pc2 += ATOM_INDEX_LEN;
            while (npairs) {
                pc2 += ATOM_INDEX_LEN;
                pc2 += jmplen;
                npairs--;
            }
            oplen = 1 + pc2 - pc;
            break;
          }

          case JOF_LITOPX:
            pc2 = pc + 1 + LITERAL_INDEX_LEN;
            op = *pc2;
            cs = &js_CodeSpec[op];
            JS_ASSERT(cs->length > ATOM_INDEX_LEN);
            oplen += cs->length - (1 + ATOM_INDEX_LEN);
            break;

          default:;
        }

        if (sn && SN_TYPE(sn) == SRC_HIDDEN)
            continue;

        nuses = cs->nuses;
        if (nuses < 0) {
            /* Call opcode pushes [callee, this, argv...]. */
            nuses = 2 + GET_ARGC(pc);
        } else if (op == JSOP_RETSUB) {
            /* Pop [exception or hole, retsub pc-index]. */
            JS_ASSERT(nuses == 0);
            nuses = 2;
        } else if (op == JSOP_LEAVEBLOCK || op == JSOP_LEAVEBLOCKEXPR) {
            JS_ASSERT(nuses == 0);
            nuses = GET_UINT16(pc);
        }
        pcdepth -= nuses;
        JS_ASSERT(pcdepth >= 0);

        ndefs = cs->ndefs;
        if (op == JSOP_FINALLY) {
            /* Push [exception or hole, retsub pc-index]. */
            JS_ASSERT(ndefs == 0);
            ndefs = 2;
        } else if (op == JSOP_ENTERBLOCK) {
            jsatomid atomIndex;
            JSAtom *atom;
            JSObject *obj;

            JS_ASSERT(ndefs == 0);
            atomIndex = pc2 ? GET_LITERAL_INDEX(pc) : GET_ATOM_INDEX(pc);
            atom = js_GetAtom(cx, &script->atomMap, atomIndex);
            obj = ATOM_TO_OBJECT(atom);
            JS_ASSERT(OBJ_BLOCK_DEPTH(cx, obj) == pcdepth);
            ndefs = OBJ_BLOCK_COUNT(cx, obj);
        }
        pcdepth += ndefs;
    }

    name = NULL;
    jp = js_NewPrinter(cx, "js_DecompileValueGenerator", 0, JS_FALSE);
    if (jp) {
        if (fp->fun && fp->fun->object) {
            JS_ASSERT(OBJ_IS_NATIVE(fp->fun->object));
            jp->scope = OBJ_SCOPE(fp->fun->object);
        }
        jp->dvgfence = end;
        if (js_DecompileCode(jp, script, begin, (uintN)len, (uintN)pcdepth))
            name = js_GetPrinterOutput(jp);
        js_DestroyPrinter(jp);
    }
    return name;

  do_fallback:
    return fallback ? fallback : js_ValueToSource(cx, v);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 597 of file jsopcode.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 604 of file jsopcode.c.

{
    JSContext *cx;
    JSString *str;

    cx = jp->sprinter.context;
    if (!jp->sprinter.base)
        return cx->runtime->emptyString;
    str = JS_NewStringCopyZ(cx, jp->sprinter.base);
    if (!str)
        return NULL;
    JS_FreeArenaPool(&jp->pool);
    INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
    return str;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSPrinter* js_NewPrinter ( JSContext cx,
const char *  name,
uintN  indent,
JSBool  pretty 
)

Definition at line 574 of file jsopcode.c.

{
    JSPrinter *jp;

    jp = (JSPrinter *) JS_malloc(cx, sizeof(JSPrinter));
    if (!jp)
        return NULL;
    INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
    JS_InitArenaPool(&jp->pool, name, 256, 1);
    jp->indent = indent & ~JS_IN_GROUP_CONTEXT;
    jp->pretty = pretty;
    jp->grouped = (indent & JS_IN_GROUP_CONTEXT) != 0;
    jp->script = NULL;
    jp->dvgfence = NULL;
    jp->scope = NULL;
#if JS_HAS_BLOCK_SCOPE
    jp->braceState = ALWAYS_BRACE;
    jp->spaceOffset = -1;
#endif
    return jp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int js_printf ( JSPrinter jp,
const char *  format,
  ... 
)

Definition at line 649 of file jsopcode.c.

{
    va_list ap;
    char *bp, *fp;
    int cc;

    if (*format == '\0')
        return 0;

    va_start(ap, format);

    /* If pretty-printing, expand magic tab into a run of jp->indent spaces. */
    if (*format == '\t') {
        format++;

#if JS_HAS_BLOCK_SCOPE
        if (*format == '}' && jp->braceState != ALWAYS_BRACE) {
            JSBraceState braceState;

            braceState = jp->braceState;
            jp->braceState = ALWAYS_BRACE;
            if (braceState == DONT_BRACE) {
                ptrdiff_t offset, delta, from;

                JS_ASSERT(format[1] == '\n' || format[1] == ' ');
                offset = jp->spaceOffset;
                JS_ASSERT(offset >= 6);

                /* Replace " {\n" at the end of jp->sprinter with "\n". */
                bp = jp->sprinter.base;
                if (bp[offset+0] == ' ' && bp[offset+1] == '{') {
                    delta = 2;
                    if (jp->pretty) {
                        /* If pretty, we don't have to worry about 'else'. */
                        JS_ASSERT(bp[offset+2] == '\n');
                    } else if (bp[offset-1] != ')') {
                        /* Must keep ' ' to avoid 'dolet' or 'elselet'. */
                        ++offset;
                        delta = 1;
                    }

                    from = offset + delta;
                    memmove(bp + offset, bp + from, jp->sprinter.offset - from);
                    jp->sprinter.offset -= delta;
                    jp->spaceOffset = -1;

                    format += 2;
                    if (*format == '\0')
                        return 0;
                }
            }
        }
#endif

        if (jp->pretty && Sprint(&jp->sprinter, "%*s", jp->indent, "") < 0)
            return -1;
    }

    /* Suppress newlines (must be once per format, at the end) if not pretty. */
    fp = NULL;
    if (!jp->pretty && format[cc = strlen(format) - 1] == '\n') {
        fp = JS_strdup(jp->sprinter.context, format);
        if (!fp)
            return -1;
        fp[cc] = '\0';
        format = fp;
    }

    /* Allocate temp space, convert format, and put. */
    bp = JS_vsmprintf(format, ap);      /* XXX vsaprintf */
    if (fp) {
        JS_free(jp->sprinter.context, fp);
        format = NULL;
    }
    if (!bp) {
        JS_ReportOutOfMemory(jp->sprinter.context);
        return -1;
    }

    cc = strlen(bp);
    if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0)
        cc = -1;
    free(bp);

    va_end(ap);
    return cc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool js_puts ( JSPrinter jp,
const char *  s 
)

Definition at line 738 of file jsopcode.c.

{
    return SprintCString(&jp->sprinter, s) >= 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSString* js_QuoteString ( JSContext cx,
JSString str,
jschar  quote 
)

Definition at line 525 of file jsopcode.c.

{
    void *mark;
    Sprinter sprinter;
    char *bytes;
    JSString *escstr;

    mark = JS_ARENA_MARK(&cx->tempPool);
    INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
    bytes = QuoteString(&sprinter, str, quote);
    escstr = bytes ? JS_NewStringCopyZ(cx, bytes) : NULL;
    JS_ARENA_RELEASE(&cx->tempPool, mark);
    return escstr;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JS_STATIC_ASSERT ( sizeof(jsatomid)*JS_BITS_PER_BYTE >=ATOM_INDEX_LIMIT_LOG2 1)

Variable Documentation

Definition at line 91 of file jsopcode.c.

Definition at line 440 of file jsopcode.c.

Definition at line 98 of file jsopcode.c.