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

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

Generated by: LCOV version 1.7