Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / jsemit.h
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___ */