LCOV - code coverage report
Current view: directory - js/src/frontend - ParseNode.h (source / functions) Found Hit Coverage
Test: app.info Lines: 320 295 92.2 %
Date: 2012-06-02 Functions: 98 92 93.9 %

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

Generated by: LCOV version 1.7