~ubuntu-branches/ubuntu/wily/oolite/wily-proposed

« back to all changes in this revision

Viewing changes to deps/Windows-x86-deps/JS32ECMAv5/include/jsemit.h

  • Committer: Package Import Robot
  • Author(s): Nicolas Boulenguez
  • Date: 2011-12-22 00:22:39 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20111222002239-pr3upeupp4jw1psp
Tags: 1.76-1
* New upstream.
* watch: scan upstream stable releases instead of dev snapshots.
* control: use default gobjc instead of explicit 4.6.
* rules: use dpkg-dev build flags.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
 * vim: set ts=8 sw=4 et tw=79:
 
3
 *
 
4
 * ***** BEGIN LICENSE BLOCK *****
 
5
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
6
 *
 
7
 * The contents of this file are subject to the Mozilla Public License Version
 
8
 * 1.1 (the "License"); you may not use this file except in compliance with
 
9
 * the License. You may obtain a copy of the License at
 
10
 * http://www.mozilla.org/MPL/
 
11
 *
 
12
 * Software distributed under the License is distributed on an "AS IS" basis,
 
13
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
14
 * for the specific language governing rights and limitations under the
 
15
 * License.
 
16
 *
 
17
 * The Original Code is Mozilla Communicator client code, released
 
18
 * March 31, 1998.
 
19
 *
 
20
 * The Initial Developer of the Original Code is
 
21
 * Netscape Communications Corporation.
 
22
 * Portions created by the Initial Developer are Copyright (C) 1998
 
23
 * the Initial Developer. All Rights Reserved.
 
24
 *
 
25
 * Contributor(s):
 
26
 *
 
27
 * Alternatively, the contents of this file may be used under the terms of
 
28
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 
29
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
30
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
31
 * of those above. If you wish to allow use of your version of this file only
 
32
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
33
 * use your version of this file under the terms of the MPL, indicate your
 
34
 * decision by deleting the provisions above and replace them with the notice
 
35
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
36
 * the provisions above, a recipient may use your version of this file under
 
37
 * the terms of any one of the MPL, the GPL or the LGPL.
 
38
 *
 
39
 * ***** END LICENSE BLOCK ***** */
 
40
 
 
41
#ifndef jsemit_h___
 
42
#define jsemit_h___
 
43
/*
 
44
 * JS bytecode generation.
 
45
 */
 
46
#include "jstypes.h"
 
47
#include "jsatom.h"
 
48
#include "jsopcode.h"
 
49
#include "jsparse.h"
 
50
#include "jsscript.h"
 
51
#include "jsprvtd.h"
 
52
#include "jspubtd.h"
 
53
 
 
54
JS_BEGIN_EXTERN_C
 
55
 
 
56
/*
 
57
 * NB: If you add enumerators for scope statements, add them between STMT_WITH
 
58
 * and STMT_CATCH, or you will break the STMT_TYPE_IS_SCOPE macro. If you add
 
59
 * non-looping statement enumerators, add them before STMT_DO_LOOP or you will
 
60
 * break the STMT_TYPE_IS_LOOP macro.
 
61
 *
 
62
 * Also remember to keep the statementName array in jsemit.c in sync.
 
63
 */
 
64
typedef enum JSStmtType {
 
65
    STMT_LABEL,                 /* labeled statement:  L: s */
 
66
    STMT_IF,                    /* if (then) statement */
 
67
    STMT_ELSE,                  /* else clause of if statement */
 
68
    STMT_SEQ,                   /* synthetic sequence of statements */
 
69
    STMT_BLOCK,                 /* compound statement: { s1[;... sN] } */
 
70
    STMT_SWITCH,                /* switch statement */
 
71
    STMT_WITH,                  /* with statement */
 
72
    STMT_CATCH,                 /* catch block */
 
73
    STMT_TRY,                   /* try block */
 
74
    STMT_FINALLY,               /* finally block */
 
75
    STMT_SUBROUTINE,            /* gosub-target subroutine body */
 
76
    STMT_DO_LOOP,               /* do/while loop statement */
 
77
    STMT_FOR_LOOP,              /* for loop statement */
 
78
    STMT_FOR_IN_LOOP,           /* for/in loop statement */
 
79
    STMT_WHILE_LOOP,            /* while loop statement */
 
80
    STMT_LIMIT
 
81
} JSStmtType;
 
82
 
 
83
#define STMT_TYPE_IN_RANGE(t,b,e) ((uint)((t) - (b)) <= (uintN)((e) - (b)))
 
84
 
 
85
/*
 
86
 * A comment on the encoding of the JSStmtType enum and type-testing macros:
 
87
 *
 
88
 * STMT_TYPE_MAYBE_SCOPE tells whether a statement type is always, or may
 
89
 * become, a lexical scope.  It therefore includes block and switch (the two
 
90
 * low-numbered "maybe" scope types) and excludes with (with has dynamic scope
 
91
 * pending the "reformed with" in ES4/JS2).  It includes all try-catch-finally
 
92
 * types, which are high-numbered maybe-scope types.
 
93
 *
 
94
 * STMT_TYPE_LINKS_SCOPE tells whether a JSStmtInfo of the given type eagerly
 
95
 * links to other scoping statement info records.  It excludes the two early
 
96
 * "maybe" types, block and switch, as well as the try and both finally types,
 
97
 * since try and the other trailing maybe-scope types don't need block scope
 
98
 * unless they contain let declarations.
 
99
 *
 
100
 * We treat WITH as a static scope because it prevents lexical binding from
 
101
 * continuing further up the static scope chain. With the lost "reformed with"
 
102
 * proposal for ES4, we would be able to model it statically, too.
 
103
 */
 
104
#define STMT_TYPE_MAYBE_SCOPE(type)                                           \
 
105
    (type != STMT_WITH &&                                                     \
 
106
     STMT_TYPE_IN_RANGE(type, STMT_BLOCK, STMT_SUBROUTINE))
 
107
 
 
108
#define STMT_TYPE_LINKS_SCOPE(type)                                           \
 
109
    STMT_TYPE_IN_RANGE(type, STMT_WITH, STMT_CATCH)
 
110
 
 
111
#define STMT_TYPE_IS_TRYING(type)                                             \
 
112
    STMT_TYPE_IN_RANGE(type, STMT_TRY, STMT_SUBROUTINE)
 
113
 
 
114
#define STMT_TYPE_IS_LOOP(type) ((type) >= STMT_DO_LOOP)
 
115
 
 
116
#define STMT_MAYBE_SCOPE(stmt)  STMT_TYPE_MAYBE_SCOPE((stmt)->type)
 
117
#define STMT_LINKS_SCOPE(stmt)  (STMT_TYPE_LINKS_SCOPE((stmt)->type) ||       \
 
118
                                 ((stmt)->flags & SIF_SCOPE))
 
119
#define STMT_IS_TRYING(stmt)    STMT_TYPE_IS_TRYING((stmt)->type)
 
120
#define STMT_IS_LOOP(stmt)      STMT_TYPE_IS_LOOP((stmt)->type)
 
121
 
 
122
typedef struct JSStmtInfo JSStmtInfo;
 
123
 
 
124
struct JSStmtInfo {
 
125
    uint16          type;           /* statement type */
 
126
    uint16          flags;          /* flags, see below */
 
127
    uint32          blockid;        /* for simplified dominance computation */
 
128
    ptrdiff_t       update;         /* loop update offset (top if none) */
 
129
    ptrdiff_t       breaks;         /* offset of last break in loop */
 
130
    ptrdiff_t       continues;      /* offset of last continue in loop */
 
131
    union {
 
132
        JSAtom      *label;         /* name of LABEL */
 
133
        JSObjectBox *blockBox;      /* block scope object */
 
134
    };
 
135
    JSStmtInfo      *down;          /* info for enclosing statement */
 
136
    JSStmtInfo      *downScope;     /* next enclosing lexical scope */
 
137
};
 
138
 
 
139
#define SIF_SCOPE        0x0001     /* statement has its own lexical scope */
 
140
#define SIF_BODY_BLOCK   0x0002     /* STMT_BLOCK type is a function body */
 
141
#define SIF_FOR_BLOCK    0x0004     /* for (let ...) induced block scope */
 
142
 
 
143
/*
 
144
 * To reuse space in JSStmtInfo, rename breaks and continues for use during
 
145
 * try/catch/finally code generation and backpatching. To match most common
 
146
 * use cases, the macro argument is a struct, not a struct pointer. Only a
 
147
 * loop, switch, or label statement info record can have breaks and continues,
 
148
 * and only a for loop has an update backpatch chain, so it's safe to overlay
 
149
 * these for the "trying" JSStmtTypes.
 
150
 */
 
151
#define CATCHNOTE(stmt)  ((stmt).update)
 
152
#define GOSUBS(stmt)     ((stmt).breaks)
 
153
#define GUARDJUMP(stmt)  ((stmt).continues)
 
154
 
 
155
#define SET_STATEMENT_TOP(stmt, top)                                          \
 
156
    ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
 
157
 
 
158
#ifdef JS_SCOPE_DEPTH_METER
 
159
# define JS_SCOPE_DEPTH_METERING(code) ((void) (code))
 
160
# define JS_SCOPE_DEPTH_METERING_IF(cond, code) ((cond) ? (void) (code) : (void) 0)
 
161
#else
 
162
# define JS_SCOPE_DEPTH_METERING(code) ((void) 0)
 
163
# define JS_SCOPE_DEPTH_METERING_IF(code, x) ((void) 0)
 
164
#endif
 
165
 
 
166
#define TCF_COMPILING           0x01 /* JSTreeContext is JSCodeGenerator */
 
167
#define TCF_IN_FUNCTION         0x02 /* parsing inside function body */
 
168
#define TCF_RETURN_EXPR         0x04 /* function has 'return expr;' */
 
169
#define TCF_RETURN_VOID         0x08 /* function has 'return;' */
 
170
#define TCF_IN_FOR_INIT         0x10 /* parsing init expr of for; exclude 'in' */
 
171
#define TCF_FUN_SETS_OUTER_NAME 0x20 /* function set outer name (lexical or free) */
 
172
#define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */
 
173
#define TCF_FUN_USES_ARGUMENTS  0x80 /* function uses arguments except as a
 
174
                                        parameter name */
 
175
#define TCF_FUN_HEAVYWEIGHT    0x100 /* function needs Call object per call */
 
176
#define TCF_FUN_IS_GENERATOR   0x200 /* parsed yield statement in function */
 
177
#define TCF_FUN_USES_OWN_NAME  0x400 /* named function expression that uses its
 
178
                                        own name */
 
179
#define TCF_HAS_FUNCTION_STMT  0x800 /* block contains a function statement */
 
180
#define TCF_GENEXP_LAMBDA     0x1000 /* flag lambda from generator expression */
 
181
#define TCF_COMPILE_N_GO      0x2000 /* compile-and-go mode of script, can
 
182
                                        optimize name references based on scope
 
183
                                        chain */
 
184
#define TCF_NO_SCRIPT_RVAL    0x4000 /* API caller does not want result value
 
185
                                        from global script */
 
186
#define TCF_HAS_SHARPS        0x8000 /* source contains sharp defs or uses */
 
187
 
 
188
/*
 
189
 * Set when parsing a declaration-like destructuring pattern.  This
 
190
 * flag causes PrimaryExpr to create PN_NAME parse nodes for variable
 
191
 * references which are not hooked into any definition's use chain,
 
192
 * added to any tree context's AtomList, etc. etc.  CheckDestructuring
 
193
 * will do that work later.
 
194
 *
 
195
 * The comments atop CheckDestructuring explain the distinction
 
196
 * between assignment-like and declaration-like destructuring
 
197
 * patterns, and why they need to be treated differently.
 
198
 */
 
199
#define TCF_DECL_DESTRUCTURING  0x10000
 
200
 
 
201
/*
 
202
 * A request flag passed to Compiler::compileScript and then down via
 
203
 * JSCodeGenerator to js_NewScriptFromCG, from script_compile_sub and any
 
204
 * kindred functions that need to make mutable scripts (even empty ones;
 
205
 * i.e., they can't share the const JSScript::emptyScript() singleton).
 
206
 */
 
207
#define TCF_NEED_MUTABLE_SCRIPT 0x20000
 
208
 
 
209
/*
 
210
 * This function/global/eval code body contained a Use Strict Directive. Treat
 
211
 * certain strict warnings as errors, and forbid the use of 'with'. See also
 
212
 * TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and JSREPORT_STRICT_ERROR.
 
213
 */
 
214
#define TCF_STRICT_MODE_CODE    0x40000
 
215
 
 
216
/* bit 0x80000 is unused */
 
217
 
 
218
/*
 
219
 * Flag signifying that the current function seems to be a constructor that
 
220
 * sets this.foo to define "methods", at least one of which can't be a null
 
221
 * closure, so we should avoid over-specializing property cache entries and
 
222
 * trace inlining guards to method function object identity, which will vary
 
223
 * per instance.
 
224
 */
 
225
#define TCF_FUN_UNBRAND_THIS   0x100000
 
226
 
 
227
/*
 
228
 * "Module pattern", i.e., a lambda that is immediately applied and the whole
 
229
 * of an expression statement.
 
230
 */
 
231
#define TCF_FUN_MODULE_PATTERN 0x200000
 
232
 
 
233
/*
 
234
 * Flag to prevent a non-escaping function from being optimized into a null
 
235
 * closure (i.e., a closure that needs only its global object for free variable
 
236
 * resolution), because this function contains a closure that needs one or more
 
237
 * scope objects surrounding it (i.e., a Call object for an outer heavyweight
 
238
 * function). See bug 560234.
 
239
 */
 
240
#define TCF_FUN_ENTRAINS_SCOPES 0x400000
 
241
 
 
242
/* The function calls 'eval'. */
 
243
#define TCF_FUN_CALLS_EVAL       0x800000
 
244
 
 
245
/* The function mutates a positional (non-destructuring) parameter. */
 
246
#define TCF_FUN_MUTATES_PARAMETER 0x1000000
 
247
 
 
248
/*
 
249
 * Compiling an eval() script.
 
250
 */
 
251
#define TCF_COMPILE_FOR_EVAL     0x2000000
 
252
 
 
253
/*
 
254
 * The function or a function that encloses it may define new local names
 
255
 * at runtime through means other than calling eval.
 
256
 */
 
257
#define TCF_FUN_MIGHT_ALIAS_LOCALS  0x4000000
 
258
 
 
259
/*
 
260
 * The script contains singleton initialiser JSOP_OBJECT.
 
261
 */
 
262
#define TCF_HAS_SINGLETONS       0x8000000
 
263
 
 
264
/*
 
265
 * Some enclosing scope is a with-statement or E4X filter-expression.
 
266
 */
 
267
#define TCF_IN_WITH             0x10000000
 
268
 
 
269
/*
 
270
 * Flags to check for return; vs. return expr; in a function.
 
271
 */
 
272
#define TCF_RETURN_FLAGS        (TCF_RETURN_EXPR | TCF_RETURN_VOID)
 
273
 
 
274
/*
 
275
 * Sticky deoptimization flags to propagate from FunctionBody.
 
276
 */
 
277
#define TCF_FUN_FLAGS           (TCF_FUN_SETS_OUTER_NAME |                    \
 
278
                                 TCF_FUN_USES_ARGUMENTS  |                    \
 
279
                                 TCF_FUN_PARAM_ARGUMENTS |                    \
 
280
                                 TCF_FUN_HEAVYWEIGHT     |                    \
 
281
                                 TCF_FUN_IS_GENERATOR    |                    \
 
282
                                 TCF_FUN_USES_OWN_NAME   |                    \
 
283
                                 TCF_HAS_SHARPS          |                    \
 
284
                                 TCF_FUN_CALLS_EVAL      |                    \
 
285
                                 TCF_FUN_MIGHT_ALIAS_LOCALS |                 \
 
286
                                 TCF_FUN_MUTATES_PARAMETER |                  \
 
287
                                 TCF_STRICT_MODE_CODE)
 
288
 
 
289
struct JSTreeContext {              /* tree context for semantic checks */
 
290
    uint32          flags;          /* statement state flags, see above */
 
291
    uint32          bodyid;         /* block number of program/function body */
 
292
    uint32          blockidGen;     /* preincremented block number generator */
 
293
    JSStmtInfo      *topStmt;       /* top of statement info stack */
 
294
    JSStmtInfo      *topScopeStmt;  /* top lexical scope statement */
 
295
    JSObjectBox     *blockChainBox; /* compile time block scope chain (NB: one
 
296
                                       deeper than the topScopeStmt/downScope
 
297
                                       chain when in head of let block/expr) */
 
298
    JSParseNode     *blockNode;     /* parse node for a block with let declarations
 
299
                                       (block with its own lexical scope)  */
 
300
    JSAtomList      decls;          /* function, const, and var declarations */
 
301
    js::Parser      *parser;        /* ptr to common parsing and lexing data */
 
302
 
 
303
  private:
 
304
    union {
 
305
        JSFunction  *fun_;          /* function to store argument and variable
 
306
                                       names when flags & TCF_IN_FUNCTION */
 
307
        JSObject    *scopeChain_;   /* scope chain object for the script */
 
308
    };
 
309
 
 
310
  public:
 
311
    JSFunction *fun() const {
 
312
        JS_ASSERT(inFunction());
 
313
        return fun_;
 
314
    }
 
315
    void setFunction(JSFunction *fun) {
 
316
        JS_ASSERT(inFunction());
 
317
        fun_ = fun;
 
318
    }
 
319
    JSObject *scopeChain() const {
 
320
        JS_ASSERT(!inFunction());
 
321
        return scopeChain_;
 
322
    }
 
323
    void setScopeChain(JSObject *scopeChain) {
 
324
        JS_ASSERT(!inFunction());
 
325
        scopeChain_ = scopeChain;
 
326
    }
 
327
 
 
328
    JSAtomList      lexdeps;        /* unresolved lexical name dependencies */
 
329
    JSTreeContext   *parent;        /* enclosing function or global context */
 
330
    uintN           staticLevel;    /* static compilation unit nesting level */
 
331
 
 
332
    JSFunctionBox   *funbox;        /* null or box for function we're compiling
 
333
                                       if (flags & TCF_IN_FUNCTION) and not in
 
334
                                       Compiler::compileFunctionBody */
 
335
    JSFunctionBox   *functionList;
 
336
 
 
337
    JSParseNode     *innermostWith; /* innermost WITH parse node */
 
338
 
 
339
    js::Bindings    bindings;       /* bindings in this code, including
 
340
                                       arguments if we're compiling a function */
 
341
 
 
342
#ifdef JS_SCOPE_DEPTH_METER
 
343
    uint16          scopeDepth;     /* current lexical scope chain depth */
 
344
    uint16          maxScopeDepth;  /* maximum lexical scope chain depth */
 
345
#endif
 
346
 
 
347
    void trace(JSTracer *trc);
 
348
 
 
349
    JSTreeContext(js::Parser *prs)
 
350
      : flags(0), bodyid(0), blockidGen(0), topStmt(NULL), topScopeStmt(NULL),
 
351
        blockChainBox(NULL), blockNode(NULL), parser(prs), scopeChain_(NULL), parent(prs->tc),
 
352
        staticLevel(0), funbox(NULL), functionList(NULL), innermostWith(NULL), bindings(prs->context),
 
353
        sharpSlotBase(-1)
 
354
    {
 
355
        prs->tc = this;
 
356
        JS_SCOPE_DEPTH_METERING(scopeDepth = maxScopeDepth = 0);
 
357
    }
 
358
 
 
359
    /*
 
360
     * For functions the tree context is constructed and destructed a second
 
361
     * time during code generation. To avoid a redundant stats update in such
 
362
     * cases, we store uint16(-1) in maxScopeDepth.
 
363
     */
 
364
    ~JSTreeContext() {
 
365
        parser->tc = this->parent;
 
366
        JS_SCOPE_DEPTH_METERING_IF((maxScopeDepth != uint16(-1)),
 
367
                                   JS_BASIC_STATS_ACCUM(&parser
 
368
                                                          ->context
 
369
                                                          ->runtime
 
370
                                                          ->lexicalScopeDepthStats,
 
371
                                                        maxScopeDepth));
 
372
    }
 
373
 
 
374
    uintN blockid() { return topStmt ? topStmt->blockid : bodyid; }
 
375
 
 
376
    JSObject *blockChain() {
 
377
        return blockChainBox ? blockChainBox->object : NULL;
 
378
    }
 
379
 
 
380
    /*
 
381
     * True if we are at the topmost level of a entire script or function body.
 
382
     * For example, while parsing this code we would encounter f1 and f2 at
 
383
     * body level, but we would not encounter f3 or f4 at body level:
 
384
     *
 
385
     *   function f1() { function f2() { } }
 
386
     *   if (cond) { function f3() { if (cond) { function f4() { } } } }
 
387
     */
 
388
    bool atBodyLevel() { return !topStmt || (topStmt->flags & SIF_BODY_BLOCK); }
 
389
 
 
390
    /* Test whether we're in a statement of given type. */
 
391
    bool inStatement(JSStmtType type);
 
392
 
 
393
    bool inStrictMode() const {
 
394
        return flags & TCF_STRICT_MODE_CODE;
 
395
    }
 
396
 
 
397
    inline bool needStrictChecks();
 
398
 
 
399
    /* 
 
400
     * sharpSlotBase is -1 or first slot of pair for [sharpArray, sharpDepth].
 
401
     * The parser calls ensureSharpSlots to allocate these two stack locals.
 
402
     */
 
403
    int sharpSlotBase;
 
404
    bool ensureSharpSlots();
 
405
 
 
406
    js::Compiler *compiler() { return (js::Compiler *)parser; }
 
407
 
 
408
    // Return true there is a generator function within |skip| lexical scopes
 
409
    // (going upward) from this context's lexical scope. Always return true if
 
410
    // this context is itself a generator.
 
411
    bool skipSpansGenerator(unsigned skip);
 
412
 
 
413
    bool compileAndGo() const { return flags & TCF_COMPILE_N_GO; }
 
414
    bool inFunction() const { return flags & TCF_IN_FUNCTION; }
 
415
 
 
416
    bool compiling() const { return flags & TCF_COMPILING; }
 
417
    inline JSCodeGenerator *asCodeGenerator();
 
418
 
 
419
    bool usesArguments() const {
 
420
        return flags & TCF_FUN_USES_ARGUMENTS;
 
421
    }
 
422
 
 
423
    void noteCallsEval() {
 
424
        flags |= TCF_FUN_CALLS_EVAL;
 
425
    }
 
426
 
 
427
    bool callsEval() const {
 
428
        return flags & TCF_FUN_CALLS_EVAL;
 
429
    }
 
430
 
 
431
    void noteMightAliasLocals() {
 
432
        flags |= TCF_FUN_MIGHT_ALIAS_LOCALS;
 
433
    }
 
434
 
 
435
    bool mightAliasLocals() const {
 
436
        return flags & TCF_FUN_MIGHT_ALIAS_LOCALS;
 
437
    }
 
438
 
 
439
    void noteParameterMutation() {
 
440
        JS_ASSERT(inFunction());
 
441
        flags |= TCF_FUN_MUTATES_PARAMETER;
 
442
    }
 
443
 
 
444
    bool mutatesParameter() const {
 
445
        JS_ASSERT(inFunction());
 
446
        return flags & TCF_FUN_MUTATES_PARAMETER;
 
447
    }
 
448
 
 
449
    void noteArgumentsUse() {
 
450
        JS_ASSERT(inFunction());
 
451
        flags |= TCF_FUN_USES_ARGUMENTS;
 
452
        if (funbox)
 
453
            funbox->node->pn_dflags |= PND_FUNARG;
 
454
    }
 
455
 
 
456
    bool needsEagerArguments() const {
 
457
        return inStrictMode() && ((usesArguments() && mutatesParameter()) || callsEval());
 
458
    }
 
459
};
 
460
 
 
461
/*
 
462
 * Return true if we need to check for conditions that elicit
 
463
 * JSOPTION_STRICT warnings or strict mode errors.
 
464
 */
 
465
inline bool JSTreeContext::needStrictChecks() {
 
466
    return parser->context->hasStrictOption() || inStrictMode();
 
467
}
 
468
 
 
469
/*
 
470
 * Span-dependent instructions are jumps whose span (from the jump bytecode to
 
471
 * the jump target) may require 2 or 4 bytes of immediate operand.
 
472
 */
 
473
typedef struct JSSpanDep    JSSpanDep;
 
474
typedef struct JSJumpTarget JSJumpTarget;
 
475
 
 
476
struct JSSpanDep {
 
477
    ptrdiff_t       top;        /* offset of first bytecode in an opcode */
 
478
    ptrdiff_t       offset;     /* offset - 1 within opcode of jump operand */
 
479
    ptrdiff_t       before;     /* original offset - 1 of jump operand */
 
480
    JSJumpTarget    *target;    /* tagged target pointer or backpatch delta */
 
481
};
 
482
 
 
483
/*
 
484
 * Jump targets are stored in an AVL tree, for O(log(n)) lookup with targets
 
485
 * sorted by offset from left to right, so that targets after a span-dependent
 
486
 * instruction whose jump offset operand must be extended can be found quickly
 
487
 * and adjusted upward (toward higher offsets).
 
488
 */
 
489
struct JSJumpTarget {
 
490
    ptrdiff_t       offset;     /* offset of span-dependent jump target */
 
491
    int             balance;    /* AVL tree balance number */
 
492
    JSJumpTarget    *kids[2];   /* left and right AVL tree child pointers */
 
493
};
 
494
 
 
495
#define JT_LEFT                 0
 
496
#define JT_RIGHT                1
 
497
#define JT_OTHER_DIR(dir)       (1 - (dir))
 
498
#define JT_IMBALANCE(dir)       (((dir) << 1) - 1)
 
499
#define JT_DIR(imbalance)       (((imbalance) + 1) >> 1)
 
500
 
 
501
/*
 
502
 * Backpatch deltas are encoded in JSSpanDep.target if JT_TAG_BIT is clear,
 
503
 * so we can maintain backpatch chains when using span dependency records to
 
504
 * hold jump offsets that overflow 16 bits.
 
505
 */
 
506
#define JT_TAG_BIT              ((jsword) 1)
 
507
#define JT_UNTAG_SHIFT          1
 
508
#define JT_SET_TAG(jt)          ((JSJumpTarget *)((jsword)(jt) | JT_TAG_BIT))
 
509
#define JT_CLR_TAG(jt)          ((JSJumpTarget *)((jsword)(jt) & ~JT_TAG_BIT))
 
510
#define JT_HAS_TAG(jt)          ((jsword)(jt) & JT_TAG_BIT)
 
511
 
 
512
#define BITS_PER_PTRDIFF        (sizeof(ptrdiff_t) * JS_BITS_PER_BYTE)
 
513
#define BITS_PER_BPDELTA        (BITS_PER_PTRDIFF - 1 - JT_UNTAG_SHIFT)
 
514
#define BPDELTA_MAX             (((ptrdiff_t)1 << BITS_PER_BPDELTA) - 1)
 
515
#define BPDELTA_TO_JT(bp)       ((JSJumpTarget *)((bp) << JT_UNTAG_SHIFT))
 
516
#define JT_TO_BPDELTA(jt)       ((ptrdiff_t)((jsword)(jt) >> JT_UNTAG_SHIFT))
 
517
 
 
518
#define SD_SET_TARGET(sd,jt)    ((sd)->target = JT_SET_TAG(jt))
 
519
#define SD_GET_TARGET(sd)       (JS_ASSERT(JT_HAS_TAG((sd)->target)),         \
 
520
                                 JT_CLR_TAG((sd)->target))
 
521
#define SD_SET_BPDELTA(sd,bp)   ((sd)->target = BPDELTA_TO_JT(bp))
 
522
#define SD_GET_BPDELTA(sd)      (JS_ASSERT(!JT_HAS_TAG((sd)->target)),        \
 
523
                                 JT_TO_BPDELTA((sd)->target))
 
524
 
 
525
/* Avoid asserting twice by expanding SD_GET_TARGET in the "then" clause. */
 
526
#define SD_SPAN(sd,pivot)       (SD_GET_TARGET(sd)                            \
 
527
                                 ? JT_CLR_TAG((sd)->target)->offset - (pivot) \
 
528
                                 : 0)
 
529
 
 
530
typedef struct JSTryNode JSTryNode;
 
531
 
 
532
struct JSTryNode {
 
533
    JSTryNote       note;
 
534
    JSTryNode       *prev;
 
535
};
 
536
 
 
537
struct JSCGObjectList {
 
538
    uint32              length;     /* number of emitted so far objects */
 
539
    JSObjectBox         *lastbox;   /* last emitted object */
 
540
 
 
541
    JSCGObjectList() : length(0), lastbox(NULL) {}
 
542
 
 
543
    uintN index(JSObjectBox *objbox);
 
544
    void finish(JSObjectArray *array);
 
545
};
 
546
 
 
547
class JSGCConstList {
 
548
    js::Vector<js::Value> list;
 
549
  public:
 
550
    JSGCConstList(JSContext *cx) : list(cx) {}
 
551
    bool append(js::Value v) { return list.append(v); }
 
552
    size_t length() const { return list.length(); }
 
553
    void finish(JSConstArray *array);
 
554
 
 
555
};
 
556
 
 
557
struct JSCodeGenerator : public JSTreeContext
 
558
{
 
559
    JSArenaPool     *codePool;      /* pointer to thread code arena pool */
 
560
    JSArenaPool     *notePool;      /* pointer to thread srcnote arena pool */
 
561
    void            *codeMark;      /* low watermark in cg->codePool */
 
562
    void            *noteMark;      /* low watermark in cg->notePool */
 
563
 
 
564
    struct {
 
565
        jsbytecode  *base;          /* base of JS bytecode vector */
 
566
        jsbytecode  *limit;         /* one byte beyond end of bytecode */
 
567
        jsbytecode  *next;          /* pointer to next free bytecode */
 
568
        jssrcnote   *notes;         /* source notes, see below */
 
569
        uintN       noteCount;      /* number of source notes so far */
 
570
        uintN       noteMask;       /* growth increment for notes */
 
571
        ptrdiff_t   lastNoteOffset; /* code offset for last source note */
 
572
        uintN       currentLine;    /* line number for tree-based srcnote gen */
 
573
    } prolog, main, *current;
 
574
 
 
575
    JSAtomList      atomList;       /* literals indexed for mapping */
 
576
    uintN           firstLine;      /* first line, for js_NewScriptFromCG */
 
577
 
 
578
    intN            stackDepth;     /* current stack depth in script frame */
 
579
    uintN           maxStackDepth;  /* maximum stack depth so far */
 
580
 
 
581
    uintN           ntrynotes;      /* number of allocated so far try notes */
 
582
    JSTryNode       *lastTryNode;   /* the last allocated try node */
 
583
 
 
584
    JSSpanDep       *spanDeps;      /* span dependent instruction records */
 
585
    JSJumpTarget    *jumpTargets;   /* AVL tree of jump target offsets */
 
586
    JSJumpTarget    *jtFreeList;    /* JT_LEFT-linked list of free structs */
 
587
    uintN           numSpanDeps;    /* number of span dependencies */
 
588
    uintN           numJumpTargets; /* number of jump targets */
 
589
    ptrdiff_t       spanDepTodo;    /* offset from main.base of potentially
 
590
                                       unoptimized spandeps */
 
591
 
 
592
    uintN           arrayCompDepth; /* stack depth of array in comprehension */
 
593
 
 
594
    uintN           emitLevel;      /* js_EmitTree recursion level */
 
595
 
 
596
    typedef js::HashMap<JSAtom *, js::Value> ConstMap;
 
597
    ConstMap        constMap;       /* compile time constants */
 
598
 
 
599
    JSGCConstList   constList;      /* constants to be included with the script */
 
600
 
 
601
    JSCGObjectList  objectList;     /* list of emitted objects */
 
602
    JSCGObjectList  regexpList;     /* list of emitted regexp that will be
 
603
                                       cloned during execution */
 
604
 
 
605
    JSAtomList      upvarList;      /* map of atoms to upvar indexes */
 
606
    JSUpvarArray    upvarMap;       /* indexed upvar pairs (JS_realloc'ed) */
 
607
 
 
608
    typedef js::Vector<js::GlobalSlotArray::Entry, 16, js::ContextAllocPolicy> GlobalUseVector;
 
609
 
 
610
    GlobalUseVector globalUses;     /* per-script global uses */
 
611
    JSAtomList      globalMap;      /* per-script map of global name to globalUses vector */
 
612
 
 
613
    /* Vectors of pn_cookie slot values. */
 
614
    typedef js::Vector<uint32, 8, js::ContextAllocPolicy> SlotVector;
 
615
    SlotVector      closedArgs;
 
616
    SlotVector      closedVars;
 
617
 
 
618
    uint16          traceIndex;     /* index for the next JSOP_TRACE instruction */
 
619
 
 
620
    /*
 
621
     * Initialize cg to allocate bytecode space from codePool, source note
 
622
     * space from notePool, and all other arena-allocated temporaries from
 
623
     * parser->context->tempPool.
 
624
     */
 
625
    JSCodeGenerator(js::Parser *parser,
 
626
                    JSArenaPool *codePool, JSArenaPool *notePool,
 
627
                    uintN lineno);
 
628
    bool init();
 
629
 
 
630
    /*
 
631
     * Release cg->codePool, cg->notePool, and parser->context->tempPool to
 
632
     * marks set by JSCodeGenerator's ctor. Note that cgs are magic: they own
 
633
     * the arena pool "tops-of-stack" space above their codeMark, noteMark, and
 
634
     * tempMark points.  This means you cannot alloc from tempPool and save the
 
635
     * pointer beyond the next JSCodeGenerator destructor call.
 
636
     */
 
637
    ~JSCodeGenerator();
 
638
 
 
639
    /*
 
640
     * Adds a use of a variable that is statically known to exist on the
 
641
     * global object. 
 
642
     *
 
643
     * The actual slot of the variable on the global object is not known
 
644
     * until after compilation. Properties must be resolved before being
 
645
     * added, to avoid aliasing properties that should be resolved. This makes
 
646
     * slot prediction based on the global object's free slot impossible. So,
 
647
     * we use the slot to index into cg->globalScope->defs, and perform a
 
648
     * fixup of the script at the very end of compilation.
 
649
     *
 
650
     * If the global use can be cached, |cookie| will be set to |slot|.
 
651
     * Otherwise, |cookie| is set to the free cookie value.
 
652
     */
 
653
    bool addGlobalUse(JSAtom *atom, uint32 slot, js::UpvarCookie *cookie);
 
654
 
 
655
    bool hasSharps() const {
 
656
        bool rv = !!(flags & TCF_HAS_SHARPS);
 
657
        JS_ASSERT((sharpSlotBase >= 0) == rv);
 
658
        return rv;
 
659
    }
 
660
 
 
661
    uintN sharpSlots() const {
 
662
        return hasSharps() ? SHARP_NSLOTS : 0;
 
663
    }
 
664
 
 
665
    bool compilingForEval() const { return !!(flags & TCF_COMPILE_FOR_EVAL); }
 
666
    JSVersion version() const { return parser->versionWithFlags(); }
 
667
 
 
668
    bool shouldNoteClosedName(JSParseNode *pn);
 
669
 
 
670
    bool checkSingletonContext() {
 
671
        if (!compileAndGo() || inFunction())
 
672
            return false;
 
673
        for (JSStmtInfo *stmt = topStmt; stmt; stmt = stmt->down) {
 
674
            if (STMT_IS_LOOP(stmt))
 
675
                return false;
 
676
        }
 
677
        flags |= TCF_HAS_SINGLETONS;
 
678
        return true;
 
679
    }
 
680
};
 
681
 
 
682
#define CG_TS(cg)               TS((cg)->parser)
 
683
 
 
684
#define CG_BASE(cg)             ((cg)->current->base)
 
685
#define CG_LIMIT(cg)            ((cg)->current->limit)
 
686
#define CG_NEXT(cg)             ((cg)->current->next)
 
687
#define CG_CODE(cg,offset)      (CG_BASE(cg) + (offset))
 
688
#define CG_OFFSET(cg)           (CG_NEXT(cg) - CG_BASE(cg))
 
689
 
 
690
#define CG_NOTES(cg)            ((cg)->current->notes)
 
691
#define CG_NOTE_COUNT(cg)       ((cg)->current->noteCount)
 
692
#define CG_NOTE_MASK(cg)        ((cg)->current->noteMask)
 
693
#define CG_LAST_NOTE_OFFSET(cg) ((cg)->current->lastNoteOffset)
 
694
#define CG_CURRENT_LINE(cg)     ((cg)->current->currentLine)
 
695
 
 
696
#define CG_PROLOG_BASE(cg)      ((cg)->prolog.base)
 
697
#define CG_PROLOG_LIMIT(cg)     ((cg)->prolog.limit)
 
698
#define CG_PROLOG_NEXT(cg)      ((cg)->prolog.next)
 
699
#define CG_PROLOG_CODE(cg,poff) (CG_PROLOG_BASE(cg) + (poff))
 
700
#define CG_PROLOG_OFFSET(cg)    (CG_PROLOG_NEXT(cg) - CG_PROLOG_BASE(cg))
 
701
 
 
702
#define CG_SWITCH_TO_MAIN(cg)   ((cg)->current = &(cg)->main)
 
703
#define CG_SWITCH_TO_PROLOG(cg) ((cg)->current = &(cg)->prolog)
 
704
 
 
705
inline JSCodeGenerator *
 
706
JSTreeContext::asCodeGenerator()
 
707
{
 
708
    JS_ASSERT(compiling());
 
709
    return static_cast<JSCodeGenerator *>(this);
 
710
}
 
711
 
 
712
/*
 
713
 * Emit one bytecode.
 
714
 */
 
715
extern ptrdiff_t
 
716
js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op);
 
717
 
 
718
/*
 
719
 * Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1).
 
720
 */
 
721
extern ptrdiff_t
 
722
js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1);
 
723
 
 
724
/*
 
725
 * Emit three bytecodes, an opcode with two bytes of immediate operands.
 
726
 */
 
727
extern ptrdiff_t
 
728
js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
 
729
         jsbytecode op2);
 
730
 
 
731
/*
 
732
 * Emit five bytecodes, an opcode with two 16-bit immediates.
 
733
 */
 
734
extern ptrdiff_t
 
735
js_Emit5(JSContext *cx, JSCodeGenerator *cg, JSOp op, uint16 op1,
 
736
         uint16 op2);
 
737
 
 
738
/*
 
739
 * Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
 
740
 */
 
741
extern ptrdiff_t
 
742
js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra);
 
743
 
 
744
/*
 
745
 * Unsafe macro to call js_SetJumpOffset and return false if it does.
 
746
 */
 
747
#define CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,cg,pc,off,BAD_EXIT)               \
 
748
    JS_BEGIN_MACRO                                                            \
 
749
        if (!js_SetJumpOffset(cx, cg, pc, off)) {                             \
 
750
            BAD_EXIT;                                                         \
 
751
        }                                                                     \
 
752
    JS_END_MACRO
 
753
 
 
754
#define CHECK_AND_SET_JUMP_OFFSET(cx,cg,pc,off)                               \
 
755
    CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,cg,pc,off,return JS_FALSE)
 
756
 
 
757
#define CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx,cg,off,BAD_EXIT)               \
 
758
    CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx, cg, CG_CODE(cg,off),                 \
 
759
                                     CG_OFFSET(cg) - (off), BAD_EXIT)
 
760
 
 
761
#define CHECK_AND_SET_JUMP_OFFSET_AT(cx,cg,off)                               \
 
762
    CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx, cg, off, return JS_FALSE)
 
763
 
 
764
extern JSBool
 
765
js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
 
766
                 ptrdiff_t off);
 
767
 
 
768
/*
 
769
 * Push the C-stack-allocated struct at stmt onto the stmtInfo stack.
 
770
 */
 
771
extern void
 
772
js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
 
773
                 ptrdiff_t top);
 
774
 
 
775
/*
 
776
 * Push a block scope statement and link blockObj into tc->blockChain. To pop
 
777
 * this statement info record, use js_PopStatement as usual, or if appropriate
 
778
 * (if generating code), js_PopStatementCG.
 
779
 */
 
780
extern void
 
781
js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObjectBox *blockBox,
 
782
                  ptrdiff_t top);
 
783
 
 
784
/*
 
785
 * Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it
 
786
 * is up to the caller to free it.
 
787
 */
 
788
extern void
 
789
js_PopStatement(JSTreeContext *tc);
 
790
 
 
791
/*
 
792
 * Like js_PopStatement(cg), also patch breaks and continues unless the top
 
793
 * statement info record represents a try-catch-finally suite. May fail if a
 
794
 * jump offset overflows.
 
795
 */
 
796
extern JSBool
 
797
js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);
 
798
 
 
799
/*
 
800
 * Define and lookup a primitive jsval associated with the const named by atom.
 
801
 * js_DefineCompileTimeConstant analyzes the constant-folded initializer at pn
 
802
 * and saves the const's value in cg->constList, if it can be used at compile
 
803
 * time. It returns true unless an error occurred.
 
804
 *
 
805
 * If the initializer's value could not be saved, js_DefineCompileTimeConstant
 
806
 * calls will return the undefined value. js_DefineCompileTimeConstant tries
 
807
 * to find a const value memorized for atom, returning true with *vp set to a
 
808
 * value other than undefined if the constant was found, true with *vp set to
 
809
 * JSVAL_VOID if not found, and false on error.
 
810
 */
 
811
extern JSBool
 
812
js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
 
813
                             JSParseNode *pn);
 
814
 
 
815
/*
 
816
 * Find a lexically scoped variable (one declared by let, catch, or an array
 
817
 * comprehension) named by atom, looking in tc's compile-time scopes.
 
818
 *
 
819
 * If a WITH statement is reached along the scope stack, return its statement
 
820
 * info record, so callers can tell that atom is ambiguous. If slotp is not
 
821
 * null, then if atom is found, set *slotp to its stack slot, otherwise to -1.
 
822
 * This means that if slotp is not null, all the block objects on the lexical
 
823
 * scope chain must have had their depth slots computed by the code generator,
 
824
 * so the caller must be under js_EmitTree.
 
825
 *
 
826
 * In any event, directly return the statement info record in which atom was
 
827
 * found. Otherwise return null.
 
828
 */
 
829
extern JSStmtInfo *
 
830
js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp,
 
831
                 JSStmtInfo *stmt = NULL);
 
832
 
 
833
/*
 
834
 * Emit code into cg for the tree rooted at pn.
 
835
 */
 
836
extern JSBool
 
837
js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
 
838
 
 
839
/*
 
840
 * Emit function code using cg for the tree rooted at body.
 
841
 */
 
842
extern JSBool
 
843
js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body);
 
844
 
 
845
/*
 
846
 * Source notes generated along with bytecode for decompiling and debugging.
 
847
 * A source note is a uint8 with 5 bits of type and 3 of offset from the pc of
 
848
 * the previous note. If 3 bits of offset aren't enough, extended delta notes
 
849
 * (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
 
850
 * are emitted before the next note. Some notes have operand offsets encoded
 
851
 * immediately after them, in note bytes or byte-triples.
 
852
 *
 
853
 *                 Source Note               Extended Delta
 
854
 *              +7-6-5-4-3+2-1-0+           +7-6-5+4-3-2-1-0+
 
855
 *              |note-type|delta|           |1 1| ext-delta |
 
856
 *              +---------+-----+           +---+-----------+
 
857
 *
 
858
 * At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE,
 
859
 * SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
 
860
 *
 
861
 * NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its
 
862
 * initializers need to match the order here.
 
863
 *
 
864
 * Note on adding new source notes: every pair of bytecodes (A, B) where A and
 
865
 * B have disjoint sets of source notes that could apply to each bytecode may
 
866
 * reuse the same note type value for two notes (snA, snB) that have the same
 
867
 * arity, offsetBias, and isSpanDep initializers in js_SrcNoteSpec. This is
 
868
 * why SRC_IF and SRC_INITPROP have the same value below. For bad historical
 
869
 * reasons, some bytecodes below that could be overlayed have not been, but
 
870
 * before using SRC_EXTENDED, consider compressing the existing note types.
 
871
 *
 
872
 * Don't forget to update JSXDR_BYTECODE_VERSION in jsxdrapi.h for all such
 
873
 * incompatible source note or other bytecode changes.
 
874
 */
 
875
typedef enum JSSrcNoteType {
 
876
    SRC_NULL        = 0,        /* terminates a note vector */
 
877
    SRC_IF          = 1,        /* JSOP_IFEQ bytecode is from an if-then */
 
878
    SRC_BREAK       = 1,        /* JSOP_GOTO is a break */
 
879
    SRC_INITPROP    = 1,        /* disjoint meaning applied to JSOP_INITELEM or
 
880
                                   to an index label in a regular (structuring)
 
881
                                   or a destructuring object initialiser */
 
882
    SRC_GENEXP      = 1,        /* JSOP_LAMBDA from generator expression */
 
883
    SRC_IF_ELSE     = 2,        /* JSOP_IFEQ bytecode is from an if-then-else */
 
884
    SRC_FOR_IN      = 2,        /* JSOP_GOTO to for-in loop condition from
 
885
                                   before loop (same arity as SRC_IF_ELSE) */
 
886
    SRC_FOR         = 3,        /* JSOP_NOP or JSOP_POP in for(;;) loop head */
 
887
    SRC_WHILE       = 4,        /* JSOP_GOTO to for or while loop condition
 
888
                                   from before loop, else JSOP_NOP at top of
 
889
                                   do-while loop */
 
890
    SRC_TRACE       = 4,        /* For JSOP_TRACE; includes distance to loop end */
 
891
    SRC_CONTINUE    = 5,        /* JSOP_GOTO is a continue, not a break;
 
892
                                   also used on JSOP_ENDINIT if extra comma
 
893
                                   at end of array literal: [1,2,,];
 
894
                                   JSOP_DUP continuing destructuring pattern */
 
895
    SRC_DECL        = 6,        /* type of a declaration (var, const, let*) */
 
896
    SRC_DESTRUCT    = 6,        /* JSOP_DUP starting a destructuring assignment
 
897
                                   operation, with SRC_DECL_* offset operand */
 
898
    SRC_PCDELTA     = 7,        /* distance forward from comma-operator to
 
899
                                   next POP, or from CONDSWITCH to first CASE
 
900
                                   opcode, etc. -- always a forward delta */
 
901
    SRC_GROUPASSIGN = 7,        /* SRC_DESTRUCT variant for [a, b] = [c, d] */
 
902
    SRC_ASSIGNOP    = 8,        /* += or another assign-op follows */
 
903
    SRC_COND        = 9,        /* JSOP_IFEQ is from conditional ?: operator */
 
904
    SRC_BRACE       = 10,       /* mandatory brace, for scope or to avoid
 
905
                                   dangling else */
 
906
    SRC_HIDDEN      = 11,       /* opcode shouldn't be decompiled */
 
907
    SRC_PCBASE      = 12,       /* distance back from annotated getprop or
 
908
                                   setprop op to left-most obj.prop.subprop
 
909
                                   bytecode -- always a backward delta */
 
910
    SRC_LABEL       = 13,       /* JSOP_NOP for label: with atomid immediate */
 
911
    SRC_LABELBRACE  = 14,       /* JSOP_NOP for label: {...} begin brace */
 
912
    SRC_ENDBRACE    = 15,       /* JSOP_NOP for label: {...} end brace */
 
913
    SRC_BREAK2LABEL = 16,       /* JSOP_GOTO for 'break label' with atomid */
 
914
    SRC_CONT2LABEL  = 17,       /* JSOP_GOTO for 'continue label' with atomid */
 
915
    SRC_SWITCH      = 18,       /* JSOP_*SWITCH with offset to end of switch,
 
916
                                   2nd off to first JSOP_CASE if condswitch */
 
917
    SRC_FUNCDEF     = 19,       /* JSOP_NOP for function f() with atomid */
 
918
    SRC_CATCH       = 20,       /* catch block has guard */
 
919
    SRC_EXTENDED    = 21,       /* extended source note, 32-159, in next byte */
 
920
    SRC_NEWLINE     = 22,       /* bytecode follows a source newline */
 
921
    SRC_SETLINE     = 23,       /* a file-absolute source line number note */
 
922
    SRC_XDELTA      = 24        /* 24-31 are for extended delta notes */
 
923
} JSSrcNoteType;
 
924
 
 
925
/*
 
926
 * Constants for the SRC_DECL source note. Note that span-dependent bytecode
 
927
 * selection means that any SRC_DECL offset greater than SRC_DECL_LET may need
 
928
 * to be adjusted, but these "offsets" are too small to span a span-dependent
 
929
 * instruction, so can be used to denote distinct declaration syntaxes to the
 
930
 * decompiler.
 
931
 *
 
932
 * NB: the var_prefix array in jsopcode.c depends on these dense indexes from
 
933
 * SRC_DECL_VAR through SRC_DECL_LET.
 
934
 */
 
935
#define SRC_DECL_VAR            0
 
936
#define SRC_DECL_CONST          1
 
937
#define SRC_DECL_LET            2
 
938
#define SRC_DECL_NONE           3
 
939
 
 
940
#define SN_TYPE_BITS            5
 
941
#define SN_DELTA_BITS           3
 
942
#define SN_XDELTA_BITS          6
 
943
#define SN_TYPE_MASK            (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS)
 
944
#define SN_DELTA_MASK           ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS))
 
945
#define SN_XDELTA_MASK          ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS))
 
946
 
 
947
#define SN_MAKE_NOTE(sn,t,d)    (*(sn) = (jssrcnote)                          \
 
948
                                          (((t) << SN_DELTA_BITS)             \
 
949
                                           | ((d) & SN_DELTA_MASK)))
 
950
#define SN_MAKE_XDELTA(sn,d)    (*(sn) = (jssrcnote)                          \
 
951
                                          ((SRC_XDELTA << SN_DELTA_BITS)      \
 
952
                                           | ((d) & SN_XDELTA_MASK)))
 
953
 
 
954
#define SN_IS_XDELTA(sn)        ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA)
 
955
#define SN_TYPE(sn)             ((JSSrcNoteType)(SN_IS_XDELTA(sn)             \
 
956
                                                 ? SRC_XDELTA                 \
 
957
                                                 : *(sn) >> SN_DELTA_BITS))
 
958
#define SN_SET_TYPE(sn,type)    SN_MAKE_NOTE(sn, type, SN_DELTA(sn))
 
959
#define SN_IS_GETTABLE(sn)      (SN_TYPE(sn) < SRC_NEWLINE)
 
960
 
 
961
#define SN_DELTA(sn)            ((ptrdiff_t)(SN_IS_XDELTA(sn)                 \
 
962
                                             ? *(sn) & SN_XDELTA_MASK         \
 
963
                                             : *(sn) & SN_DELTA_MASK))
 
964
#define SN_SET_DELTA(sn,delta)  (SN_IS_XDELTA(sn)                             \
 
965
                                 ? SN_MAKE_XDELTA(sn, delta)                  \
 
966
                                 : SN_MAKE_NOTE(sn, SN_TYPE(sn), delta))
 
967
 
 
968
#define SN_DELTA_LIMIT          ((ptrdiff_t)JS_BIT(SN_DELTA_BITS))
 
969
#define SN_XDELTA_LIMIT         ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS))
 
970
 
 
971
/*
 
972
 * Offset fields follow certain notes and are frequency-encoded: an offset in
 
973
 * [0,0x7f] consumes one byte, an offset in [0x80,0x7fffff] takes three, and
 
974
 * the high bit of the first byte is set.
 
975
 */
 
976
#define SN_3BYTE_OFFSET_FLAG    0x80
 
977
#define SN_3BYTE_OFFSET_MASK    0x7f
 
978
 
 
979
typedef struct JSSrcNoteSpec {
 
980
    const char      *name;      /* name for disassembly/debugging output */
 
981
    int8            arity;      /* number of offset operands */
 
982
    uint8           offsetBias; /* bias of offset(s) from annotated pc */
 
983
    int8            isSpanDep;  /* 1 or -1 if offsets could span extended ops,
 
984
                                   0 otherwise; sign tells span direction */
 
985
} JSSrcNoteSpec;
 
986
 
 
987
extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[];
 
988
extern JS_FRIEND_API(uintN)          js_SrcNoteLength(jssrcnote *sn);
 
989
 
 
990
#define SN_LENGTH(sn)           ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \
 
991
                                 : js_SrcNoteLength(sn))
 
992
#define SN_NEXT(sn)             ((sn) + SN_LENGTH(sn))
 
993
 
 
994
/* A source note array is terminated by an all-zero element. */
 
995
#define SN_MAKE_TERMINATOR(sn)  (*(sn) = SRC_NULL)
 
996
#define SN_IS_TERMINATOR(sn)    (*(sn) == SRC_NULL)
 
997
 
 
998
/*
 
999
 * Append a new source note of the given type (and therefore size) to cg's
 
1000
 * notes dynamic array, updating cg->noteCount. Return the new note's index
 
1001
 * within the array pointed at by cg->current->notes. Return -1 if out of
 
1002
 * memory.
 
1003
 */
 
1004
extern intN
 
1005
js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type);
 
1006
 
 
1007
extern intN
 
1008
js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
 
1009
               ptrdiff_t offset);
 
1010
 
 
1011
extern intN
 
1012
js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
 
1013
               ptrdiff_t offset1, ptrdiff_t offset2);
 
1014
 
 
1015
/*
 
1016
 * NB: this function can add at most one extra extended delta note.
 
1017
 */
 
1018
extern jssrcnote *
 
1019
js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn,
 
1020
                     ptrdiff_t delta);
 
1021
 
 
1022
/*
 
1023
 * Get and set the offset operand identified by which (0 for the first, etc.).
 
1024
 */
 
1025
extern JS_FRIEND_API(ptrdiff_t)
 
1026
js_GetSrcNoteOffset(jssrcnote *sn, uintN which);
 
1027
 
 
1028
extern JSBool
 
1029
js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
 
1030
                    uintN which, ptrdiff_t offset);
 
1031
 
 
1032
/*
 
1033
 * Finish taking source notes in cx's notePool, copying final notes to the new
 
1034
 * stable store allocated by the caller and passed in via notes. Return false
 
1035
 * on malloc failure, which means this function reported an error.
 
1036
 *
 
1037
 * To compute the number of jssrcnotes to allocate and pass in via notes, use
 
1038
 * the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of
 
1039
 * js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes
 
1040
 * FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES!
 
1041
 */
 
1042
#define CG_COUNT_FINAL_SRCNOTES(cg, cnt)                                      \
 
1043
    JS_BEGIN_MACRO                                                            \
 
1044
        ptrdiff_t diff_ = CG_PROLOG_OFFSET(cg) - (cg)->prolog.lastNoteOffset; \
 
1045
        cnt = (cg)->prolog.noteCount + (cg)->main.noteCount + 1;              \
 
1046
        if ((cg)->prolog.noteCount &&                                         \
 
1047
            (cg)->prolog.currentLine != (cg)->firstLine) {                    \
 
1048
            if (diff_ > SN_DELTA_MASK)                                        \
 
1049
                cnt += JS_HOWMANY(diff_ - SN_DELTA_MASK, SN_XDELTA_MASK);     \
 
1050
            cnt += 2 + (((cg)->firstLine > SN_3BYTE_OFFSET_MASK) << 1);       \
 
1051
        } else if (diff_ > 0) {                                               \
 
1052
            if (cg->main.noteCount) {                                         \
 
1053
                jssrcnote *sn_ = (cg)->main.notes;                            \
 
1054
                diff_ -= SN_IS_XDELTA(sn_)                                    \
 
1055
                         ? SN_XDELTA_MASK - (*sn_ & SN_XDELTA_MASK)           \
 
1056
                         : SN_DELTA_MASK - (*sn_ & SN_DELTA_MASK);            \
 
1057
            }                                                                 \
 
1058
            if (diff_ > 0)                                                    \
 
1059
                cnt += JS_HOWMANY(diff_, SN_XDELTA_MASK);                     \
 
1060
        }                                                                     \
 
1061
    JS_END_MACRO
 
1062
 
 
1063
extern JSBool
 
1064
js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes);
 
1065
 
 
1066
extern void
 
1067
js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array);
 
1068
 
 
1069
JS_END_EXTERN_C
 
1070
 
 
1071
#endif /* jsemit_h___ */