LCOV - app.info - js/src/frontend/ParseNode.h

LCOV - code coverage report
| Current view: | directory - js/src/frontend - ParseNode.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 297 | 273 | 91.9 %
| Date: | 2012-04-07 | Functions: | 95 | 89 | 93.7 %

           1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=8 sw=4 et tw=99:
           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-2011
          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 the GNU General Public License Version 2 or later (the "GPL"), or
          29                 :  * 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 ParseNode_h__
          42                 : #define ParseNode_h__
          43                 :
          44                 : #include "mozilla/Attributes.h"
          45                 :
          46                 : #include "jsscript.h"
          47                 :
          48                 : #include "frontend/ParseMaps.h"
          49                 : #include "frontend/TokenStream.h"
          50                 :
          51                 : namespace js {
          52                 :
          53                 : /*
          54                 :  * Indicates a location in the stack that an upvar value can be retrieved from
          55                 :  * as a two tuple of (level, slot).
          56                 :  *
          57                 :  * Some existing client code uses the level value as a delta, or level "skip"
          58                 :  * quantity. We could probably document that through use of more types at some
          59                 :  * point in the future.
          60                 :  */
          61                 : class UpvarCookie
          62                 : {
          63                 :     uint32_t value;
          64                 :
          65                 :     static const uint32_t FREE_VALUE = 0xfffffffful;
          66                 :
          67                 :     void checkInvariants() {
          68                 :         JS_STATIC_ASSERT(sizeof(UpvarCookie) == sizeof(uint32_t));
          69                 :         JS_STATIC_ASSERT(UPVAR_LEVEL_LIMIT < FREE_LEVEL);
          70                 :     }
          71                 :
          72                 :   public:
          73                 :     /*
          74                 :      * All levels above-and-including FREE_LEVEL are reserved so that
          75                 :      * FREE_VALUE can be used as a special value.
          76                 :      */
          77                 :     static const uint16_t FREE_LEVEL = 0x3fff;
          78                 :
          79                 :     /*
          80                 :      * If a function has a higher static level than this limit, we will not
          81                 :      * optimize it using UPVAR opcodes.
          82                 :      */
          83                 :     static const uint16_t UPVAR_LEVEL_LIMIT = 16;
          84                 :     static const uint16_t CALLEE_SLOT = 0xffff;
          85          251616 :     static bool isLevelReserved(uint16_t level) { return level >= FREE_LEVEL; }
          86                 :
          87        17432866 :     bool isFree() const { return value == FREE_VALUE; }
          88                 :     /* isFree check should be performed before using these accessors. */
          89         1200386 :     uint16_t level() const { JS_ASSERT(!isFree()); return uint16_t(value >> 16); }
          90         2873676 :     uint16_t slot() const { JS_ASSERT(!isFree()); return uint16_t(value); }
          91                 :
          92                 :     void set(const UpvarCookie &other) { set(other.level(), other.slot()); }
          93         5668489 :     void set(uint16_t newLevel, uint16_t newSlot) { value = (uint32_t(newLevel) << 16) | newSlot; }
          94         4063410 :     void makeFree() { set(0xffff, 0xffff); JS_ASSERT(isFree()); }
          95                 : };
          96                 :
          97                 : /*
          98                 :  * Parsing builds a tree of nodes that directs code generation.  This tree is
          99                 :  * not a concrete syntax tree in all respects (for example, || and && are left
         100                 :  * associative, but (A && B && C) translates into the right-associated tree
         101                 :  * <A && <B && C>> so that code generation can emit a left-associative branch
         102                 :  * around <B && C> when A is false).  Nodes are labeled by kind, with a
         103                 :  * secondary JSOp label when needed.
         104                 :  *
         105                 :  * The long comment after this enum block describes the kinds in detail.
         106                 :  */
         107                 : enum ParseNodeKind {
         108                 :     PNK_SEMI,
         109                 :     PNK_COMMA,
         110                 :     PNK_CONDITIONAL,
         111                 :     PNK_COLON,
         112                 :     PNK_OR,
         113                 :     PNK_AND,
         114                 :     PNK_BITOR,
         115                 :     PNK_BITXOR,
         116                 :     PNK_BITAND,
         117                 :     PNK_POS,
         118                 :     PNK_NEG,
         119                 :     PNK_ADD,
         120                 :     PNK_SUB,
         121                 :     PNK_STAR,
         122                 :     PNK_DIV,
         123                 :     PNK_MOD,
         124                 :     PNK_PREINCREMENT,
         125                 :     PNK_POSTINCREMENT,
         126                 :     PNK_PREDECREMENT,
         127                 :     PNK_POSTDECREMENT,
         128                 :     PNK_DOT,
         129                 :     PNK_LB,
         130                 :     PNK_RB,
         131                 :     PNK_STATEMENTLIST,
         132                 :     PNK_XMLCURLYEXPR,
         133                 :     PNK_RC,
         134                 :     PNK_LP,
         135                 :     PNK_RP,
         136                 :     PNK_NAME,
         137                 :     PNK_NUMBER,
         138                 :     PNK_STRING,
         139                 :     PNK_REGEXP,
         140                 :     PNK_TRUE,
         141                 :     PNK_FALSE,
         142                 :     PNK_NULL,
         143                 :     PNK_THIS,
         144                 :     PNK_FUNCTION,
         145                 :     PNK_IF,
         146                 :     PNK_ELSE,
         147                 :     PNK_SWITCH,
         148                 :     PNK_CASE,
         149                 :     PNK_DEFAULT,
         150                 :     PNK_WHILE,
         151                 :     PNK_DOWHILE,
         152                 :     PNK_FOR,
         153                 :     PNK_BREAK,
         154                 :     PNK_CONTINUE,
         155                 :     PNK_IN,
         156                 :     PNK_VAR,
         157                 :     PNK_CONST,
         158                 :     PNK_WITH,
         159                 :     PNK_RETURN,
         160                 :     PNK_NEW,
         161                 :     PNK_DELETE,
         162                 :     PNK_TRY,
         163                 :     PNK_CATCH,
         164                 :     PNK_CATCHLIST,
         165                 :     PNK_FINALLY,
         166                 :     PNK_THROW,
         167                 :     PNK_INSTANCEOF,
         168                 :     PNK_DEBUGGER,
         169                 :     PNK_DEFXMLNS,
         170                 :     PNK_XMLSTAGO,
         171                 :     PNK_XMLETAGO,
         172                 :     PNK_XMLPTAGC,
         173                 :     PNK_XMLTAGC,
         174                 :     PNK_XMLNAME,
         175                 :     PNK_XMLATTR,
         176                 :     PNK_XMLSPACE,
         177                 :     PNK_XMLTEXT,
         178                 :     PNK_XMLCOMMENT,
         179                 :     PNK_XMLCDATA,
         180                 :     PNK_XMLPI,
         181                 :     PNK_XMLUNARY,
         182                 :     PNK_AT,
         183                 :     PNK_DBLCOLON,
         184                 :     PNK_ANYNAME,
         185                 :     PNK_DBLDOT,
         186                 :     PNK_FILTER,
         187                 :     PNK_XMLELEM,
         188                 :     PNK_XMLLIST,
         189                 :     PNK_YIELD,
         190                 :     PNK_ARRAYCOMP,
         191                 :     PNK_ARRAYPUSH,
         192                 :     PNK_LEXICALSCOPE,
         193                 :     PNK_LET,
         194                 :     PNK_SEQ,
         195                 :     PNK_FORIN,
         196                 :     PNK_FORHEAD,
         197                 :     PNK_ARGSBODY,
         198                 :     PNK_UPVARS,
         199                 :
         200                 :     /*
         201                 :      * The following parse node kinds occupy contiguous ranges to enable easy
         202                 :      * range-testing.
         203                 :      */
         204                 :
         205                 :     /* Equality operators. */
         206                 :     PNK_STRICTEQ,
         207                 :     PNK_EQ,
         208                 :     PNK_STRICTNE,
         209                 :     PNK_NE,
         210                 :
         211                 :     /* Unary operators. */
         212                 :     PNK_TYPEOF,
         213                 :     PNK_VOID,
         214                 :     PNK_NOT,
         215                 :     PNK_BITNOT,
         216                 :
         217                 :     /* Relational operators (< <= > >=). */
         218                 :     PNK_LT,
         219                 :     PNK_LE,
         220                 :     PNK_GT,
         221                 :     PNK_GE,
         222                 :
         223                 :     /* Shift operators (<< >> >>>). */
         224                 :     PNK_LSH,
         225                 :     PNK_RSH,
         226                 :     PNK_URSH,
         227                 :
         228                 :     /* Assignment operators (= += -= etc.). */
         229                 :     PNK_ASSIGN,
         230                 :     PNK_ASSIGNMENT_START = PNK_ASSIGN,
         231                 :     PNK_ADDASSIGN,
         232                 :     PNK_SUBASSIGN,
         233                 :     PNK_BITORASSIGN,
         234                 :     PNK_BITXORASSIGN,
         235                 :     PNK_BITANDASSIGN,
         236                 :     PNK_LSHASSIGN,
         237                 :     PNK_RSHASSIGN,
         238                 :     PNK_URSHASSIGN,
         239                 :     PNK_MULASSIGN,
         240                 :     PNK_DIVASSIGN,
         241                 :     PNK_MODASSIGN,
         242                 :     PNK_ASSIGNMENT_LAST = PNK_MODASSIGN,
         243                 :
         244                 :     PNK_LIMIT /* domain size */
         245                 : };
         246                 :
         247                 : /*
         248                 :  * Label        Variant     Members
         249                 :  * -----        -------     -------
         250                 :  * <Definitions>
         251                 :  * PNK_FUNCTION name        pn_funbox: ptr to js::FunctionBox holding function
         252                 :  *                            object containing arg and var properties.  We
         253                 :  *                            create the function object at parse (not emit)
         254                 :  *                            time to specialize arg and var bytecodes early.
         255                 :  *                          pn_body: PNK_UPVARS if the function's source body
         256                 :  *                                     depends on outer names,
         257                 :  *                                   PNK_ARGSBODY if formal parameters,
         258                 :  *                                   PNK_STATEMENTLIST node for function body
         259                 :  *                                     statements,
         260                 :  *                                   PNK_RETURN for expression closure, or
         261                 :  *                                   PNK_SEQ for expression closure with
         262                 :  *                                     destructured formal parameters
         263                 :  *                          pn_cookie: static level and var index for function
         264                 :  *                          pn_dflags: PND_* definition/use flags (see below)
         265                 :  *                          pn_blockid: block id number
         266                 :  * PNK_ARGSBODY list        list of formal parameters followed by
         267                 :  *                            PNK_STATEMENTLIST node for function body
         268                 :  *                            statements as final element
         269                 :  *                          pn_count: 1 + number of formal parameters
         270                 :  * PNK_UPVARS   nameset     pn_names: lexical dependencies (js::Definitions)
         271                 :  *                            defined in enclosing scopes, or ultimately not
         272                 :  *                            defined (free variables, either global property
         273                 :  *                            references or reference errors).
         274                 :  *                          pn_tree: PNK_ARGSBODY or PNK_STATEMENTLIST node
         275                 :  *
         276                 :  * <Statements>
         277                 :  * PNK_STATEMENTLIST list   pn_head: list of pn_count statements
         278                 :  * PNK_IF       ternary     pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
         279                 :  *                            In body of a comprehension or desugared generator
         280                 :  *                            expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH,
         281                 :  *                            or (if the push was optimized away) empty
         282                 :  *                            PNK_STATEMENTLIST.
         283                 :  * PNK_SWITCH   binary      pn_left: discriminant
         284                 :  *                          pn_right: list of PNK_CASE nodes, with at most one
         285                 :  *                            PNK_DEFAULT node, or if there are let bindings
         286                 :  *                            in the top level of the switch body's cases, a
         287                 :  *                            PNK_LEXICALSCOPE node that contains the list of
         288                 :  *                            PNK_CASE nodes.
         289                 :  * PNK_CASE,    binary      pn_left: case expr
         290                 :  *                          pn_right: PNK_STATEMENTLIST node for this case's
         291                 :  *                            statements
         292                 :  * PNK_DEFAULT  binary      pn_left: null
         293                 :  *                          pn_right: PNK_STATEMENTLIST node for this default's
         294                 :  *                            statements
         295                 :  *                          pn_val: constant value if lookup or table switch
         296                 :  * PNK_WHILE    binary      pn_left: cond, pn_right: body
         297                 :  * PNK_DOWHILE  binary      pn_left: body, pn_right: cond
         298                 :  * PNK_FOR      binary      pn_left: either PNK_FORIN (for-in statement) or
         299                 :  *                            PNK_FORHEAD (for(;;) statement)
         300                 :  *                          pn_right: body
         301                 :  * PNK_FORIN    ternary     pn_kid1:  PNK_VAR to left of 'in', or NULL
         302                 :  *                            its pn_xflags may have PNX_POPVAR
         303                 :  *                            and PNX_FORINVAR bits set
         304                 :  *                          pn_kid2: PNK_NAME or destructuring expr
         305                 :  *                            to left of 'in'; if pn_kid1, then this
         306                 :  *                            is a clone of pn_kid1->pn_head
         307                 :  *                          pn_kid3: object expr to right of 'in'
         308                 :  * PNK_FORHEAD  ternary     pn_kid1:  init expr before first ';' or NULL
         309                 :  *                          pn_kid2:  cond expr before second ';' or NULL
         310                 :  *                          pn_kid3:  update expr after second ';' or NULL
         311                 :  * PNK_THROW    unary       pn_op: JSOP_THROW, pn_kid: exception
         312                 :  * PNK_TRY      ternary     pn_kid1: try block
         313                 :  *                          pn_kid2: null or PNK_CATCHLIST list of
         314                 :  *                          PNK_LEXICALSCOPE nodes, each with pn_expr pointing
         315                 :  *                          to a PNK_CATCH node
         316                 :  *                          pn_kid3: null or finally block
         317                 :  * PNK_CATCH    ternary     pn_kid1: PNK_NAME, PNK_RB, or PNK_RC catch var node
         318                 :  *                                   (PNK_RB or PNK_RC if destructuring)
         319                 :  *                          pn_kid2: null or the catch guard expression
         320                 :  *                          pn_kid3: catch block statements
         321                 :  * PNK_BREAK    name        pn_atom: label or null
         322                 :  * PNK_CONTINUE name        pn_atom: label or null
         323                 :  * PNK_WITH     binary      pn_left: head expr, pn_right: body
         324                 :  * PNK_VAR,     list        pn_head: list of PNK_NAME or PNK_ASSIGN nodes
         325                 :  * PNK_CONST                         each name node has either
         326                 :  *                                     pn_used: false
         327                 :  *                                     pn_atom: variable name
         328                 :  *                                     pn_expr: initializer or null
         329                 :  *                                   or
         330                 :  *                                     pn_used: true
         331                 :  *                                     pn_atom: variable name
         332                 :  *                                     pn_lexdef: def node
         333                 :  *                                   each assignment node has
         334                 :  *                                     pn_left: PNK_NAME with pn_used true and
         335                 :  *                                              pn_lexdef (NOT pn_expr) set
         336                 :  *                                     pn_right: initializer
         337                 :  * PNK_RETURN   unary       pn_kid: return expr or null
         338                 :  * PNK_SEMI     unary       pn_kid: expr or null statement
         339                 :  *                          pn_prologue: true if Directive Prologue member
         340                 :  *                              in original source, not introduced via
         341                 :  *                              constant folding or other tree rewriting
         342                 :  * PNK_COLON    name        pn_atom: label, pn_expr: labeled statement
         343                 :  *
         344                 :  * <Expressions>
         345                 :  * All left-associated binary trees of the same type are optimized into lists
         346                 :  * to avoid recursion when processing expression chains.
         347                 :  * PNK_COMMA    list        pn_head: list of pn_count comma-separated exprs
         348                 :  * PNK_ASSIGN   binary      pn_left: lvalue, pn_right: rvalue
         349                 :  * PNK_ADDASSIGN,   binary  pn_left: lvalue, pn_right: rvalue
         350                 :  * PNK_SUBASSIGN,           pn_op: JSOP_ADD for +=, etc.
         351                 :  * PNK_BITORASSIGN,
         352                 :  * PNK_BITXORASSIGN,
         353                 :  * PNK_BITANDASSIGN,
         354                 :  * PNK_LSHASSIGN,
         355                 :  * PNK_RSHASSIGN,
         356                 :  * PNK_URSHASSIGN,
         357                 :  * PNK_MULASSIGN,
         358                 :  * PNK_DIVASSIGN,
         359                 :  * PNK_MODASSIGN
         360                 :  * PNK_CONDITIONAL ternary  (cond ? trueExpr : falseExpr)
         361                 :  *                          pn_kid1: cond, pn_kid2: then, pn_kid3: else
         362                 :  * PNK_OR       binary      pn_left: first in || chain, pn_right: rest of chain
         363                 :  * PNK_AND      binary      pn_left: first in && chain, pn_right: rest of chain
         364                 :  * PNK_BITOR    binary      pn_left: left-assoc | expr, pn_right: ^ expr
         365                 :  * PNK_BITXOR   binary      pn_left: left-assoc ^ expr, pn_right: & expr
         366                 :  * PNK_BITAND   binary      pn_left: left-assoc & expr, pn_right: EQ expr
         367                 :  *
         368                 :  * PNK_EQ,      binary      pn_left: left-assoc EQ expr, pn_right: REL expr
         369                 :  * PNK_NE,
         370                 :  * PNK_STRICTEQ,
         371                 :  * PNK_STRICTNE
         372                 :  * PNK_LT,      binary      pn_left: left-assoc REL expr, pn_right: SH expr
         373                 :  * PNK_LE,
         374                 :  * PNK_GT,
         375                 :  * PNK_GE
         376                 :  * PNK_LSH,     binary      pn_left: left-assoc SH expr, pn_right: ADD expr
         377                 :  * PNK_RSH,
         378                 :  * PNK_URSH
         379                 :  * PNK_ADD      binary      pn_left: left-assoc ADD expr, pn_right: MUL expr
         380                 :  *                          pn_xflags: if a left-associated binary PNK_ADD
         381                 :  *                            tree has been flattened into a list (see above
         382                 :  *                            under <Expressions>), pn_xflags will contain
         383                 :  *                            PNX_STRCAT if at least one list element is a
         384                 :  *                            string literal (PNK_STRING); if such a list has
         385                 :  *                            any non-string, non-number term, pn_xflags will
         386                 :  *                            contain PNX_CANTFOLD.
         387                 :  * PNK_SUB      binary      pn_left: left-assoc SH expr, pn_right: ADD expr
         388                 :  * PNK_STAR,    binary      pn_left: left-assoc MUL expr, pn_right: UNARY expr
         389                 :  * PNK_DIV,                 pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
         390                 :  * PNK_MOD
         391                 :  * PNK_POS,     unary       pn_kid: UNARY expr
         392                 :  * PNK_NEG
         393                 :  * PNK_TYPEOF,  unary       pn_kid: UNARY expr
         394                 :  * PNK_VOID,
         395                 :  * PNK_NOT,
         396                 :  * PNK_BITNOT
         397                 :  * PNK_PREINCREMENT, unary  pn_kid: MEMBER expr
         398                 :  * PNK_POSTINCREMENT,
         399                 :  * PNK_PREDECREMENT,
         400                 :  * PNK_POSTDECREMENT
         401                 :  * PNK_NEW      list        pn_head: list of ctor, arg1, arg2, ... argN
         402                 :  *                          pn_count: 1 + N (where N is number of args)
         403                 :  *                          ctor is a MEMBER expr
         404                 :  * PNK_DELETE   unary       pn_kid: MEMBER expr
         405                 :  * PNK_DOT,     name        pn_expr: MEMBER expr to left of .
         406                 :  * PNK_DBLDOT               pn_atom: name to right of .
         407                 :  * PNK_LB       binary      pn_left: MEMBER expr to left of [
         408                 :  *                          pn_right: expr between [ and ]
         409                 :  * PNK_LP       list        pn_head: list of call, arg1, arg2, ... argN
         410                 :  *                          pn_count: 1 + N (where N is number of args)
         411                 :  *                          call is a MEMBER expr naming a callable object
         412                 :  * PNK_RB       list        pn_head: list of pn_count array element exprs
         413                 :  *                          [,,] holes are represented by PNK_COMMA nodes
         414                 :  *                          pn_xflags: PN_ENDCOMMA if extra comma at end
         415                 :  * PNK_RC       list        pn_head: list of pn_count binary PNK_COLON nodes
         416                 :  * PNK_COLON    binary      key-value pair in object initializer or
         417                 :  *                          destructuring lhs
         418                 :  *                          pn_left: property id, pn_right: value
         419                 :  *                          var {x} = object destructuring shorthand shares
         420                 :  *                          PN_NAME node for x on left and right of PNK_COLON
         421                 :  *                          node in PNK_RC's list, has PNX_DESTRUCT flag
         422                 :  * PNK_NAME,    name        pn_atom: name, string, or object atom
         423                 :  * PNK_STRING,              pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or
         424                 :  *                                 JSOP_REGEXP
         425                 :  * PNK_REGEXP               If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
         426                 :  *                          with pn_cookie telling (staticLevel, slot) (see
         427                 :  *                          jsscript.h's UPVAR macros) and pn_dflags telling
         428                 :  *                          const-ness and static analysis results
         429                 :  * PNK_NAME     name        If pn_used, PNK_NAME uses the lexdef member instead
         430                 :  *                          of the expr member it overlays
         431                 :  * PNK_NUMBER   dval        pn_dval: double value of numeric literal
         432                 :  * PNK_TRUE,    nullary     pn_op: JSOp bytecode
         433                 :  * PNK_FALSE,
         434                 :  * PNK_NULL,
         435                 :  * PNK_THIS
         436                 :  *
         437                 :  * <E4X node descriptions>
         438                 :  * PNK_XMLUNARY unary       pn_kid: PNK_AT, PNK_ANYNAME, or PNK_DBLCOLON node
         439                 :  *                          pn_op: JSOP_XMLNAME, JSOP_BINDXMLNAME, or
         440                 :  *                                 JSOP_SETXMLNAME
         441                 :  * PNK_DEFXMLNS name        pn_kid: namespace expr
         442                 :  * PNK_FILTER   binary      pn_left: container expr, pn_right: filter expr
         443                 :  * PNK_DBLDOT   binary      pn_left: container expr, pn_right: selector expr
         444                 :  * PNK_ANYNAME  nullary     pn_op: JSOP_ANYNAME
         445                 :  *                          pn_atom: cx->runtime->atomState.starAtom
         446                 :  * PNK_AT       unary       pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr
         447                 :  * PNK_DBLCOLON binary      pn_op: JSOP_QNAME
         448                 :  *                          pn_left: PNK_ANYNAME or PNK_NAME node
         449                 :  *                          pn_right: PNK_STRING "*" node, or expr within []
         450                 :  *              name        pn_op: JSOP_QNAMECONST
         451                 :  *                          pn_expr: PNK_ANYNAME or PNK_NAME left operand
         452                 :  *                          pn_atom: name on right of ::
         453                 :  * PNK_XMLELEM  list        XML element node
         454                 :  *                          pn_head: start tag, content1, ... contentN, end tag
         455                 :  *                          pn_count: 2 + N where N is number of content nodes
         456                 :  *                                    N may be > x.length() if {expr} embedded
         457                 :  *                            After constant folding, these contents may be
         458                 :  *                            concatenated into string nodes.
         459                 :  * PNK_XMLLIST  list        XML list node
         460                 :  *                          pn_head: content1, ... contentN
         461                 :  * PNK_XMLSTAGO, list       XML start, end, and point tag contents
         462                 :  * PNK_XMLETAGO,            pn_head: tag name or {expr}, ... XML attrs ...
         463                 :  * PNK_XMLPTAGC
         464                 :  * PNK_XMLNAME  nullary     pn_atom: XML name, with no {expr} embedded
         465                 :  * PNK_XMLNAME  list        pn_head: tag name or {expr}, ... name or {expr}
         466                 :  * PNK_XMLATTR, nullary     pn_atom: attribute value string; pn_op: JSOP_STRING
         467                 :  * PNK_XMLCDATA,
         468                 :  * PNK_XMLCOMMENT
         469                 :  * PNK_XMLPI    nullary     pn_pitarget: XML processing instruction target
         470                 :  *                          pn_pidata: XML PI data, or null if no data
         471                 :  * PNK_XMLTEXT  nullary     pn_atom: marked-up text, or null if empty string
         472                 :  * PNK_XMLCURLYEXPR unary   {expr} in XML tag or content; pn_kid is expr
         473                 :  *
         474                 :  * So an XML tag with no {expr} and three attributes is a list with the form:
         475                 :  *
         476                 :  *    (tagname attrname1 attrvalue1 attrname2 attrvalue2 attrname2 attrvalue3)
         477                 :  *
         478                 :  * An XML tag with embedded expressions like so:
         479                 :  *
         480                 :  *    <name1{expr1} name2{expr2}name3={expr3}>
         481                 :  *
         482                 :  * would have the form:
         483                 :  *
         484                 :  *    ((name1 {expr1}) (name2 {expr2} name3) {expr3})
         485                 :  *
         486                 :  * where () bracket a list with elements separated by spaces, and {expr} is a
         487                 :  * PNK_XMLCURLYEXPR unary node with expr as its kid.
         488                 :  *
         489                 :  * Thus, the attribute name/value pairs occupy successive odd and even list
         490                 :  * locations, where pn_head is the PNK_XMLNAME node at list location 0.  The
         491                 :  * parser builds the same sort of structures for elements:
         492                 :  *
         493                 :  *    <a x={x}>Hi there!<b y={y}>How are you?</b><answer>{x + y}</answer></a>
         494                 :  *
         495                 :  * translates to:
         496                 :  *
         497                 :  *    ((a x {x}) 'Hi there!' ((b y {y}) 'How are you?') ((answer) {x + y}))
         498                 :  *
         499                 :  * <Non-E4X node descriptions, continued>
         500                 :  *
         501                 :  * Label              Variant   Members
         502                 :  * -----              -------   -------
         503                 :  * PNK_LEXICALSCOPE   name      pn_op: JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR
         504                 :  *                              pn_objbox: block object in ObjectBox holder
         505                 :  *                              pn_expr: block body
         506                 :  * PNK_ARRAYCOMP      list      pn_count: 1
         507                 :  *                              pn_head: list of 1 element, which is block
         508                 :  *                                enclosing for loop(s) and optionally
         509                 :  *                                if-guarded PNK_ARRAYPUSH
         510                 :  * PNK_ARRAYPUSH      unary     pn_op: JSOP_ARRAYCOMP
         511                 :  *                              pn_kid: array comprehension expression
         512                 :  */
         513                 : enum ParseNodeArity {
         514                 :     PN_NULLARY,                         /* 0 kids, only pn_atom/pn_dval/etc. */
         515                 :     PN_UNARY,                           /* one kid, plus a couple of scalars */
         516                 :     PN_BINARY,                          /* two kids, plus a couple of scalars */
         517                 :     PN_TERNARY,                         /* three kids */
         518                 :     PN_FUNC,                            /* function definition node */
         519                 :     PN_LIST,                            /* generic singly linked list */
         520                 :     PN_NAME,                            /* name use or definition node */
         521                 :     PN_NAMESET                          /* AtomDefnMapPtr + ParseNode ptr */
         522                 : };
         523                 :
         524                 : struct Definition;
         525                 :
         526                 : class LoopControlStatement;
         527                 : class BreakStatement;
         528                 : class ContinueStatement;
         529                 : class XMLProcessingInstruction;
         530                 : class ConditionalExpression;
         531                 : class PropertyAccess;
         532                 :
         533                 : struct ParseNode {
         534                 :   private:
         535                 :     uint32_t            pn_type   : 16, /* PNK_* type */
         536                 :                         pn_op     : 8,  /* see JSOp enum and jsopcode.tbl */
         537                 :                         pn_arity  : 5,  /* see ParseNodeArity enum */
         538                 :                         pn_parens : 1,  /* this expr was enclosed in parens */
         539                 :                         pn_used   : 1,  /* name node is on a use-chain */
         540                 :                         pn_defn   : 1;  /* this node is a Definition */
         541                 :
         542                 :     ParseNode(const ParseNode &other) MOZ_DELETE;
         543                 :     void operator=(const ParseNode &other) MOZ_DELETE;
         544                 :
         545                 :   public:
         546                 :     ParseNode(ParseNodeKind kind, JSOp op, ParseNodeArity arity)
         547                 :       : pn_type(kind), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0),
         548                 :         pn_offset(0), pn_next(NULL), pn_link(NULL)
         549                 :     {
         550                 :         JS_ASSERT(kind < PNK_LIMIT);
         551                 :         pn_pos.begin.index = 0;
         552                 :         pn_pos.begin.lineno = 0;
         553                 :         pn_pos.end.index = 0;
         554                 :         pn_pos.end.lineno = 0;
         555                 :         memset(&pn_u, 0, sizeof pn_u);
         556                 :     }
         557                 :
         558         7724483 :     ParseNode(ParseNodeKind kind, JSOp op, ParseNodeArity arity, const TokenPos &pos)
         559                 :       : pn_type(kind), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0),
         560         7724483 :         pn_pos(pos), pn_offset(0), pn_next(NULL), pn_link(NULL)
         561                 :     {
         562         7724483 :         JS_ASSERT(kind < PNK_LIMIT);
         563         7724483 :         memset(&pn_u, 0, sizeof pn_u);
         564         7724483 :     }
         565                 :
         566        31502553 :     JSOp getOp() const                     { return JSOp(pn_op); }
         567         8462154 :     void setOp(JSOp op)                    { pn_op = op; }
         568        21609546 :     bool isOp(JSOp op) const               { return getOp() == op; }
         569                 :
         570        51698163 :     ParseNodeKind getKind() const {
         571        51698163 :         JS_ASSERT(pn_type < PNK_LIMIT);
         572        51698163 :         return ParseNodeKind(pn_type);
         573                 :     }
         574           34633 :     void setKind(ParseNodeKind kind) {
         575           34633 :         JS_ASSERT(kind < PNK_LIMIT);
         576           34633 :         pn_type = kind;
         577           34633 :     }
         578        26604134 :     bool isKind(ParseNodeKind kind) const  { return getKind() == kind; }
         579                 :
         580        17427418 :     ParseNodeArity getArity() const        { return ParseNodeArity(pn_arity); }
         581         4071338 :     bool isArity(ParseNodeArity a) const   { return getArity() == a; }
         582           38111 :     void setArity(ParseNodeArity a)        { pn_arity = a; }
         583                 :
         584         3614000 :     bool isXMLNameOp() const {
         585         3614000 :         ParseNodeKind kind = getKind();
         586         3614000 :         return kind == PNK_ANYNAME || kind == PNK_AT || kind == PNK_DBLCOLON;
         587                 :     }
         588          517758 :     bool isAssignment() const {
         589          517758 :         ParseNodeKind kind = getKind();
         590          517758 :         return PNK_ASSIGNMENT_START <= kind && kind <= PNK_ASSIGNMENT_LAST;
         591                 :     }
         592                 :
         593               0 :     bool isXMLPropertyIdentifier() const {
         594               0 :         ParseNodeKind kind = getKind();
         595               0 :         return kind == PNK_ANYNAME || kind == PNK_AT || kind == PNK_DBLCOLON;
         596                 :     }
         597                 :
         598          101660 :     bool isXMLItem() const {
         599          101660 :         ParseNodeKind kind = getKind();
         600                 :         return kind == PNK_XMLCOMMENT || kind == PNK_XMLCDATA || kind == PNK_XMLPI ||
         601          101660 :                kind == PNK_XMLELEM || kind == PNK_XMLLIST;
         602                 :     }
         603                 :
         604                 :     /* Boolean attributes. */
         605          225444 :     bool isInParens() const                { return pn_parens; }
         606          140789 :     void setInParens(bool enabled)         { pn_parens = enabled; }
         607        17552257 :     bool isUsed() const                    { return pn_used; }
         608         2593697 :     void setUsed(bool enabled)             { pn_used = enabled; }
         609        15428112 :     bool isDefn() const                    { return pn_defn; }
         610         1195789 :     void setDefn(bool enabled)             { pn_defn = enabled; }
         611                 :
         612                 :     TokenPos            pn_pos;         /* two 16-bit pairs here, for 64 bits */
         613                 :     int32_t             pn_offset;      /* first generated bytecode offset */
         614                 :     ParseNode           *pn_next;       /* intrinsic link in parent PN_LIST */
         615                 :     ParseNode           *pn_link;       /* def/use link (alignment freebie);
         616                 :                                            also links FunctionBox::methods
         617                 :                                            lists of would-be |this| methods */
         618                 :
         619                 :     union {
         620                 :         struct {                        /* list of next-linked nodes */
         621                 :             ParseNode   *head;          /* first node in list */
         622                 :             ParseNode   **tail;         /* ptr to ptr to last node in list */
         623                 :             uint32_t    count;          /* number of nodes in list */
         624                 :             uint32_t    xflags:12,      /* extra flags, see below */
         625                 :                         blockid:20;     /* see name variant below */
         626                 :         } list;
         627                 :         struct {                        /* ternary: if, for(;;), ?: */
         628                 :             ParseNode   *kid1;          /* condition, discriminant, etc. */
         629                 :             ParseNode   *kid2;          /* then-part, case list, etc. */
         630                 :             ParseNode   *kid3;          /* else-part, default case, etc. */
         631                 :         } ternary;
         632                 :         struct {                        /* two kids if binary */
         633                 :             ParseNode   *left;
         634                 :             ParseNode   *right;
         635                 :             Value       *pval;          /* switch case value */
         636                 :             unsigned       iflags;         /* JSITER_* flags for PNK_FOR node */
         637                 :         } binary;
         638                 :         struct {                        /* one kid if unary */
         639                 :             ParseNode   *kid;
         640                 :             JSBool      hidden;         /* hidden genexp-induced JSOP_YIELD
         641                 :                                            or directive prologue member (as
         642                 :                                            pn_prologue) */
         643                 :         } unary;
         644                 :         struct {                        /* name, labeled statement, etc. */
         645                 :             union {
         646                 :                 JSAtom        *atom;    /* lexical name or label atom */
         647                 :                 FunctionBox   *funbox;  /* function object */
         648                 :                 ObjectBox     *objbox;  /* block or regexp object */
         649                 :             };
         650                 :             union {
         651                 :                 ParseNode    *expr;     /* function body, var initializer, or
         652                 :                                            base object of PNK_DOT */
         653                 :                 Definition   *lexdef;   /* lexical definition for this use */
         654                 :             };
         655                 :             UpvarCookie cookie;         /* upvar cookie with absolute frame
         656                 :                                            level (not relative skip), possibly
         657                 :                                            in current frame */
         658                 :             uint32_t    dflags:12,      /* definition/use flags, see below */
         659                 :                         blockid:20;     /* block number, for subset dominance
         660                 :                                            computation */
         661                 :         } name;
         662                 :         struct {                        /* lexical dependencies + sub-tree */
         663                 :             AtomDefnMapPtr   defnMap;
         664                 :             ParseNode        *tree;     /* sub-tree containing name uses */
         665                 :         } nameset;
         666                 :         double        dval;             /* aligned numeric literal value */
         667                 :         class {
         668                 :             friend class LoopControlStatement;
         669                 :             PropertyName     *label;    /* target of break/continue statement */
         670                 :         } loopControl;
         671                 :         class {                         /* E4X <?target data?> XML PI */
         672                 :             friend class XMLProcessingInstruction;
         673                 :             PropertyName     *target;   /* non-empty */
         674                 :             JSAtom           *data;     /* may be empty, never null */
         675                 :         } xmlpi;
         676                 :     } pn_u;
         677                 :
         678                 : #define pn_funbox       pn_u.name.funbox
         679                 : #define pn_body         pn_u.name.expr
         680                 : #define pn_cookie       pn_u.name.cookie
         681                 : #define pn_dflags       pn_u.name.dflags
         682                 : #define pn_blockid      pn_u.name.blockid
         683                 : #define pn_index        pn_u.name.blockid /* reuse as object table index */
         684                 : #define pn_head         pn_u.list.head
         685                 : #define pn_tail         pn_u.list.tail
         686                 : #define pn_count        pn_u.list.count
         687                 : #define pn_xflags       pn_u.list.xflags
         688                 : #define pn_kid1         pn_u.ternary.kid1
         689                 : #define pn_kid2         pn_u.ternary.kid2
         690                 : #define pn_kid3         pn_u.ternary.kid3
         691                 : #define pn_left         pn_u.binary.left
         692                 : #define pn_right        pn_u.binary.right
         693                 : #define pn_pval         pn_u.binary.pval
         694                 : #define pn_iflags       pn_u.binary.iflags
         695                 : #define pn_kid          pn_u.unary.kid
         696                 : #define pn_hidden       pn_u.unary.hidden
         697                 : #define pn_prologue     pn_u.unary.hidden
         698                 : #define pn_atom         pn_u.name.atom
         699                 : #define pn_objbox       pn_u.name.objbox
         700                 : #define pn_expr         pn_u.name.expr
         701                 : #define pn_lexdef       pn_u.name.lexdef
         702                 : #define pn_names        pn_u.nameset.defnMap
         703                 : #define pn_tree         pn_u.nameset.tree
         704                 : #define pn_dval         pn_u.dval
         705                 :
         706                 :   protected:
         707                 :     void init(TokenKind type, JSOp op, ParseNodeArity arity) {
         708                 :         pn_type = type;
         709                 :         pn_op = op;
         710                 :         pn_arity = arity;
         711                 :         pn_parens = false;
         712                 :         JS_ASSERT(!pn_used);
         713                 :         JS_ASSERT(!pn_defn);
         714                 :         pn_names.init();
         715                 :         pn_next = pn_link = NULL;
         716                 :     }
         717                 :
         718                 :     static ParseNode *create(ParseNodeKind kind, ParseNodeArity arity, TreeContext *tc);
         719                 :
         720                 :   public:
         721                 :     /*
         722                 :      * Append right to left, forming a list node.  |left| must have the given
         723                 :      * kind and op, and op must be left-associative.
         724                 :      */
         725                 :     static ParseNode *
         726                 :     append(ParseNodeKind tt, JSOp op, ParseNode *left, ParseNode *right);
         727                 :
         728                 :     /*
         729                 :      * Either append right to left, if left meets the conditions necessary to
         730                 :      * append (see append), or form a binary node whose children are right and
         731                 :      * left.
         732                 :      */
         733                 :     static ParseNode *
         734                 :     newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right,
         735                 :                       TreeContext *tc);
         736                 :
         737                 :     /*
         738                 :      * The pn_expr and lexdef members are arms of an unsafe union. Unless you
         739                 :      * know exactly what you're doing, use only the following methods to access
         740                 :      * them. For less overhead and assertions for protection, use pn->expr()
         741                 :      * and pn->lexdef(). Otherwise, use pn->maybeExpr() and pn->maybeLexDef().
         742                 :      */
         743          871830 :     ParseNode *expr() const {
         744          871830 :         JS_ASSERT(!pn_used);
         745          871830 :         JS_ASSERT(pn_arity == PN_NAME || pn_arity == PN_FUNC);
         746          871830 :         return pn_expr;
         747                 :     }
         748                 :
         749           99271 :     Definition *lexdef() const {
         750           99271 :         JS_ASSERT(pn_used || isDeoptimized());
         751           99271 :         JS_ASSERT(pn_arity == PN_NAME);
         752           99271 :         return pn_lexdef;
         753                 :     }
         754                 :
         755          870638 :     ParseNode  *maybeExpr()   { return pn_used ? NULL : expr(); }
         756                 :     Definition *maybeLexDef() { return pn_used ? lexdef() : NULL; }
         757                 :
         758                 : /* PN_FUNC and PN_NAME pn_dflags bits. */
         759                 : #define PND_LET         0x01            /* let (block-scoped) binding */
         760                 : #define PND_CONST       0x02            /* const binding (orthogonal to let) */
         761                 : #define PND_INITIALIZED 0x04            /* initialized declaration */
         762                 : #define PND_ASSIGNED    0x08            /* set if ever LHS of assignment */
         763                 : #define PND_TOPLEVEL    0x10            /* see isTopLevel() below */
         764                 : #define PND_BLOCKCHILD  0x20            /* use or def is direct block child */
         765                 : #define PND_GVAR        0x40            /* gvar binding, can't close over
         766                 :                                            because it could be deleted */
         767                 : #define PND_PLACEHOLDER 0x80            /* placeholder definition for lexdep */
         768                 : #define PND_BOUND      0x100            /* bound to a stack or global slot */
         769                 : #define PND_DEOPTIMIZED 0x200           /* former pn_used name node, pn_lexdef
         770                 :                                            still valid, but this use no longer
         771                 :                                            optimizable via an upvar opcode */
         772                 : #define PND_CLOSED      0x400           /* variable is closed over */
         773                 :
         774                 : /* Flags to propagate from uses to definition. */
         775                 : #define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
         776                 :
         777                 : /* PN_LIST pn_xflags bits. */
         778                 : #define PNX_STRCAT      0x01            /* PNK_ADD list has string term */
         779                 : #define PNX_CANTFOLD    0x02            /* PNK_ADD list has unfoldable term */
         780                 : #define PNX_POPVAR      0x04            /* PNK_VAR or PNK_CONST last result
         781                 :                                            needs popping */
         782                 : #define PNX_FORINVAR    0x08            /* PNK_VAR is left kid of PNK_FORIN node
         783                 :                                            which is left kid of PNK_FOR */
         784                 : #define PNX_ENDCOMMA    0x10            /* array literal has comma at end */
         785                 : #define PNX_XMLROOT     0x20            /* top-most node in XML literal tree */
         786                 : #define PNX_GROUPINIT   0x40            /* var [a, b] = [c, d]; unit list */
         787                 : #define PNX_NEEDBRACES  0x80            /* braces necessary due to closure */
         788                 : #define PNX_FUNCDEFS   0x100            /* contains top-level function statements */
         789                 : #define PNX_SETCALL    0x100            /* call expression in lvalue context */
         790                 : #define PNX_DESTRUCT   0x200            /* destructuring special cases:
         791                 :                                            1. shorthand syntax used, at present
         792                 :                                               object destructuring ({x,y}) only;
         793                 :                                            2. code evaluating destructuring
         794                 :                                               arguments occurs before function
         795                 :                                               body */
         796                 : #define PNX_HOLEY      0x400            /* array initialiser has holes */
         797                 : #define PNX_NONCONST   0x800            /* initialiser has non-constants */
         798                 :
         799           11315 :     unsigned frameLevel() const {
         800           11315 :         JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
         801           11315 :         return pn_cookie.level();
         802                 :     }
         803                 :
         804          640624 :     unsigned frameSlot() const {
         805          640624 :         JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
         806          640624 :         return pn_cookie.slot();
         807                 :     }
         808                 :
         809                 :     inline bool test(unsigned flag) const;
         810                 :
         811          616973 :     bool isLet() const          { return test(PND_LET); }
         812         2136679 :     bool isConst() const        { return test(PND_CONST); }
         813            1260 :     bool isInitialized() const  { return test(PND_INITIALIZED); }
         814           28647 :     bool isBlockChild() const   { return test(PND_BLOCKCHILD); }
         815          109017 :     bool isPlaceholder() const  { return test(PND_PLACEHOLDER); }
         816         4437738 :     bool isDeoptimized() const  { return test(PND_DEOPTIMIZED); }
         817          371691 :     bool isAssigned() const     { return test(PND_ASSIGNED); }
         818          344873 :     bool isClosed() const       { return test(PND_CLOSED); }
         819                 :
         820                 :     /*
         821                 :      * True iff this definition creates a top-level binding in the overall
         822                 :      * script being compiled -- that is, it affects the whole program's
         823                 :      * bindings, not bindings for a specific function (unless this definition
         824                 :      * is in the outermost scope in eval code, executed within a function) or
         825                 :      * the properties of a specific object (through the with statement).
         826                 :      *
         827                 :      * NB: Function sub-statements found in overall program code and not nested
         828                 :      *     within other functions are not currently top level, even though (if
         829                 :      *     executed) they do create top-level bindings; there is no particular
         830                 :      *     rationale for this behavior.
         831                 :      */
         832               9 :     bool isTopLevel() const     { return test(PND_TOPLEVEL); }
         833                 :
         834                 :     void become(ParseNode *pn2);
         835                 :     void clear();
         836                 :
         837                 :     /* True if pn is a parsenode representing a literal constant. */
         838                 :     bool isLiteral() const {
         839                 :         return isKind(PNK_NUMBER) ||
         840                 :                isKind(PNK_STRING) ||
         841                 :                isKind(PNK_TRUE) ||
         842                 :                isKind(PNK_FALSE) ||
         843                 :                isKind(PNK_NULL);
         844                 :     }
         845                 :
         846                 :     /*
         847                 :      * True if this statement node could be a member of a Directive Prologue: an
         848                 :      * expression statement consisting of a single string literal.
         849                 :      *
         850                 :      * This considers only the node and its children, not its context. After
         851                 :      * parsing, check the node's pn_prologue flag to see if it is indeed part of
         852                 :      * a directive prologue.
         853                 :      *
         854                 :      * Note that a Directive Prologue can contain statements that cannot
         855                 :      * themselves be directives (string literals that include escape sequences
         856                 :      * or escaped newlines, say). This member function returns true for such
         857                 :      * nodes; we use it to determine the extent of the prologue.
         858                 :      * isEscapeFreeStringLiteral, below, checks whether the node itself could be
         859                 :      * a directive.
         860                 :      */
         861          183879 :     bool isStringExprStatement() const {
         862          183879 :         if (getKind() == PNK_SEMI) {
         863           74082 :             JS_ASSERT(pn_arity == PN_UNARY);
         864           74082 :             ParseNode *kid = pn_kid;
         865           74082 :             return kid && kid->getKind() == PNK_STRING && !kid->pn_parens;
         866                 :         }
         867          109797 :         return false;
         868                 :     }
         869                 :
         870                 :     /*
         871                 :      * Return true if this node, known to be an unparenthesized string literal,
         872                 :      * could be the string of a directive in a Directive Prologue. Directive
         873                 :      * strings never contain escape sequences or line continuations.
         874                 :      */
         875             836 :     bool isEscapeFreeStringLiteral() const {
         876             836 :         JS_ASSERT(isKind(PNK_STRING) && !pn_parens);
         877                 :
         878                 :         /*
         879                 :          * If the string's length in the source code is its length as a value,
         880                 :          * accounting for the quotes, then it must not contain any escape
         881                 :          * sequences or line continuations.
         882                 :          */
         883             836 :         JSString *str = pn_atom;
         884                 :         return (pn_pos.begin.lineno == pn_pos.end.lineno &&
         885             836 :                 pn_pos.begin.index + str->length() + 2 == pn_pos.end.index);
         886                 :     }
         887                 :
         888                 :     /* Return true if this node appears in a Directive Prologue. */
         889             713 :     bool isDirectivePrologueMember() const { return pn_prologue; }
         890                 :
         891                 : #ifdef JS_HAS_DESTRUCTURING
         892                 :     /* Return true if this represents a hole in an array literal. */
         893            8442 :     bool isArrayHole() const { return isKind(PNK_COMMA) && isArity(PN_NULLARY); }
         894                 : #endif
         895                 :
         896                 : #ifdef JS_HAS_GENERATOR_EXPRS
         897                 :     /*
         898                 :      * True if this node is a desugared generator expression.
         899                 :      */
         900             810 :     bool isGeneratorExpr() const {
         901             810 :         if (getKind() == PNK_LP) {
         902             810 :             ParseNode *callee = this->pn_head;
         903             810 :             if (callee->getKind() == PNK_FUNCTION) {
         904             108 :                 ParseNode *body = (callee->pn_body->getKind() == PNK_UPVARS)
         905                 :                                   ? callee->pn_body->pn_tree
         906             108 :                                   : callee->pn_body;
         907             108 :                 if (body->getKind() == PNK_LEXICALSCOPE)
         908              72 :                     return true;
         909                 :             }
         910                 :         }
         911             738 :         return false;
         912                 :     }
         913                 :
         914              36 :     ParseNode *generatorExpr() const {
         915              36 :         JS_ASSERT(isGeneratorExpr());
         916              36 :         ParseNode *callee = this->pn_head;
         917              36 :         ParseNode *body = callee->pn_body->getKind() == PNK_UPVARS
         918                 :                           ? callee->pn_body->pn_tree
         919              36 :                           : callee->pn_body;
         920              36 :         JS_ASSERT(body->getKind() == PNK_LEXICALSCOPE);
         921              36 :         return body->pn_expr;
         922                 :     }
         923                 : #endif
         924                 :
         925                 :     /*
         926                 :      * Compute a pointer to the last element in a singly-linked list. NB: list
         927                 :      * must be non-empty for correct PN_LAST usage -- this is asserted!
         928                 :      */
         929          261994 :     ParseNode *last() const {
         930          261994 :         JS_ASSERT(pn_arity == PN_LIST);
         931          261994 :         JS_ASSERT(pn_count != 0);
         932          261994 :         return (ParseNode *)(uintptr_t(pn_tail) - offsetof(ParseNode, pn_next));
         933                 :     }
         934                 :
         935          804491 :     void makeEmpty() {
         936          804491 :         JS_ASSERT(pn_arity == PN_LIST);
         937          804491 :         pn_head = NULL;
         938          804491 :         pn_tail = &pn_head;
         939          804491 :         pn_count = 0;
         940          804491 :         pn_xflags = 0;
         941          804491 :         pn_blockid = 0;
         942          804491 :     }
         943                 :
         944          240143 :     void initList(ParseNode *pn) {
         945          240143 :         JS_ASSERT(pn_arity == PN_LIST);
         946          240143 :         pn_head = pn;
         947          240143 :         pn_tail = &pn->pn_next;
         948          240143 :         pn_count = 1;
         949          240143 :         pn_xflags = 0;
         950          240143 :         pn_blockid = 0;
         951          240143 :     }
         952                 :
         953         3402464 :     void append(ParseNode *pn) {
         954         3402464 :         JS_ASSERT(pn_arity == PN_LIST);
         955         3402464 :         *pn_tail = pn;
         956         3402464 :         pn_tail = &pn->pn_next;
         957         3402464 :         pn_count++;
         958         3402464 :     }
         959                 :
         960                 :     bool getConstantValue(JSContext *cx, bool strictChecks, Value *vp);
         961                 :     inline bool isConstant();
         962                 :
         963                 :     /* Casting operations. */
         964                 :     inline BreakStatement &asBreakStatement();
         965                 :     inline ContinueStatement &asContinueStatement();
         966                 : #if JS_HAS_XML_SUPPORT
         967                 :     inline XMLProcessingInstruction &asXMLProcessingInstruction();
         968                 : #endif
         969                 :     inline ConditionalExpression &asConditionalExpression();
         970                 :     inline PropertyAccess &asPropertyAccess();
         971                 :
         972                 : #ifdef DEBUG
         973                 :     inline void dump(int indent);
         974                 : #endif
         975                 : };
         976                 :
         977                 : struct NullaryNode : public ParseNode {
         978          732394 :     static inline NullaryNode *create(ParseNodeKind kind, TreeContext *tc) {
         979          732394 :         return (NullaryNode *)ParseNode::create(kind, PN_NULLARY, tc);
         980                 :     }
         981                 :
         982                 : #ifdef DEBUG
         983                 :     inline void dump();
         984                 : #endif
         985                 : };
         986                 :
         987                 : struct UnaryNode : public ParseNode {
         988          109921 :     UnaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *kid)
         989          109921 :       : ParseNode(kind, op, PN_UNARY, pos)
         990                 :     {
         991          109921 :         pn_kid = kid;
         992          109921 :     }
         993                 :
         994          634930 :     static inline UnaryNode *create(ParseNodeKind kind, TreeContext *tc) {
         995          634930 :         return (UnaryNode *)ParseNode::create(kind, PN_UNARY, tc);
         996                 :     }
         997                 :
         998                 : #ifdef DEBUG
         999                 :     inline void dump(int indent);
        1000                 : #endif
        1001                 : };
        1002                 :
        1003                 : struct BinaryNode : public ParseNode {
        1004           31179 :     BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right)
        1005           31179 :       : ParseNode(kind, op, PN_BINARY, pos)
        1006                 :     {
        1007           31179 :         pn_left = left;
        1008           31179 :         pn_right = right;
        1009           31179 :     }
        1010                 :
        1011          616197 :     BinaryNode(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right)
        1012          616197 :       : ParseNode(kind, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos))
        1013                 :     {
        1014          616197 :         pn_left = left;
        1015          616197 :         pn_right = right;
        1016          616197 :     }
        1017                 :
        1018           42371 :     static inline BinaryNode *create(ParseNodeKind kind, TreeContext *tc) {
        1019           42371 :         return (BinaryNode *)ParseNode::create(kind, PN_BINARY, tc);
        1020                 :     }
        1021                 :
        1022                 : #ifdef DEBUG
        1023                 :     inline void dump(int indent);
        1024                 : #endif
        1025                 : };
        1026                 :
        1027                 : struct TernaryNode : public ParseNode {
        1028             549 :     TernaryNode(ParseNodeKind kind, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3)
        1029                 :       : ParseNode(kind, op, PN_TERNARY,
        1030                 :                   TokenPos::make((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
        1031             549 :                                  (kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end))
        1032                 :     {
        1033             549 :         pn_kid1 = kid1;
        1034             549 :         pn_kid2 = kid2;
        1035             549 :         pn_kid3 = kid3;
        1036             549 :     }
        1037                 :
        1038          297495 :     static inline TernaryNode *create(ParseNodeKind kind, TreeContext *tc) {
        1039          297495 :         return (TernaryNode *)ParseNode::create(kind, PN_TERNARY, tc);
        1040                 :     }
        1041                 :
        1042                 : #ifdef DEBUG
        1043                 :     inline void dump(int indent);
        1044                 : #endif
        1045                 : };
        1046                 :
        1047                 : struct ListNode : public ParseNode {
        1048         1037553 :     static inline ListNode *create(ParseNodeKind kind, TreeContext *tc) {
        1049         1037553 :         return (ListNode *)ParseNode::create(kind, PN_LIST, tc);
        1050                 :     }
        1051                 :
        1052                 : #ifdef DEBUG
        1053                 :     inline void dump(int indent);
        1054                 : #endif
        1055                 : };
        1056                 :
        1057                 : struct FunctionNode : public ParseNode {
        1058          167389 :     static inline FunctionNode *create(ParseNodeKind kind, TreeContext *tc) {
        1059          167389 :         return (FunctionNode *)ParseNode::create(kind, PN_FUNC, tc);
        1060                 :     }
        1061                 :
        1062                 : #ifdef DEBUG
        1063                 :     inline void dump(int indent);
        1064                 : #endif
        1065                 : };
        1066                 :
        1067                 : struct NameNode : public ParseNode {
        1068                 :     static NameNode *create(ParseNodeKind kind, JSAtom *atom, TreeContext *tc);
        1069                 :
        1070                 :     inline void initCommon(TreeContext *tc);
        1071                 :
        1072                 : #ifdef DEBUG
        1073                 :     inline void dump(int indent);
        1074                 : #endif
        1075                 : };
        1076                 :
        1077                 : struct NameSetNode : public ParseNode {
        1078           61222 :     static inline NameSetNode *create(ParseNodeKind kind, TreeContext *tc) {
        1079           61222 :         return (NameSetNode *)ParseNode::create(kind, PN_NAMESET, tc);
        1080                 :     }
        1081                 : };
        1082                 :
        1083                 : struct LexicalScopeNode : public ParseNode {
        1084          100846 :     static inline LexicalScopeNode *create(ParseNodeKind kind, TreeContext *tc) {
        1085          100846 :         return (LexicalScopeNode *)ParseNode::create(kind, PN_NAME, tc);
        1086                 :     }
        1087                 : };
        1088                 :
        1089                 : class LoopControlStatement : public ParseNode {
        1090                 :   protected:
        1091            1881 :     LoopControlStatement(ParseNodeKind kind, PropertyName *label,
        1092                 :                          const TokenPtr &begin, const TokenPtr &end)
        1093            1881 :       : ParseNode(kind, JSOP_NOP, PN_NULLARY, TokenPos::make(begin, end))
        1094                 :     {
        1095            1881 :         JS_ASSERT(kind == PNK_BREAK || kind == PNK_CONTINUE);
        1096            1881 :         pn_u.loopControl.label = label;
        1097            1881 :     }
        1098                 :
        1099                 :   public:
        1100                 :     /* Label associated with this break/continue statement, if any. */
        1101            1809 :     PropertyName *label() const {
        1102            1809 :         return pn_u.loopControl.label;
        1103                 :     }
        1104                 : };
        1105                 :
        1106                 : class BreakStatement : public LoopControlStatement {
        1107                 :   public:
        1108            1728 :     BreakStatement(PropertyName *label, const TokenPtr &begin, const TokenPtr &end)
        1109            1728 :       : LoopControlStatement(PNK_BREAK, label, begin, end)
        1110            1728 :     { }
        1111                 : };
        1112                 :
        1113                 : inline BreakStatement &
        1114            1656 : ParseNode::asBreakStatement()
        1115                 : {
        1116            1656 :     JS_ASSERT(isKind(PNK_BREAK));
        1117            1656 :     JS_ASSERT(isOp(JSOP_NOP));
        1118            1656 :     JS_ASSERT(pn_arity == PN_NULLARY);
        1119            1656 :     return *static_cast<BreakStatement *>(this);
        1120                 : }
        1121                 :
        1122                 : class ContinueStatement : public LoopControlStatement {
        1123                 :   public:
        1124             153 :     ContinueStatement(PropertyName *label, TokenPtr &begin, TokenPtr &end)
        1125             153 :       : LoopControlStatement(PNK_CONTINUE, label, begin, end)
        1126             153 :     { }
        1127                 : };
        1128                 :
        1129                 : inline ContinueStatement &
        1130             153 : ParseNode::asContinueStatement()
        1131                 : {
        1132             153 :     JS_ASSERT(isKind(PNK_CONTINUE));
        1133             153 :     JS_ASSERT(isOp(JSOP_NOP));
        1134             153 :     JS_ASSERT(pn_arity == PN_NULLARY);
        1135             153 :     return *static_cast<ContinueStatement *>(this);
        1136                 : }
        1137                 :
        1138                 : class DebuggerStatement : public ParseNode {
        1139                 :   public:
        1140            4334 :     DebuggerStatement(const TokenPos &pos)
        1141            4334 :       : ParseNode(PNK_DEBUGGER, JSOP_NOP, PN_NULLARY, pos)
        1142            4334 :     { }
        1143                 : };
        1144                 :
        1145                 : #if JS_HAS_XML_SUPPORT
        1146                 : class XMLProcessingInstruction : public ParseNode {
        1147                 :   public:
        1148               0 :     XMLProcessingInstruction(PropertyName *target, JSAtom *data, const TokenPos &pos)
        1149               0 :       : ParseNode(PNK_XMLPI, JSOP_NOP, PN_NULLARY, pos)
        1150                 :     {
        1151               0 :         pn_u.xmlpi.target = target;
        1152               0 :         pn_u.xmlpi.data = data;
        1153               0 :     }
        1154                 :
        1155               0 :     PropertyName *target() const {
        1156               0 :         return pn_u.xmlpi.target;
        1157                 :     }
        1158                 :
        1159               0 :     JSAtom *data() const {
        1160               0 :         return pn_u.xmlpi.data;
        1161                 :     }
        1162                 : };
        1163                 :
        1164                 : inline XMLProcessingInstruction &
        1165               0 : ParseNode::asXMLProcessingInstruction()
        1166                 : {
        1167               0 :     JS_ASSERT(isKind(PNK_XMLPI));
        1168               0 :     JS_ASSERT(isOp(JSOP_NOP));
        1169               0 :     JS_ASSERT(pn_arity == PN_NULLARY);
        1170               0 :     return *static_cast<XMLProcessingInstruction *>(this);
        1171                 : }
        1172                 : #endif
        1173                 :
        1174                 : class ConditionalExpression : public ParseNode {
        1175                 :   public:
        1176            6635 :     ConditionalExpression(ParseNode *condition, ParseNode *thenExpr, ParseNode *elseExpr)
        1177                 :       : ParseNode(PNK_CONDITIONAL, JSOP_NOP, PN_TERNARY,
        1178            6635 :                   TokenPos::make(condition->pn_pos.begin, elseExpr->pn_pos.end))
        1179                 :     {
        1180            6635 :         JS_ASSERT(condition);
        1181            6635 :         JS_ASSERT(thenExpr);
        1182            6635 :         JS_ASSERT(elseExpr);
        1183            6635 :         pn_u.ternary.kid1 = condition;
        1184            6635 :         pn_u.ternary.kid2 = thenExpr;
        1185            6635 :         pn_u.ternary.kid3 = elseExpr;
        1186            6635 :     }
        1187                 :
        1188            6635 :     ParseNode &condition() const {
        1189            6635 :         return *pn_u.ternary.kid1;
        1190                 :     }
        1191                 :
        1192            6635 :     ParseNode &thenExpression() const {
        1193            6635 :         return *pn_u.ternary.kid2;
        1194                 :     }
        1195                 :
        1196            6635 :     ParseNode &elseExpression() const {
        1197            6635 :         return *pn_u.ternary.kid3;
        1198                 :     }
        1199                 : };
        1200                 :
        1201                 : inline ConditionalExpression &
        1202            6635 : ParseNode::asConditionalExpression()
        1203                 : {
        1204            6635 :     JS_ASSERT(isKind(PNK_CONDITIONAL));
        1205            6635 :     JS_ASSERT(isOp(JSOP_NOP));
        1206            6635 :     JS_ASSERT(pn_arity == PN_TERNARY);
        1207            6635 :     return *static_cast<ConditionalExpression *>(this);
        1208                 : }
        1209                 :
        1210                 : class ThisLiteral : public ParseNode {
        1211                 :   public:
        1212           90824 :     ThisLiteral(const TokenPos &pos) : ParseNode(PNK_THIS, JSOP_THIS, PN_NULLARY, pos) { }
        1213                 : };
        1214                 :
        1215                 : class NullLiteral : public ParseNode {
        1216                 :   public:
        1217           13619 :     NullLiteral(const TokenPos &pos) : ParseNode(PNK_NULL, JSOP_NULL, PN_NULLARY, pos) { }
        1218                 : };
        1219                 :
        1220                 : class BooleanLiteral : public ParseNode {
        1221                 :   public:
        1222           21967 :     BooleanLiteral(bool b, const TokenPos &pos)
        1223           21967 :       : ParseNode(b ? PNK_TRUE : PNK_FALSE, b ? JSOP_TRUE : JSOP_FALSE, PN_NULLARY, pos)
        1224           21967 :     { }
        1225                 : };
        1226                 :
        1227                 : class XMLDoubleColonProperty : public ParseNode {
        1228                 :   public:
        1229               9 :     XMLDoubleColonProperty(ParseNode *lhs, ParseNode *rhs,
        1230                 :                            const TokenPtr &begin, const TokenPtr &end)
        1231               9 :       : ParseNode(PNK_LB, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
        1232                 :     {
        1233               9 :         JS_ASSERT(rhs->isKind(PNK_DBLCOLON));
        1234               9 :         pn_u.binary.left = lhs;
        1235               9 :         pn_u.binary.right = rhs;
        1236               9 :     }
        1237                 :
        1238                 :     ParseNode &left() const {
        1239                 :         return *pn_u.binary.left;
        1240                 :     }
        1241                 :
        1242                 :     ParseNode &right() const {
        1243                 :         return *pn_u.binary.right;
        1244                 :     }
        1245                 : };
        1246                 :
        1247                 : class XMLFilterExpression : public ParseNode {
        1248                 :   public:
        1249              72 :     XMLFilterExpression(ParseNode *lhs, ParseNode *filterExpr,
        1250                 :                         const TokenPtr &begin, const TokenPtr &end)
        1251              72 :       : ParseNode(PNK_FILTER, JSOP_FILTER, PN_BINARY, TokenPos::make(begin, end))
        1252                 :     {
        1253              72 :         pn_u.binary.left = lhs;
        1254              72 :         pn_u.binary.right = filterExpr;
        1255              72 :     }
        1256                 :
        1257                 :     ParseNode &left() const {
        1258                 :         return *pn_u.binary.left;
        1259                 :     }
        1260                 :
        1261                 :     ParseNode &filter() const {
        1262                 :         return *pn_u.binary.right;
        1263                 :     }
        1264                 : };
        1265                 :
        1266                 : class XMLProperty : public ParseNode {
        1267                 :   public:
        1268               0 :     XMLProperty(ParseNode *lhs, ParseNode *propertyId,
        1269                 :                 const TokenPtr &begin, const TokenPtr &end)
        1270               0 :       : ParseNode(PNK_LB, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
        1271                 :     {
        1272               0 :         pn_u.binary.left = lhs;
        1273               0 :         pn_u.binary.right = propertyId;
        1274               0 :     }
        1275                 :
        1276                 :     ParseNode &left() const {
        1277                 :         return *pn_u.binary.left;
        1278                 :     }
        1279                 :
        1280                 :     ParseNode &right() const {
        1281                 :         return *pn_u.binary.right;
        1282                 :     }
        1283                 : };
        1284                 :
        1285                 : class PropertyAccess : public ParseNode {
        1286                 :   public:
        1287          143372 :     PropertyAccess(ParseNode *lhs, PropertyName *name,
        1288                 :                    const TokenPtr &begin, const TokenPtr &end)
        1289          143372 :       : ParseNode(PNK_DOT, JSOP_GETPROP, PN_NAME, TokenPos::make(begin, end))
        1290                 :     {
        1291          143372 :         JS_ASSERT(lhs != NULL);
        1292          143372 :         JS_ASSERT(name != NULL);
        1293          143372 :         pn_u.name.expr = lhs;
        1294          143372 :         pn_u.name.atom = name;
        1295          143372 :     }
        1296                 :
        1297                 :     ParseNode &expression() const {
        1298                 :         return *pn_u.name.expr;
        1299                 :     }
        1300                 :
        1301                 :     PropertyName &name() const {
        1302                 :         return *pn_u.name.atom->asPropertyName();
        1303                 :     }
        1304                 : };
        1305                 :
        1306                 : inline PropertyAccess &
        1307                 : ParseNode::asPropertyAccess()
        1308                 : {
        1309                 :     JS_ASSERT(isKind(PNK_DOT));
        1310                 :     JS_ASSERT(pn_arity == PN_NAME);
        1311                 :     return *static_cast<PropertyAccess *>(this);
        1312                 : }
        1313                 :
        1314                 : class PropertyByValue : public ParseNode {
        1315                 :   public:
        1316           49202 :     PropertyByValue(ParseNode *lhs, ParseNode *propExpr,
        1317                 :                     const TokenPtr &begin, const TokenPtr &end)
        1318           49202 :       : ParseNode(PNK_LB, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end))
        1319                 :     {
        1320           49202 :         pn_u.binary.left = lhs;
        1321           49202 :         pn_u.binary.right = propExpr;
        1322           49202 :     }
        1323                 : };
        1324                 :
        1325                 : ParseNode *
        1326                 : CloneLeftHandSide(ParseNode *opn, TreeContext *tc);
        1327                 :
        1328                 : #ifdef DEBUG
        1329                 : void DumpParseTree(ParseNode *pn, int indent = 0);
        1330                 : #endif
        1331                 :
        1332                 : /*
        1333                 :  * js::Definition is a degenerate subtype of the PN_FUNC and PN_NAME variants
        1334                 :  * of js::ParseNode, allocated only for function, var, const, and let
        1335                 :  * declarations that define truly lexical bindings. This means that a child of
        1336                 :  * a PNK_VAR list may be a Definition as well as a ParseNode. The pn_defn bit
        1337                 :  * is set for all Definitions, clear otherwise.
        1338                 :  *
        1339                 :  * In an upvars list, defn->resolve() is the outermost definition the
        1340                 :  * name may reference. If a with block or a function that calls eval encloses
        1341                 :  * the use, the name may end up referring to something else at runtime.
        1342                 :  *
        1343                 :  * Note that not all var declarations are definitions: JS allows multiple var
        1344                 :  * declarations in a function or script, but only the first creates the hoisted
        1345                 :  * binding. JS programmers do redeclare variables for good refactoring reasons,
        1346                 :  * for example:
        1347                 :  *
        1348                 :  *   function foo() {
        1349                 :  *       ...
        1350                 :  *       for (var i ...) ...;
        1351                 :  *       ...
        1352                 :  *       for (var i ...) ...;
        1353                 :  *       ...
        1354                 :  *   }
        1355                 :  *
        1356                 :  * Not all definitions bind lexical variables, alas. In global and eval code
        1357                 :  * var may re-declare a pre-existing property having any attributes, with or
        1358                 :  * without JSPROP_PERMANENT. In eval code, indeed, ECMA-262 Editions 1 through
        1359                 :  * 3 require function and var to bind deletable bindings. Global vars thus are
        1360                 :  * properties of the global object, so they can be aliased even if they can't
        1361                 :  * be deleted.
        1362                 :  *
        1363                 :  * Only bindings within function code may be treated as lexical, of course with
        1364                 :  * the caveat that hoisting means use before initialization is allowed. We deal
        1365                 :  * with use before declaration in one pass as follows (error checking elided):
        1366                 :  *
        1367                 :  *   for (each use of unqualified name x in parse order) {
        1368                 :  *       if (this use of x is a declaration) {
        1369                 :  *           if (x in tc->decls) {                          // redeclaring
        1370                 :  *               pn = allocate a PN_NAME ParseNode;
        1371                 :  *           } else {                                       // defining
        1372                 :  *               dn = lookup x in tc->lexdeps;
        1373                 :  *               if (dn)                                    // use before def
        1374                 :  *                   remove x from tc->lexdeps;
        1375                 :  *               else                                       // def before use
        1376                 :  *                   dn = allocate a PN_NAME Definition;
        1377                 :  *               map x to dn via tc->decls;
        1378                 :  *               pn = dn;
        1379                 :  *           }
        1380                 :  *           insert pn into its parent PNK_VAR/PNK_CONST list;
        1381                 :  *       } else {
        1382                 :  *           pn = allocate a ParseNode for this reference to x;
        1383                 :  *           dn = lookup x in tc's lexical scope chain;
        1384                 :  *           if (!dn) {
        1385                 :  *               dn = lookup x in tc->lexdeps;
        1386                 :  *               if (!dn) {
        1387                 :  *                   dn = pre-allocate a Definition for x;
        1388                 :  *                   map x to dn in tc->lexdeps;
        1389                 :  *               }
        1390                 :  *           }
        1391                 :  *           append pn to dn's use chain;
        1392                 :  *       }
        1393                 :  *   }
        1394                 :  *
        1395                 :  * See frontend/BytecodeEmitter.h for js::TreeContext and its top*Stmt,
        1396                 :  * decls, and lexdeps members.
        1397                 :  *
        1398                 :  * Notes:
        1399                 :  *
        1400                 :  *  0. To avoid bloating ParseNode, we steal a bit from pn_arity for pn_defn
        1401                 :  *     and set it on a ParseNode instead of allocating a Definition.
        1402                 :  *
        1403                 :  *  1. Due to hoisting, a definition cannot be eliminated even if its "Variable
        1404                 :  *     statement" (ECMA-262 12.2) can be proven to be dead code. RecycleTree in
        1405                 :  *     ParseNode.cpp will not recycle a node whose pn_defn bit is set.
        1406                 :  *
        1407                 :  *  2. "lookup x in tc's lexical scope chain" gives up on def/use chaining if a
        1408                 :  *     with statement is found along the the scope chain, which includes tc,
        1409                 :  *     tc->parent, etc. Thus we eagerly connect an inner function's use of an
        1410                 :  *     outer's var x if the var x was parsed before the inner function.
        1411                 :  *
        1412                 :  *  3. A use may be eliminated as dead by the constant folder, which therefore
        1413                 :  *     must remove the dead name node from its singly-linked use chain, which
        1414                 :  *     would mean hashing to find the definition node and searching to update
        1415                 :  *     the pn_link pointing at the use to be removed. This is costly, so as for
        1416                 :  *     dead definitions, we do not recycle dead pn_used nodes.
        1417                 :  *
        1418                 :  * At the end of parsing a function body or global or eval program, tc->lexdeps
        1419                 :  * holds the lexical dependencies of the parsed unit. The name to def/use chain
        1420                 :  * mappings are then merged into the parent tc->lexdeps.
        1421                 :  *
        1422                 :  * Thus if a later var x is parsed in the outer function satisfying an earlier
        1423                 :  * inner function's use of x, we will remove dn from tc->lexdeps and re-use it
        1424                 :  * as the new definition node in the outer function's parse tree.
        1425                 :  *
        1426                 :  * When the compiler unwinds from the outermost tc, tc->lexdeps contains the
        1427                 :  * definition nodes with use chains for all free variables. These are either
        1428                 :  * global variables or reference errors.
        1429                 :  */
        1430                 : #define dn_uses         pn_link
        1431                 :
        1432                 : struct Definition : public ParseNode
        1433                 : {
        1434                 :     /*
        1435                 :      * We store definition pointers in PN_NAMESET AtomDefnMapPtrs in the AST,
        1436                 :      * but due to redefinition these nodes may become uses of other
        1437                 :      * definitions.  This is unusual, so we simply chase the pn_lexdef link to
        1438                 :      * find the final definition node. See functions called from
        1439                 :      * js::frontend::AnalyzeFunctions.
        1440                 :      *
        1441                 :      * FIXME: MakeAssignment mutates for want of a parent link...
        1442                 :      */
        1443           99982 :     Definition *resolve() {
        1444           99982 :         ParseNode *pn = this;
        1445          299028 :         while (!pn->isDefn()) {
        1446           99064 :             if (pn->isAssignment()) {
        1447               0 :                 pn = pn->pn_left;
        1448               0 :                 continue;
        1449                 :             }
        1450           99064 :             pn = pn->lexdef();
        1451                 :         }
        1452           99982 :         return (Definition *) pn;
        1453                 :     }
        1454                 :
        1455           99064 :     bool isFreeVar() const {
        1456           99064 :         JS_ASSERT(isDefn());
        1457           99064 :         return pn_cookie.isFree() || test(PND_GVAR);
        1458                 :     }
        1459                 :
        1460         2634803 :     bool isGlobal() const {
        1461         2634803 :         JS_ASSERT(isDefn());
        1462         2634803 :         return test(PND_GVAR);
        1463                 :     }
        1464                 :
        1465                 :     enum Kind { VAR, CONST, LET, FUNCTION, ARG, UNKNOWN };
        1466                 :
        1467              72 :     bool isBindingForm() { return int(kind()) <= int(LET); }
        1468                 :
        1469                 :     static const char *kindString(Kind kind);
        1470                 :
        1471         2595093 :     Kind kind() {
        1472         2595093 :         if (getKind() == PNK_FUNCTION)
        1473           69171 :             return FUNCTION;
        1474         2525922 :         JS_ASSERT(getKind() == PNK_NAME);
        1475         2525922 :         if (isOp(JSOP_NOP))
        1476         1730793 :             return UNKNOWN;
        1477          795129 :         if (isOp(JSOP_GETARG))
        1478          131366 :             return ARG;
        1479          663763 :         if (isConst())
        1480           56340 :             return CONST;
        1481          607423 :         if (isLet())
        1482           25206 :             return LET;
        1483          582217 :         return VAR;
        1484                 :     }
        1485                 : };
        1486                 :
        1487                 : class ParseNodeAllocator {
        1488                 :   public:
        1489          109194 :     explicit ParseNodeAllocator(JSContext *cx) : cx(cx), freelist(NULL) {}
        1490                 :
        1491                 :     void *allocNode();
        1492                 :     void freeNode(ParseNode *pn);
        1493                 :     ParseNode *freeTree(ParseNode *pn);
        1494                 :     void prepareNodeForMutation(ParseNode *pn);
        1495                 :
        1496                 :   private:
        1497                 :     JSContext *cx;
        1498                 :     ParseNode *freelist;
        1499                 : };
        1500                 :
        1501                 : inline bool
        1502        10705364 : ParseNode::test(unsigned flag) const
        1503                 : {
        1504        10705364 :     JS_ASSERT(pn_defn || pn_arity == PN_FUNC || pn_arity == PN_NAME);
        1505                 : #ifdef DEBUG
        1506        10705364 :     if ((flag & PND_ASSIGNED) && pn_defn && !(pn_dflags & flag)) {
        1507            3411 :         for (ParseNode *pn = ((Definition *) this)->dn_uses; pn; pn = pn->pn_link) {
        1508            1845 :             JS_ASSERT(!pn->pn_defn);
        1509            1845 :             JS_ASSERT(!(pn->pn_dflags & flag));
        1510                 :         }
        1511                 :     }
        1512                 : #endif
        1513        10705364 :     return !!(pn_dflags & flag);
        1514                 : }
        1515                 :
        1516                 : inline void
        1517         2492689 : LinkUseToDef(ParseNode *pn, Definition *dn, TreeContext *tc)
        1518                 : {
        1519         2492689 :     JS_ASSERT(!pn->isUsed());
        1520         2492689 :     JS_ASSERT(!pn->isDefn());
        1521         2492689 :     JS_ASSERT(pn != dn->dn_uses);
        1522         2492689 :     pn->pn_link = dn->dn_uses;
        1523         2492689 :     dn->dn_uses = pn;
        1524         2492689 :     dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
        1525         2492689 :     pn->setUsed(true);
        1526         2492689 :     pn->pn_lexdef = dn;
        1527         2492689 : }
        1528                 :
        1529                 : struct ObjectBox {
        1530                 :     ObjectBox           *traceLink;
        1531                 :     ObjectBox           *emitLink;
        1532                 :     JSObject            *object;
        1533                 :     bool                isFunctionBox;
        1534                 : };
        1535                 :
        1536                 : #define JSFB_LEVEL_BITS 14
        1537                 :
        1538                 : struct FunctionBox : public ObjectBox
        1539                 : {
        1540                 :     ParseNode           *node;
        1541                 :     FunctionBox         *siblings;
        1542                 :     FunctionBox         *kids;
        1543                 :     FunctionBox         *parent;
        1544                 :     ParseNode           *methods;               /* would-be methods set on this;
        1545                 :                                                    these nodes are linked via
        1546                 :                                                    pn_link, since lambdas are
        1547                 :                                                    neither definitions nor uses
        1548                 :                                                    of a binding */
        1549                 :     Bindings            bindings;               /* bindings for this function */
        1550                 :     uint32_t            queued:1,
        1551                 :                         inLoop:1,               /* in a loop in parent function */
        1552                 :                         level:JSFB_LEVEL_BITS;
        1553                 :     uint32_t            tcflags;
        1554                 :
        1555          490652 :     JSFunction *function() const { return (JSFunction *) object; }
        1556                 :
        1557                 :     /*
        1558                 :      * True if this function is inside the scope of a with-statement, an E4X
        1559                 :      * filter-expression, or a function that uses direct eval.
        1560                 :      */
        1561                 :     bool inAnyDynamicScope() const;
        1562                 :
        1563                 :     /*
        1564                 :      * Must this function's descendants be marked as having an extensible
        1565                 :      * ancestor?
        1566                 :      */
        1567                 :     bool scopeIsExtensible() const;
        1568                 : };
        1569                 :
        1570                 : struct FunctionBoxQueue {
        1571                 :     FunctionBox         **vector;
        1572                 :     size_t              head, tail;
        1573                 :     size_t              lengthMask;
        1574                 :
        1575                 :     size_t count()  { return head - tail; }
        1576                 :     size_t length() { return lengthMask + 1; }
        1577                 :
        1578                 :     FunctionBoxQueue()
        1579                 :       : vector(NULL), head(0), tail(0), lengthMask(0) { }
        1580                 :
        1581                 :     bool init(uint32_t count) {
        1582                 :         lengthMask = JS_BITMASK(JS_CEILING_LOG2W(count));
        1583                 :         vector = (FunctionBox **) OffTheBooks::malloc_(sizeof(FunctionBox) * length());
        1584                 :         return !!vector;
        1585                 :     }
        1586                 :
        1587                 :     ~FunctionBoxQueue() { UnwantedForeground::free_(vector); }
        1588                 :
        1589                 :     void push(FunctionBox *funbox) {
        1590                 :         if (!funbox->queued) {
        1591                 :             JS_ASSERT(count() < length());
        1592                 :             vector[head++ & lengthMask] = funbox;
        1593                 :             funbox->queued = true;
        1594                 :         }
        1595                 :     }
        1596                 :
        1597                 :     FunctionBox *pull() {
        1598                 :         if (tail == head)
        1599                 :             return NULL;
        1600                 :         JS_ASSERT(tail < head);
        1601                 :         FunctionBox *funbox = vector[tail++ & lengthMask];
        1602                 :         funbox->queued = false;
        1603                 :         return funbox;
        1604                 :     }
        1605                 : };
        1606                 :
        1607                 : } /* namespace js */
        1608                 :
        1609                 : #endif /* ParseNode_h__ */

Generated by: LCOV version 1.7