/[jscoverage]/trunk/js/jsemit.h
ViewVC logotype

Diff of /trunk/js/jsemit.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 399 by siliconforks, Tue Dec 9 03:37:47 2008 UTC revision 460 by siliconforks, Sat Sep 26 23:15:22 2009 UTC
# Line 48  Line 48 
48  #include "jstypes.h"  #include "jstypes.h"
49  #include "jsatom.h"  #include "jsatom.h"
50  #include "jsopcode.h"  #include "jsopcode.h"
51    #include "jsparse.h"
52  #include "jsscript.h"  #include "jsscript.h"
53  #include "jsprvtd.h"  #include "jsprvtd.h"
54  #include "jspubtd.h"  #include "jspubtd.h"
# Line 125  Line 126 
126  struct JSStmtInfo {  struct JSStmtInfo {
127      uint16          type;           /* statement type */      uint16          type;           /* statement type */
128      uint16          flags;          /* flags, see below */      uint16          flags;          /* flags, see below */
129        uint32          blockid;        /* for simplified dominance computation */
130      ptrdiff_t       update;         /* loop update offset (top if none) */      ptrdiff_t       update;         /* loop update offset (top if none) */
131      ptrdiff_t       breaks;         /* offset of last break in loop */      ptrdiff_t       breaks;         /* offset of last break in loop */
132      ptrdiff_t       continues;      /* offset of last continue in loop */      ptrdiff_t       continues;      /* offset of last continue in loop */
133      union {      union {
134          JSAtom      *label;         /* name of LABEL */          JSAtom      *label;         /* name of LABEL */
135          JSObject    *blockObj;      /* block scope object */          JSObject    *blockObj;      /* block scope object */
136      } u;      };
137      JSStmtInfo      *down;          /* info for enclosing statement */      JSStmtInfo      *down;          /* info for enclosing statement */
138      JSStmtInfo      *downScope;     /* next enclosing lexical scope */      JSStmtInfo      *downScope;     /* next enclosing lexical scope */
139  };  };
# Line 152  Line 154 
154  #define GOSUBS(stmt)     ((stmt).breaks)  #define GOSUBS(stmt)     ((stmt).breaks)
155  #define GUARDJUMP(stmt)  ((stmt).continues)  #define GUARDJUMP(stmt)  ((stmt).continues)
156    
 #define AT_TOP_LEVEL(tc)                                                      \  
     (!(tc)->topStmt || ((tc)->topStmt->flags & SIF_BODY_BLOCK))  
   
157  #define SET_STATEMENT_TOP(stmt, top)                                          \  #define SET_STATEMENT_TOP(stmt, top)                                          \
158      ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))      ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
159    
160    #ifdef JS_SCOPE_DEPTH_METER
161    # define JS_SCOPE_DEPTH_METERING(code) ((void) (code))
162    #else
163    # define JS_SCOPE_DEPTH_METERING(code) ((void) 0)
164    #endif
165    
166  struct JSTreeContext {              /* tree context for semantic checks */  struct JSTreeContext {              /* tree context for semantic checks */
167      uint16          flags;          /* statement state flags, see below */      uint16          flags;          /* statement state flags, see below */
168      uint16          ngvars;         /* max. no. of global variables/regexps */      uint16          ngvars;         /* max. no. of global variables/regexps */
169        uint32          bodyid;         /* block number of program/function body */
170        uint32          blockidGen;     /* preincremented block number generator */
171      JSStmtInfo      *topStmt;       /* top of statement info stack */      JSStmtInfo      *topStmt;       /* top of statement info stack */
172      JSStmtInfo      *topScopeStmt;  /* top lexical scope statement */      JSStmtInfo      *topScopeStmt;  /* top lexical scope statement */
173      JSObject        *blockChain;    /* compile time block scope chain (NB: one      JSObject        *blockChain;    /* compile time block scope chain (NB: one
174                                         deeper than the topScopeStmt/downScope                                         deeper than the topScopeStmt/downScope
175                                         chain when in head of let block/expr) */                                         chain when in head of let block/expr) */
176      JSParseNode     *blockNode;     /* parse node for a lexical scope.      JSParseNode     *blockNode;     /* parse node for a block with let declarations
177                                         XXX combine with blockChain? */                                         (block with its own lexical scope)  */
178      JSAtomList      decls;          /* function, const, and var declarations */      JSAtomList      decls;          /* function, const, and var declarations */
179      JSParseContext  *parseContext;      JSCompiler      *compiler;      /* ptr to common parsing and lexing data */
180    
181      union {      union {
   
182          JSFunction  *fun;           /* function to store argument and variable          JSFunction  *fun;           /* function to store argument and variable
183                                         names when flags & TCF_IN_FUNCTION */                                         names when flags & TCF_IN_FUNCTION */
184          JSObject    *scopeChain;    /* scope chain object for the script */          JSObject    *scopeChain;    /* scope chain object for the script */
185      } u;      };
186    
187        JSAtomList      lexdeps;        /* unresolved lexical name dependencies */
188        JSTreeContext   *parent;        /* enclosing function or global context */
189        uintN           staticLevel;    /* static compilation unit nesting level */
190    
191        JSFunctionBox   *funbox;        /* null or box for function we're compiling
192                                           if (flags & TCF_IN_FUNCTION) and not in
193                                           JSCompiler::compileFunctionBody */
194        JSFunctionBox   *functionList;
195    
196  #ifdef JS_SCOPE_DEPTH_METER  #ifdef JS_SCOPE_DEPTH_METER
197      uint16          scopeDepth;     /* current lexical scope chain depth */      uint16          scopeDepth;     /* current lexical scope chain depth */
198      uint16          maxScopeDepth;  /* maximum lexical scope chain depth */      uint16          maxScopeDepth;  /* maximum lexical scope chain depth */
199  #endif  #endif
200    
201        JSTreeContext(JSCompiler *jsc)
202          : flags(0), ngvars(0), bodyid(0), blockidGen(0),
203            topStmt(NULL), topScopeStmt(NULL), blockChain(NULL), blockNode(NULL),
204            compiler(jsc), scopeChain(NULL), parent(NULL), staticLevel(0),
205            funbox(NULL), functionList(NULL)
206        {
207            JS_SCOPE_DEPTH_METERING(scopeDepth = maxScopeDepth = 0);
208        }
209    
210        /*
211         * For functions the tree context is constructed and destructed a second
212         * time during code generation. To avoid a redundant stats update in such
213         * cases, we store (uintN) -1 in maxScopeDepth.
214         */
215        ~JSTreeContext() {
216            JS_SCOPE_DEPTH_METERING(maxScopeDepth == (uintN) -1 ||
217                                    JS_BASIC_STATS_ACCUM(&compiler
218                                                           ->context
219                                                           ->runtime
220                                                           ->lexicalScopeDepthStats,
221                                                         maxScopeDepth));
222        }
223    
224        uintN blockid() { return topStmt ? topStmt->blockid : bodyid; }
225    
226        bool atTopLevel() { return !topStmt || (topStmt->flags & SIF_BODY_BLOCK); }
227    
228        /* Test whether we're in a statement of given type. */
229        bool inStatement(JSStmtType type);
230  };  };
231    
 #define TCF_IN_FUNCTION        0x01 /* parsing inside function body */  
 #define TCF_RETURN_EXPR        0x02 /* function has 'return expr;' */  
 #define TCF_RETURN_VOID        0x04 /* function has 'return;' */  
 #define TCF_IN_FOR_INIT        0x08 /* parsing init expr of for; exclude 'in' */  
 #define TCF_FUN_CLOSURE_VS_VAR 0x10 /* function and var with same name */  
 #define TCF_FUN_USES_NONLOCALS 0x20 /* function refers to non-local names */  
 #define TCF_FUN_HEAVYWEIGHT    0x40 /* function needs Call object per call */  
 #define TCF_FUN_IS_GENERATOR   0x80 /* parsed yield statement in function */  
 #define TCF_HAS_DEFXMLNS      0x100 /* default xml namespace = ...; parsed */  
 #define TCF_HAS_FUNCTION_STMT 0x200 /* block contains a function statement */  
 #define TCF_GENEXP_LAMBDA     0x400 /* flag lambda from generator expression */  
 #define TCF_COMPILE_N_GO      0x800 /* compiler-and-go mode of script, can  
                                        optimize name references based on scope  
                                        chain */  
 #define TCF_NO_SCRIPT_RVAL   0x1000 /* API caller does not want result value  
                                        from global script */  
232  /*  /*
233   * Flags to propagate out of the blocks.   * Flags to propagate out of the blocks.
234   */   */
235  #define TCF_RETURN_FLAGS        (TCF_RETURN_EXPR | TCF_RETURN_VOID)  #define TCF_RETURN_FLAGS        (TCF_RETURN_EXPR | TCF_RETURN_VOID)
236    
237  /*  /*
238   * Flags to propagate from FunctionBody.   * TreeContext flags must fit in 16 bits, and all bits are in use now. Widening
239   */   * requires changing JSFunctionBox.tcflags too and repacking. Alternative fix
240  #define TCF_FUN_FLAGS           (TCF_FUN_IS_GENERATOR   |                     \   * gets rid of flags, probably starting with TCF_HAS_FUNCTION_STMT.
241                                   TCF_FUN_HEAVYWEIGHT    |                     \   */
242                                   TCF_FUN_USES_NONLOCALS |                     \  #define TCF_COMPILING           0x01 /* JSTreeContext is JSCodeGenerator */
243                                   TCF_FUN_CLOSURE_VS_VAR)  #define TCF_IN_FUNCTION         0x02 /* parsing inside function body */
244    #define TCF_RETURN_EXPR         0x04 /* function has 'return expr;' */
245    #define TCF_RETURN_VOID         0x08 /* function has 'return;' */
246    #define TCF_IN_FOR_INIT         0x10 /* parsing init expr of for; exclude 'in' */
247    #define TCF_FUN_SETS_OUTER_NAME 0x20 /* function set outer name (lexical or free) */
248    #define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */
249    #define TCF_FUN_USES_ARGUMENTS  0x80 /* function uses arguments except as a
250                                            parameter name */
251    #define TCF_FUN_HEAVYWEIGHT    0x100 /* function needs Call object per call */
252    #define TCF_FUN_IS_GENERATOR   0x200 /* parsed yield statement in function */
253    #define TCF_FUN_IS_FUNARG      0x400 /* function escapes as an argument, return
254                                            value, or via the heap */
255    #define TCF_HAS_FUNCTION_STMT  0x800 /* block contains a function statement */
256    #define TCF_GENEXP_LAMBDA     0x1000 /* flag lambda from generator expression */
257    #define TCF_COMPILE_N_GO      0x2000 /* compiler-and-go mode of script, can
258                                            optimize name references based on scope
259                                            chain */
260    #define TCF_NO_SCRIPT_RVAL    0x4000 /* API caller does not want result value
261                                            from global script */
262    #define TCF_HAS_SHARPS        0x8000 /* source contains sharp defs or uses */
263    
264    /*
265     * Sticky deoptimization flags to propagate from FunctionBody.
266     */
267    #define TCF_FUN_FLAGS           (TCF_FUN_SETS_OUTER_NAME |                    \
268                                     TCF_FUN_USES_ARGUMENTS  |                    \
269                                     TCF_FUN_PARAM_ARGUMENTS |                    \
270                                     TCF_FUN_HEAVYWEIGHT     |                    \
271                                     TCF_FUN_IS_GENERATOR    |                    \
272                                     TCF_FUN_IS_FUNARG       |                    \
273                                     TCF_HAS_SHARPS)
274    
275  /*  /*
276   * Flags field, not stored in JSTreeContext.flags, for passing staticDepth   * Flags field, not stored in JSTreeContext.flags, for passing a static level
277   * into js_CompileScript.   * into js_CompileScript.
278   */   */
279  #define TCF_STATIC_DEPTH_MASK   0xffff0000  #define TCF_STATIC_LEVEL_MASK   0xffff0000
280  #define TCF_GET_STATIC_DEPTH(f) ((uint32)(f) >> 16)  #define TCF_GET_STATIC_LEVEL(f) ((uint32)(f) >> 16)
281  #define TCF_PUT_STATIC_DEPTH(d) ((uint16)(d) << 16)  #define TCF_PUT_STATIC_LEVEL(d) ((uint16)(d) << 16)
   
 #ifdef JS_SCOPE_DEPTH_METER  
 # define JS_SCOPE_DEPTH_METERING(code) ((void) (code))  
 #else  
 # define JS_SCOPE_DEPTH_METERING(code) ((void) 0)  
 #endif  
   
 #define TREE_CONTEXT_INIT(tc, pc)                                             \  
     ((tc)->flags = (tc)->ngvars = 0,                                          \  
      (tc)->topStmt = (tc)->topScopeStmt = NULL,                               \  
      (tc)->blockChain = NULL,                                                 \  
      ATOM_LIST_INIT(&(tc)->decls),                                            \  
      (tc)->blockNode = NULL,                                                  \  
      (tc)->parseContext = (pc),                                               \  
      (tc)->u.scopeChain = NULL,                                               \  
      JS_SCOPE_DEPTH_METERING((tc)->scopeDepth = (tc)->maxScopeDepth = 0))  
   
 /*  
  * For functions TREE_CONTEXT_FINISH is called the second time to finish the  
  * extra tc created during code generation. We skip stats update in such  
  * cases.  
  */  
 #define TREE_CONTEXT_FINISH(cx, tc)                                           \  
     JS_SCOPE_DEPTH_METERING(                                                  \  
         (tc)->maxScopeDepth == (uintN) -1 ||                                  \  
         JS_BASIC_STATS_ACCUM(&(cx)->runtime->lexicalScopeDepthStats,          \  
                              (tc)->maxScopeDepth))  
282    
283  /*  /*
284   * Span-dependent instructions are jumps whose span (from the jump bytecode to   * Span-dependent instructions are jumps whose span (from the jump bytecode to
# Line 316  Line 348 
348      JSTryNode       *prev;      JSTryNode       *prev;
349  };  };
350    
351  typedef struct JSEmittedObjectList {  struct JSCGObjectList {
352      uint32              length;     /* number of emitted so far objects */      uint32              length;     /* number of emitted so far objects */
353      JSParsedObjectBox   *lastPob;   /* last emitted object */      JSObjectBox         *lastbox;   /* last emitted object */
 } JSEmittedObjectList;  
354    
355  extern void      JSCGObjectList() : length(0), lastbox(NULL) {}
 FinishParsedObjects(JSEmittedObjectList *emittedList, JSObjectArray *objectMap);  
356    
357  struct JSCodeGenerator {      uintN index(JSObjectBox *objbox);
358      JSTreeContext   treeContext;    /* base state: statement info stack, etc. */      void finish(JSObjectArray *array);
359    };
360    
361    struct JSCodeGenerator : public JSTreeContext
362    {
363      JSArenaPool     *codePool;      /* pointer to thread code arena pool */      JSArenaPool     *codePool;      /* pointer to thread code arena pool */
364      JSArenaPool     *notePool;      /* pointer to thread srcnote arena pool */      JSArenaPool     *notePool;      /* pointer to thread srcnote arena pool */
365      void            *codeMark;      /* low watermark in cg->codePool */      void            *codeMark;      /* low watermark in cg->codePool */
# Line 365  Line 398 
398      uintN           emitLevel;      /* js_EmitTree recursion level */      uintN           emitLevel;      /* js_EmitTree recursion level */
399      JSAtomList      constList;      /* compile time constants */      JSAtomList      constList;      /* compile time constants */
400    
401      JSEmittedObjectList objectList; /* list of emitted so far objects */      JSCGObjectList  objectList;     /* list of emitted objects */
402      JSEmittedObjectList regexpList; /* list of emitted so far regexp      JSCGObjectList  regexpList;     /* list of emitted regexp that will be
403                                         that will be cloned during execution */                                         cloned during execution */
404    
     uintN           staticDepth;    /* static frame chain depth */  
405      JSAtomList      upvarList;      /* map of atoms to upvar indexes */      JSAtomList      upvarList;      /* map of atoms to upvar indexes */
406      JSUpvarArray    upvarMap;       /* indexed upvar pairs (JS_realloc'ed) */      JSUpvarArray    upvarMap;       /* indexed upvar pairs (JS_realloc'ed) */
407      JSCodeGenerator *parent;        /* enclosing function or global context */  
408        /*
409         * Initialize cg to allocate bytecode space from codePool, source note
410         * space from notePool, and all other arena-allocated temporaries from
411         * jsc->context->tempPool.
412         */
413        JSCodeGenerator(JSCompiler *jsc,
414                        JSArenaPool *codePool, JSArenaPool *notePool,
415                        uintN lineno);
416    
417        /*
418         * Release cg->codePool, cg->notePool, and compiler->context->tempPool to
419         * marks set by JSCodeGenerator's ctor. Note that cgs are magic: they own
420         * the arena pool "tops-of-stack" space above their codeMark, noteMark, and
421         * tempMark points.  This means you cannot alloc from tempPool and save the
422         * pointer beyond the next JSCodeGenerator destructor call.
423         */
424        ~JSCodeGenerator();
425  };  };
426    
427  #define CG_TS(cg)               TS((cg)->treeContext.parseContext)  #define CG_TS(cg)               TS((cg)->compiler)
428    
429  #define CG_BASE(cg)             ((cg)->current->base)  #define CG_BASE(cg)             ((cg)->current->base)
430  #define CG_LIMIT(cg)            ((cg)->current->limit)  #define CG_LIMIT(cg)            ((cg)->current->limit)
# Line 400  Line 449 
449  #define CG_SWITCH_TO_PROLOG(cg) ((cg)->current = &(cg)->prolog)  #define CG_SWITCH_TO_PROLOG(cg) ((cg)->current = &(cg)->prolog)
450    
451  /*  /*
  * Initialize cg to allocate bytecode space from codePool, source note space  
  * from notePool, and all other arena-allocated temporaries from cx->tempPool.  
  */  
 extern JS_FRIEND_API(void)  
 js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc,  
                      JSArenaPool *codePool, JSArenaPool *notePool,  
                      uintN lineno);  
   
 /*  
  * Release cg->codePool, cg->notePool, and cx->tempPool to marks set by  
  * js_InitCodeGenerator. Note that cgs are magic: they own the arena pool  
  * "tops-of-stack" space above their codeMark, noteMark, and tempMark points.  
  * This means you cannot alloc from tempPool and save the pointer beyond the  
  * next JS_FinishCodeGenerator.  
  */  
 extern JS_FRIEND_API(void)  
 js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg);  
   
 /*  
452   * Emit one bytecode.   * Emit one bytecode.
453   */   */
454  extern ptrdiff_t  extern ptrdiff_t
# Line 467  Line 497 
497  js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,  js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
498                   ptrdiff_t off);                   ptrdiff_t off);
499    
 /* Test whether we're in a statement of given type. */  
 extern JSBool  
 js_InStatement(JSTreeContext *tc, JSStmtType type);  
   
 /* Test whether we're in a with statement. */  
 #define js_InWithStatement(tc)      js_InStatement(tc, STMT_WITH)  
   
500  /*  /*
501   * Push the C-stack-allocated struct at stmt onto the stmtInfo stack.   * Push the C-stack-allocated struct at stmt onto the stmtInfo stack.
502   */   */
# Line 498  Line 521 
521  js_PopStatement(JSTreeContext *tc);  js_PopStatement(JSTreeContext *tc);
522    
523  /*  /*
524   * Like js_PopStatement(&cg->treeContext), also patch breaks and continues   * Like js_PopStatement(cg), also patch breaks and continues unless the top
525   * unless the top statement info record represents a try-catch-finally suite.   * statement info record represents a try-catch-finally suite. May fail if a
526   * May fail if a jump offset overflows.   * jump offset overflows.
527   */   */
528  extern JSBool  extern JSBool
529  js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);  js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);
# Line 536  Line 559 
559   * found. Otherwise return null.   * found. Otherwise return null.
560   */   */
561  extern JSStmtInfo *  extern JSStmtInfo *
562  js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp);  js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp,
563                     JSStmtInfo *stmt = NULL);
564    
565  /*  /*
566   * Emit code into cg for the tree rooted at pn.   * Emit code into cg for the tree rooted at pn.
# Line 587  Line 611 
611      SRC_INITPROP    = 1,        /* disjoint meaning applied to JSOP_INITELEM or      SRC_INITPROP    = 1,        /* disjoint meaning applied to JSOP_INITELEM or
612                                     to an index label in a regular (structuring)                                     to an index label in a regular (structuring)
613                                     or a destructuring object initialiser */                                     or a destructuring object initialiser */
614      SRC_GENEXP      = 1,        /* JSOP_ANONFUNOBJ from generator expression */      SRC_GENEXP      = 1,        /* JSOP_LAMBDA from generator expression */
615      SRC_IF_ELSE     = 2,        /* JSOP_IFEQ bytecode is from an if-then-else */      SRC_IF_ELSE     = 2,        /* JSOP_IFEQ bytecode is from an if-then-else */
616      SRC_FOR_IN      = 2,        /* JSOP_GOTO to for-in loop condition from      SRC_FOR_IN      = 2,        /* JSOP_GOTO to for-in loop condition from
617                                     before loop (same arity as SRC_IF_ELSE) */                                     before loop (same arity as SRC_IF_ELSE) */
# Line 597  Line 621 
621                                     do-while loop */                                     do-while loop */
622      SRC_CONTINUE    = 5,        /* JSOP_GOTO is a continue, not a break;      SRC_CONTINUE    = 5,        /* JSOP_GOTO is a continue, not a break;
623                                     also used on JSOP_ENDINIT if extra comma                                     also used on JSOP_ENDINIT if extra comma
624                                     at end of array literal: [1,2,,] */                                     at end of array literal: [1,2,,];
625                                       JSOP_DUP continuing destructuring pattern */
626      SRC_DECL        = 6,        /* type of a declaration (var, const, let*) */      SRC_DECL        = 6,        /* type of a declaration (var, const, let*) */
627      SRC_DESTRUCT    = 6,        /* JSOP_DUP starting a destructuring assignment      SRC_DESTRUCT    = 6,        /* JSOP_DUP starting a destructuring assignment
628                                     operation, with SRC_DECL_* offset operand */                                     operation, with SRC_DECL_* offset operand */

Legend:
Removed from v.399  
changed lines
  Added in v.460

  ViewVC Help
Powered by ViewVC 1.1.24