LCOV - code coverage report
Current view: top level - js/src/frontend - ParseNode.h (source / functions) Hit Total Coverage
Test: output.info Lines: 365 419 87.1 %
Date: 2017-07-14 16:53:18 Functions: 122 136 89.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef frontend_ParseNode_h
       8             : #define frontend_ParseNode_h
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : 
      12             : #include "builtin/ModuleObject.h"
      13             : #include "frontend/TokenStream.h"
      14             : 
      15             : namespace js {
      16             : namespace frontend {
      17             : 
      18             : class ParseContext;
      19             : class FullParseHandler;
      20             : class FunctionBox;
      21             : class ObjectBox;
      22             : 
      23             : #define FOR_EACH_PARSE_NODE_KIND(F) \
      24             :     F(NOP) \
      25             :     F(SEMI) \
      26             :     F(COMMA) \
      27             :     F(CONDITIONAL) \
      28             :     F(COLON) \
      29             :     F(SHORTHAND) \
      30             :     F(POS) \
      31             :     F(NEG) \
      32             :     F(PREINCREMENT) \
      33             :     F(POSTINCREMENT) \
      34             :     F(PREDECREMENT) \
      35             :     F(POSTDECREMENT) \
      36             :     F(DOT) \
      37             :     F(ELEM) \
      38             :     F(ARRAY) \
      39             :     F(ELISION) \
      40             :     F(STATEMENTLIST) \
      41             :     F(LABEL) \
      42             :     F(OBJECT) \
      43             :     F(CALL) \
      44             :     F(NAME) \
      45             :     F(OBJECT_PROPERTY_NAME) \
      46             :     F(COMPUTED_NAME) \
      47             :     F(NUMBER) \
      48             :     F(STRING) \
      49             :     F(TEMPLATE_STRING_LIST) \
      50             :     F(TEMPLATE_STRING) \
      51             :     F(TAGGED_TEMPLATE) \
      52             :     F(CALLSITEOBJ) \
      53             :     F(REGEXP) \
      54             :     F(TRUE) \
      55             :     F(FALSE) \
      56             :     F(NULL) \
      57             :     F(RAW_UNDEFINED) \
      58             :     F(THIS) \
      59             :     F(FUNCTION) \
      60             :     F(MODULE) \
      61             :     F(IF) \
      62             :     F(SWITCH) \
      63             :     F(CASE) \
      64             :     F(WHILE) \
      65             :     F(DOWHILE) \
      66             :     F(FOR) \
      67             :     F(COMPREHENSIONFOR) \
      68             :     F(BREAK) \
      69             :     F(CONTINUE) \
      70             :     F(VAR) \
      71             :     F(CONST) \
      72             :     F(WITH) \
      73             :     F(RETURN) \
      74             :     F(NEW) \
      75             :     /* Delete operations.  These must be sequential. */ \
      76             :     F(DELETENAME) \
      77             :     F(DELETEPROP) \
      78             :     F(DELETEELEM) \
      79             :     F(DELETEEXPR) \
      80             :     F(TRY) \
      81             :     F(CATCH) \
      82             :     F(CATCHLIST) \
      83             :     F(THROW) \
      84             :     F(DEBUGGER) \
      85             :     F(GENERATOR) \
      86             :     F(INITIALYIELD) \
      87             :     F(YIELD) \
      88             :     F(YIELD_STAR) \
      89             :     F(GENEXP) \
      90             :     F(ARRAYCOMP) \
      91             :     F(ARRAYPUSH) \
      92             :     F(LEXICALSCOPE) \
      93             :     F(LET) \
      94             :     F(IMPORT) \
      95             :     F(IMPORT_SPEC_LIST) \
      96             :     F(IMPORT_SPEC) \
      97             :     F(EXPORT) \
      98             :     F(EXPORT_FROM) \
      99             :     F(EXPORT_DEFAULT) \
     100             :     F(EXPORT_SPEC_LIST) \
     101             :     F(EXPORT_SPEC) \
     102             :     F(EXPORT_BATCH_SPEC) \
     103             :     F(FORIN) \
     104             :     F(FOROF) \
     105             :     F(FORHEAD) \
     106             :     F(PARAMSBODY) \
     107             :     F(SPREAD) \
     108             :     F(MUTATEPROTO) \
     109             :     F(CLASS) \
     110             :     F(CLASSMETHOD) \
     111             :     F(CLASSMETHODLIST) \
     112             :     F(CLASSNAMES) \
     113             :     F(NEWTARGET) \
     114             :     F(POSHOLDER) \
     115             :     F(SUPERBASE) \
     116             :     F(SUPERCALL) \
     117             :     F(SETTHIS) \
     118             :     \
     119             :     /* Unary operators. */ \
     120             :     F(TYPEOFNAME) \
     121             :     F(TYPEOFEXPR) \
     122             :     F(VOID) \
     123             :     F(NOT) \
     124             :     F(BITNOT) \
     125             :     F(AWAIT) \
     126             :     \
     127             :     /* \
     128             :      * Binary operators. \
     129             :      * These must be in the same order as TOK_OR and friends in TokenStream.h. \
     130             :      */ \
     131             :     F(OR) \
     132             :     F(AND) \
     133             :     F(BITOR) \
     134             :     F(BITXOR) \
     135             :     F(BITAND) \
     136             :     F(STRICTEQ) \
     137             :     F(EQ) \
     138             :     F(STRICTNE) \
     139             :     F(NE) \
     140             :     F(LT) \
     141             :     F(LE) \
     142             :     F(GT) \
     143             :     F(GE) \
     144             :     F(INSTANCEOF) \
     145             :     F(IN) \
     146             :     F(LSH) \
     147             :     F(RSH) \
     148             :     F(URSH) \
     149             :     F(ADD) \
     150             :     F(SUB) \
     151             :     F(STAR) \
     152             :     F(DIV) \
     153             :     F(MOD) \
     154             :     F(POW) \
     155             :     \
     156             :     /* Assignment operators (= += -= etc.). */ \
     157             :     /* ParseNode::isAssignment assumes all these are consecutive. */ \
     158             :     F(ASSIGN) \
     159             :     F(ADDASSIGN) \
     160             :     F(SUBASSIGN) \
     161             :     F(BITORASSIGN) \
     162             :     F(BITXORASSIGN) \
     163             :     F(BITANDASSIGN) \
     164             :     F(LSHASSIGN) \
     165             :     F(RSHASSIGN) \
     166             :     F(URSHASSIGN) \
     167             :     F(MULASSIGN) \
     168             :     F(DIVASSIGN) \
     169             :     F(MODASSIGN) \
     170             :     F(POWASSIGN)
     171             : 
     172             : /*
     173             :  * Parsing builds a tree of nodes that directs code generation.  This tree is
     174             :  * not a concrete syntax tree in all respects (for example, || and && are left
     175             :  * associative, but (A && B && C) translates into the right-associated tree
     176             :  * <A && <B && C>> so that code generation can emit a left-associative branch
     177             :  * around <B && C> when A is false).  Nodes are labeled by kind, with a
     178             :  * secondary JSOp label when needed.
     179             :  *
     180             :  * The long comment after this enum block describes the kinds in detail.
     181             :  */
     182             : enum ParseNodeKind
     183             : {
     184             : #define EMIT_ENUM(name) PNK_##name,
     185             :     FOR_EACH_PARSE_NODE_KIND(EMIT_ENUM)
     186             : #undef EMIT_ENUM
     187             :     PNK_LIMIT, /* domain size */
     188             :     PNK_BINOP_FIRST = PNK_OR,
     189             :     PNK_BINOP_LAST = PNK_POW,
     190             :     PNK_ASSIGNMENT_START = PNK_ASSIGN,
     191             :     PNK_ASSIGNMENT_LAST = PNK_POWASSIGN
     192             : };
     193             : 
     194             : inline bool
     195           0 : IsDeleteKind(ParseNodeKind kind)
     196             : {
     197           0 :     return PNK_DELETENAME <= kind && kind <= PNK_DELETEEXPR;
     198             : }
     199             : 
     200             : inline bool
     201           0 : IsTypeofKind(ParseNodeKind kind)
     202             : {
     203           0 :     return PNK_TYPEOFNAME <= kind && kind <= PNK_TYPEOFEXPR;
     204             : }
     205             : 
     206             : /*
     207             :  * Label        Variant     Members
     208             :  * -----        -------     -------
     209             :  * <Definitions>
     210             :  * PNK_FUNCTION name        pn_funbox: ptr to js::FunctionBox holding function
     211             :  *                            object containing arg and var properties.  We
     212             :  *                            create the function object at parse (not emit)
     213             :  *                            time to specialize arg and var bytecodes early.
     214             :  *                          pn_body: PNK_PARAMSBODY, ordinarily;
     215             :  *                            PNK_LEXICALSCOPE for implicit function in genexpr
     216             :  * PNK_PARAMSBODY list      list of formal parameters with
     217             :  *                              PNK_NAME node with non-empty name for
     218             :  *                                SingleNameBinding without Initializer
     219             :  *                              PNK_ASSIGN node for SingleNameBinding with
     220             :  *                                Initializer
     221             :  *                              PNK_NAME node with empty name for destructuring
     222             :  *                                pn_expr: PNK_ARRAY, PNK_OBJECT, or PNK_ASSIGN
     223             :  *                                  PNK_ARRAY or PNK_OBJECT for BindingPattern
     224             :  *                                    without Initializer
     225             :  *                                  PNK_ASSIGN for BindingPattern with
     226             :  *                                    Initializer
     227             :  *                          followed by:
     228             :  *                              PNK_STATEMENTLIST node for function body
     229             :  *                                statements,
     230             :  *                              PNK_RETURN for expression closure
     231             :  *                          pn_count: 1 + number of formal parameters
     232             :  *                          pn_tree: PNK_PARAMSBODY or PNK_STATEMENTLIST node
     233             :  * PNK_SPREAD   unary       pn_kid: expression being spread
     234             :  *
     235             :  * <Statements>
     236             :  * PNK_STATEMENTLIST list   pn_head: list of pn_count statements
     237             :  * PNK_IF       ternary     pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
     238             :  *                            In body of a comprehension or desugared generator
     239             :  *                            expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH,
     240             :  *                            or (if the push was optimized away) empty
     241             :  *                            PNK_STATEMENTLIST.
     242             :  * PNK_SWITCH   binary      pn_left: discriminant
     243             :  *                          pn_right: list of PNK_CASE nodes, with at most one
     244             :  *                            default node, or if there are let bindings
     245             :  *                            in the top level of the switch body's cases, a
     246             :  *                            PNK_LEXICALSCOPE node that contains the list of
     247             :  *                            PNK_CASE nodes.
     248             :  * PNK_CASE     binary      pn_left: case-expression if CaseClause, or
     249             :  *                            null if DefaultClause
     250             :  *                          pn_right: PNK_STATEMENTLIST node for this case's
     251             :  *                            statements
     252             :  *                          pn_u.binary.offset: scratch space for the emitter
     253             :  * PNK_WHILE    binary      pn_left: cond, pn_right: body
     254             :  * PNK_DOWHILE  binary      pn_left: body, pn_right: cond
     255             :  * PNK_FOR      binary      pn_left: either PNK_FORIN (for-in statement),
     256             :  *                            PNK_FOROF (for-of) or PNK_FORHEAD (for(;;))
     257             :  *                          pn_right: body
     258             :  * PNK_COMPREHENSIONFOR     pn_left: either PNK_FORIN or PNK_FOROF
     259             :  *              binary      pn_right: body
     260             :  * PNK_FORIN    ternary     pn_kid1: declaration or expression to left of 'in'
     261             :  *                          pn_kid2: null
     262             :  *                          pn_kid3: object expr to right of 'in'
     263             :  * PNK_FOROF    ternary     pn_kid1: declaration or expression to left of 'of'
     264             :  *                          pn_kid2: null
     265             :  *                          pn_kid3: expr to right of 'of'
     266             :  * PNK_FORHEAD  ternary     pn_kid1:  init expr before first ';' or nullptr
     267             :  *                          pn_kid2:  cond expr before second ';' or nullptr
     268             :  *                          pn_kid3:  update expr after second ';' or nullptr
     269             :  * PNK_THROW    unary       pn_op: JSOP_THROW, pn_kid: exception
     270             :  * PNK_TRY      ternary     pn_kid1: try block
     271             :  *                          pn_kid2: null or PNK_CATCHLIST list
     272             :  *                          pn_kid3: null or finally block
     273             :  * PNK_CATCHLIST list       pn_head: list of PNK_LEXICALSCOPE nodes, one per
     274             :  *                                   catch-block, each with pn_expr pointing
     275             :  *                                   to a PNK_CATCH node
     276             :  * PNK_CATCH    ternary     pn_kid1: PNK_NAME, PNK_ARRAY, or PNK_OBJECT catch var node
     277             :  *                                   (PNK_ARRAY or PNK_OBJECT if destructuring)
     278             :  *                          pn_kid2: null or the catch guard expression
     279             :  *                          pn_kid3: catch block statements
     280             :  * PNK_BREAK    name        pn_atom: label or null
     281             :  * PNK_CONTINUE name        pn_atom: label or null
     282             :  * PNK_WITH     binary      pn_left: head expr; pn_right: body;
     283             :  * PNK_VAR,     list        pn_head: list of PNK_NAME or PNK_ASSIGN nodes
     284             :  * PNK_LET,                          each name node has either
     285             :  * PNK_CONST                           pn_used: false
     286             :  *                                     pn_atom: variable name
     287             :  *                                     pn_expr: initializer or null
     288             :  *                                   or
     289             :  *                                     pn_used: true
     290             :  *                                     pn_atom: variable name
     291             :  *                                     pn_lexdef: def node
     292             :  *                                   each assignment node has
     293             :  *                                     pn_left: PNK_NAME with pn_used true and
     294             :  *                                              pn_lexdef (NOT pn_expr) set
     295             :  *                                     pn_right: initializer
     296             :  * PNK_RETURN   unary       pn_kid: return expr or null
     297             :  * PNK_SEMI     unary       pn_kid: expr or null statement
     298             :  *                          pn_prologue: true if Directive Prologue member
     299             :  *                              in original source, not introduced via
     300             :  *                              constant folding or other tree rewriting
     301             :  * PNK_LABEL    name        pn_atom: label, pn_expr: labeled statement
     302             :  * PNK_IMPORT   binary      pn_left: PNK_IMPORT_SPEC_LIST import specifiers
     303             :  *                          pn_right: PNK_STRING module specifier
     304             :  * PNK_EXPORT   unary       pn_kid: declaration expression
     305             :  * PNK_EXPORT_FROM binary   pn_left: PNK_EXPORT_SPEC_LIST export specifiers
     306             :  *                          pn_right: PNK_STRING module specifier
     307             :  * PNK_EXPORT_DEFAULT unary pn_kid: export default declaration or expression
     308             :  *
     309             :  * <Expressions>
     310             :  * All left-associated binary trees of the same type are optimized into lists
     311             :  * to avoid recursion when processing expression chains.
     312             :  * PNK_COMMA    list        pn_head: list of pn_count comma-separated exprs
     313             :  * PNK_ASSIGN   binary      pn_left: lvalue, pn_right: rvalue
     314             :  * PNK_ADDASSIGN,   binary  pn_left: lvalue, pn_right: rvalue
     315             :  * PNK_SUBASSIGN,           pn_op: JSOP_ADD for +=, etc.
     316             :  * PNK_BITORASSIGN,
     317             :  * PNK_BITXORASSIGN,
     318             :  * PNK_BITANDASSIGN,
     319             :  * PNK_LSHASSIGN,
     320             :  * PNK_RSHASSIGN,
     321             :  * PNK_URSHASSIGN,
     322             :  * PNK_MULASSIGN,
     323             :  * PNK_DIVASSIGN,
     324             :  * PNK_MODASSIGN,
     325             :  * PNK_POWASSIGN
     326             :  * PNK_CONDITIONAL ternary  (cond ? trueExpr : falseExpr)
     327             :  *                          pn_kid1: cond, pn_kid2: then, pn_kid3: else
     328             :  * PNK_OR,      list        pn_head; list of pn_count subexpressions
     329             :  * PNK_AND,                 All of these operators are left-associative except (**).
     330             :  * PNK_BITOR,
     331             :  * PNK_BITXOR,
     332             :  * PNK_BITAND,
     333             :  * PNK_EQ,
     334             :  * PNK_NE,
     335             :  * PNK_STRICTEQ,
     336             :  * PNK_STRICTNE,
     337             :  * PNK_LT,
     338             :  * PNK_LE,
     339             :  * PNK_GT,
     340             :  * PNK_GE,
     341             :  * PNK_LSH,
     342             :  * PNK_RSH,
     343             :  * PNK_URSH,
     344             :  * PNK_ADD,
     345             :  * PNK_SUB,
     346             :  * PNK_STAR,
     347             :  * PNK_DIV,
     348             :  * PNK_MOD,
     349             :  * PNK_POW                  (**) is right-associative, but forms a list
     350             :  *                          nonetheless. Special hacks everywhere.
     351             :  *
     352             :  * PNK_POS,     unary       pn_kid: UNARY expr
     353             :  * PNK_NEG
     354             :  * PNK_VOID,    unary       pn_kid: UNARY expr
     355             :  * PNK_NOT,
     356             :  * PNK_BITNOT
     357             :  * PNK_TYPEOFNAME, unary    pn_kid: UNARY expr
     358             :  * PNK_TYPEOFEXPR
     359             :  * PNK_PREINCREMENT, unary  pn_kid: MEMBER expr
     360             :  * PNK_POSTINCREMENT,
     361             :  * PNK_PREDECREMENT,
     362             :  * PNK_POSTDECREMENT
     363             :  * PNK_NEW      list        pn_head: list of ctor, arg1, arg2, ... argN
     364             :  *                          pn_count: 1 + N (where N is number of args)
     365             :  *                          ctor is a MEMBER expr
     366             :  * PNK_DELETENAME unary     pn_kid: PNK_NAME expr
     367             :  * PNK_DELETEPROP unary     pn_kid: PNK_DOT expr
     368             :  * PNK_DELETEELEM unary     pn_kid: PNK_ELEM expr
     369             :  * PNK_DELETEEXPR unary     pn_kid: MEMBER expr that's evaluated, then the
     370             :  *                          overall delete evaluates to true; can't be a kind
     371             :  *                          for a more-specific PNK_DELETE* unless constant
     372             :  *                          folding (or a similar parse tree manipulation) has
     373             :  *                          occurred
     374             :  * PNK_DOT      name        pn_expr: MEMBER expr to left of .
     375             :  *                          pn_atom: name to right of .
     376             :  * PNK_ELEM     binary      pn_left: MEMBER expr to left of [
     377             :  *                          pn_right: expr between [ and ]
     378             :  * PNK_CALL     list        pn_head: list of call, arg1, arg2, ... argN
     379             :  *                          pn_count: 1 + N (where N is number of args)
     380             :  *                          call is a MEMBER expr naming a callable object
     381             :  * PNK_GENEXP   list        Exactly like PNK_CALL, used for the implicit call
     382             :  *                          in the desugaring of a generator-expression.
     383             :  * PNK_ARRAY    list        pn_head: list of pn_count array element exprs
     384             :  *                          [,,] holes are represented by PNK_ELISION nodes
     385             :  *                          pn_xflags: PN_ENDCOMMA if extra comma at end
     386             :  * PNK_OBJECT   list        pn_head: list of pn_count binary PNK_COLON nodes
     387             :  * PNK_COLON    binary      key-value pair in object initializer or
     388             :  *                          destructuring lhs
     389             :  *                          pn_left: property id, pn_right: value
     390             :  * PNK_SHORTHAND binary     Same fields as PNK_COLON. This is used for object
     391             :  *                          literal properties using shorthand ({x}).
     392             :  * PNK_COMPUTED_NAME unary  ES6 ComputedPropertyName.
     393             :  *                          pn_kid: the AssignmentExpression inside the square brackets
     394             :  * PNK_NAME,    name        pn_atom: name, string, or object atom
     395             :  * PNK_STRING               pn_op: JSOP_GETNAME, JSOP_STRING, or JSOP_OBJECT
     396             :  *                          If JSOP_GETNAME, pn_op may be JSOP_*ARG or JSOP_*VAR
     397             :  *                          telling const-ness and static analysis results
     398             :  * PNK_TEMPLATE_STRING_LIST pn_head: list of alternating expr and template strings
     399             :  *              list
     400             :  * PNK_TEMPLATE_STRING      pn_atom: template string atom
     401             :                 nullary     pn_op: JSOP_NOP
     402             :  * PNK_TAGGED_TEMPLATE      pn_head: list of call, call site object, arg1, arg2, ... argN
     403             :  *              list        pn_count: 2 + N (N is the number of substitutions)
     404             :  * PNK_CALLSITEOBJ list     pn_head: a PNK_ARRAY node followed by
     405             :  *                          list of pn_count - 1 PNK_TEMPLATE_STRING nodes
     406             :  * PNK_REGEXP   nullary     pn_objbox: RegExp model object
     407             :  * PNK_NUMBER   dval        pn_dval: double value of numeric literal
     408             :  * PNK_TRUE,    nullary     pn_op: JSOp bytecode
     409             :  * PNK_FALSE,
     410             :  * PNK_NULL,
     411             :  * PNK_RAW_UNDEFINED
     412             :  *
     413             :  * PNK_THIS,        unary   pn_kid: '.this' Name if function `this`, else nullptr
     414             :  * PNK_SUPERBASE    unary   pn_kid: '.this' Name
     415             :  *
     416             :  * PNK_SETTHIS      binary  pn_left: '.this' Name, pn_right: SuperCall
     417             :  *
     418             :  * PNK_LEXICALSCOPE scope   pn_u.scope.bindings: scope bindings
     419             :  *                          pn_u.scope.body: scope body
     420             :  * PNK_GENERATOR    nullary
     421             :  * PNK_INITIALYIELD unary   pn_kid: generator object
     422             :  * PNK_YIELD,       unary   pn_kid: expr or null
     423             :  * PNK_YIELD_STAR,
     424             :  * PNK_AWAIT
     425             :  * PNK_ARRAYCOMP    list    pn_count: 1
     426             :  *                          pn_head: list of 1 element, which is block
     427             :  *                          enclosing for loop(s) and optionally
     428             :  *                          if-guarded PNK_ARRAYPUSH
     429             :  * PNK_ARRAYPUSH    unary   pn_op: JSOP_ARRAYCOMP
     430             :  *                          pn_kid: array comprehension expression
     431             :  * PNK_NOP          nullary
     432             :  */
     433             : enum ParseNodeArity
     434             : {
     435             :     PN_NULLARY,                         /* 0 kids, only pn_atom/pn_dval/etc. */
     436             :     PN_UNARY,                           /* one kid, plus a couple of scalars */
     437             :     PN_BINARY,                          /* two kids, plus a couple of scalars */
     438             :     PN_TERNARY,                         /* three kids */
     439             :     PN_CODE,                            /* module or function definition node */
     440             :     PN_LIST,                            /* generic singly linked list */
     441             :     PN_NAME,                            /* name, label, or regexp */
     442             :     PN_SCOPE                            /* lexical scope */
     443             : };
     444             : 
     445             : class LoopControlStatement;
     446             : class BreakStatement;
     447             : class ContinueStatement;
     448             : class ConditionalExpression;
     449             : class PropertyAccess;
     450             : 
     451             : class ParseNode
     452             : {
     453             :     uint16_t pn_type;   /* PNK_* type */
     454             :     uint8_t pn_op;      /* see JSOp enum and jsopcode.tbl */
     455             :     uint8_t pn_arity:4; /* see ParseNodeArity enum */
     456             :     bool pn_parens:1;   /* this expr was enclosed in parens */
     457             :     bool pn_rhs_anon_fun:1;  /* this expr is anonymous function or class that
     458             :                               * is a direct RHS of PNK_ASSIGN or PNK_COLON of
     459             :                               * property, that needs SetFunctionName. */
     460             : 
     461             :     ParseNode(const ParseNode& other) = delete;
     462             :     void operator=(const ParseNode& other) = delete;
     463             : 
     464             :   public:
     465             :     ParseNode(ParseNodeKind kind, JSOp op, ParseNodeArity arity)
     466             :       : pn_type(kind),
     467             :         pn_op(op),
     468             :         pn_arity(arity),
     469             :         pn_parens(false),
     470             :         pn_rhs_anon_fun(false),
     471             :         pn_pos(0, 0),
     472             :         pn_next(nullptr)
     473             :     {
     474             :         MOZ_ASSERT(kind < PNK_LIMIT);
     475             :         memset(&pn_u, 0, sizeof pn_u);
     476             :     }
     477             : 
     478      310719 :     ParseNode(ParseNodeKind kind, JSOp op, ParseNodeArity arity, const TokenPos& pos)
     479      310719 :       : pn_type(kind),
     480             :         pn_op(op),
     481             :         pn_arity(arity),
     482             :         pn_parens(false),
     483             :         pn_rhs_anon_fun(false),
     484             :         pn_pos(pos),
     485      310719 :         pn_next(nullptr)
     486             :     {
     487      310719 :         MOZ_ASSERT(kind < PNK_LIMIT);
     488      310719 :         memset(&pn_u, 0, sizeof pn_u);
     489      310719 :     }
     490             : 
     491      316024 :     JSOp getOp() const                     { return JSOp(pn_op); }
     492       38310 :     void setOp(JSOp op)                    { pn_op = op; }
     493      123224 :     bool isOp(JSOp op) const               { return getOp() == op; }
     494             : 
     495     4459471 :     ParseNodeKind getKind() const {
     496     4459471 :         MOZ_ASSERT(pn_type < PNK_LIMIT);
     497     4459471 :         return ParseNodeKind(pn_type);
     498             :     }
     499        2036 :     void setKind(ParseNodeKind kind) {
     500        2036 :         MOZ_ASSERT(kind < PNK_LIMIT);
     501        2036 :         pn_type = kind;
     502        2036 :     }
     503     2759948 :     bool isKind(ParseNodeKind kind) const  { return getKind() == kind; }
     504             : 
     505     1557370 :     ParseNodeArity getArity() const        { return ParseNodeArity(pn_arity); }
     506     1557370 :     bool isArity(ParseNodeArity a) const   { return getArity() == a; }
     507        1457 :     void setArity(ParseNodeArity a)        { pn_arity = a; }
     508             : 
     509        4370 :     bool isAssignment() const {
     510        4370 :         ParseNodeKind kind = getKind();
     511        4370 :         return PNK_ASSIGNMENT_START <= kind && kind <= PNK_ASSIGNMENT_LAST;
     512             :     }
     513             : 
     514           0 :     bool isBinaryOperation() const {
     515           0 :         ParseNodeKind kind = getKind();
     516           0 :         return PNK_BINOP_FIRST <= kind && kind <= PNK_BINOP_LAST;
     517             :     }
     518             : 
     519             :     /* Boolean attributes. */
     520       51835 :     bool isInParens() const                { return pn_parens; }
     521        5479 :     bool isLikelyIIFE() const              { return isInParens(); }
     522        2046 :     void setInParens(bool enabled)         { pn_parens = enabled; }
     523             : 
     524       17734 :     bool isDirectRHSAnonFunction() const {
     525       17734 :         return pn_rhs_anon_fun;
     526             :     }
     527         491 :     void setDirectRHSAnonFunction(bool enabled) {
     528         491 :         pn_rhs_anon_fun = enabled;
     529         491 :     }
     530             : 
     531             :     TokenPos            pn_pos;         /* two 16-bit pairs here, for 64 bits */
     532             :     ParseNode*          pn_next;        /* intrinsic link in parent PN_LIST */
     533             : 
     534             :     union {
     535             :         struct {                        /* list of next-linked nodes */
     536             :             ParseNode*  head;           /* first node in list */
     537             :             ParseNode** tail;           /* ptr to ptr to last node in list */
     538             :             uint32_t    count;          /* number of nodes in list */
     539             :             uint32_t    xflags;         /* see PNX_* below */
     540             :         } list;
     541             :         struct {                        /* ternary: if, for(;;), ?: */
     542             :             ParseNode*  kid1;           /* condition, discriminant, etc. */
     543             :             ParseNode*  kid2;           /* then-part, case list, etc. */
     544             :             ParseNode*  kid3;           /* else-part, default case, etc. */
     545             :         } ternary;
     546             :         struct {                        /* two kids if binary */
     547             :             ParseNode*  left;
     548             :             ParseNode*  right;
     549             :             union {
     550             :                 unsigned iflags;        /* JSITER_* flags for PNK_{COMPREHENSION,}FOR node */
     551             :                 bool isStatic;          /* only for PNK_CLASSMETHOD */
     552             :                 uint32_t offset;        /* for the emitter's use on PNK_CASE nodes */
     553             :             };
     554             :         } binary;
     555             :         struct {                        /* one kid if unary */
     556             :             ParseNode*  kid;
     557             :             bool        prologue;       /* directive prologue member (as
     558             :                                            pn_prologue) */
     559             :         } unary;
     560             :         struct {                        /* name, labeled statement, etc. */
     561             :             union {
     562             :                 JSAtom*      atom;      /* lexical name or label atom */
     563             :                 ObjectBox*   objbox;    /* regexp object */
     564             :                 FunctionBox* funbox;    /* function object */
     565             :             };
     566             :             ParseNode*  expr;           /* module or function body, var
     567             :                                            initializer, argument default, or
     568             :                                            base object of PNK_DOT */
     569             :         } name;
     570             :         struct {
     571             :             LexicalScope::Data* bindings;
     572             :             ParseNode*          body;
     573             :         } scope;
     574             :         struct {
     575             :             double       value;         /* aligned numeric literal value */
     576             :             DecimalPoint decimalPoint;  /* Whether the number has a decimal point */
     577             :         } number;
     578             :         class {
     579             :             friend class LoopControlStatement;
     580             :             PropertyName*    label;    /* target of break/continue statement */
     581             :         } loopControl;
     582             :     } pn_u;
     583             : 
     584             : #define pn_objbox       pn_u.name.objbox
     585             : #define pn_funbox       pn_u.name.funbox
     586             : #define pn_body         pn_u.name.expr
     587             : #define pn_head         pn_u.list.head
     588             : #define pn_tail         pn_u.list.tail
     589             : #define pn_count        pn_u.list.count
     590             : #define pn_xflags       pn_u.list.xflags
     591             : #define pn_kid1         pn_u.ternary.kid1
     592             : #define pn_kid2         pn_u.ternary.kid2
     593             : #define pn_kid3         pn_u.ternary.kid3
     594             : #define pn_left         pn_u.binary.left
     595             : #define pn_right        pn_u.binary.right
     596             : #define pn_pval         pn_u.binary.pval
     597             : #define pn_iflags       pn_u.binary.iflags
     598             : #define pn_kid          pn_u.unary.kid
     599             : #define pn_prologue     pn_u.unary.prologue
     600             : #define pn_atom         pn_u.name.atom
     601             : #define pn_objbox       pn_u.name.objbox
     602             : #define pn_expr         pn_u.name.expr
     603             : #define pn_dval         pn_u.number.value
     604             : 
     605             : 
     606             :   public:
     607             :     /*
     608             :      * If |left| is a list of the given kind/left-associative op, append
     609             :      * |right| to it and return |left|.  Otherwise return a [left, right] list.
     610             :      */
     611             :     static ParseNode*
     612             :     appendOrCreateList(ParseNodeKind kind, JSOp op, ParseNode* left, ParseNode* right,
     613             :                        FullParseHandler* handler, ParseContext* pc);
     614             : 
     615             :     inline PropertyName* name() const;
     616             :     inline JSAtom* atom() const;
     617             : 
     618      132881 :     ParseNode* expr() const {
     619      132881 :         MOZ_ASSERT(pn_arity == PN_NAME || pn_arity == PN_CODE);
     620      132881 :         return pn_expr;
     621             :     }
     622             : 
     623       15830 :     bool isEmptyScope() const {
     624       15830 :         MOZ_ASSERT(pn_arity == PN_SCOPE);
     625       15830 :         return !pn_u.scope.bindings;
     626             :     }
     627             : 
     628        2941 :     Handle<LexicalScope::Data*> scopeBindings() const {
     629        2941 :         MOZ_ASSERT(!isEmptyScope());
     630             :         // Bindings' GC safety depend on the presence of an AutoKeepAtoms that
     631             :         // the rest of the frontend also depends on.
     632        2941 :         return Handle<LexicalScope::Data*>::fromMarkedLocation(&pn_u.scope.bindings);
     633             :     }
     634             : 
     635       60630 :     ParseNode* scopeBody() const {
     636       60630 :         MOZ_ASSERT(pn_arity == PN_SCOPE);
     637       60630 :         return pn_u.scope.body;
     638             :     }
     639             : 
     640       10121 :     void setScopeBody(ParseNode* body) {
     641       10121 :         MOZ_ASSERT(pn_arity == PN_SCOPE);
     642       10121 :         pn_u.scope.body = body;
     643       10121 :     }
     644             : 
     645             : /* PN_LIST pn_xflags bits. */
     646             : #define PNX_FUNCDEFS    0x01            /* contains top-level function statements */
     647             : #define PNX_ARRAYHOLESPREAD 0x02        /* one or more of
     648             :                                            1. array initialiser has holes
     649             :                                            2. array initializer has spread node */
     650             : #define PNX_NONCONST    0x04            /* initialiser has non-constants */
     651             : 
     652        5930 :     bool functionIsHoisted() const {
     653        5930 :         MOZ_ASSERT(pn_arity == PN_CODE && getKind() == PNK_FUNCTION);
     654        5930 :         MOZ_ASSERT(isOp(JSOP_LAMBDA) ||        // lambda, genexpr
     655             :                    isOp(JSOP_LAMBDA_ARROW) ||  // arrow function
     656             :                    isOp(JSOP_DEFFUN) ||        // non-body-level function statement
     657             :                    isOp(JSOP_NOP) ||           // body-level function stmt in global code
     658             :                    isOp(JSOP_GETLOCAL) ||      // body-level function stmt in function code
     659             :                    isOp(JSOP_GETARG) ||        // body-level function redeclaring formal
     660             :                    isOp(JSOP_INITLEXICAL));    // block-level function stmt
     661        5930 :         return !isOp(JSOP_LAMBDA) && !isOp(JSOP_LAMBDA_ARROW) && !isOp(JSOP_DEFFUN);
     662             :     }
     663             : 
     664             :     /*
     665             :      * True if this statement node could be a member of a Directive Prologue: an
     666             :      * expression statement consisting of a single string literal.
     667             :      *
     668             :      * This considers only the node and its children, not its context. After
     669             :      * parsing, check the node's pn_prologue flag to see if it is indeed part of
     670             :      * a directive prologue.
     671             :      *
     672             :      * Note that a Directive Prologue can contain statements that cannot
     673             :      * themselves be directives (string literals that include escape sequences
     674             :      * or escaped newlines, say). This member function returns true for such
     675             :      * nodes; we use it to determine the extent of the prologue.
     676             :      */
     677        5291 :     JSAtom* isStringExprStatement() const {
     678        5291 :         if (getKind() == PNK_SEMI) {
     679        1460 :             MOZ_ASSERT(pn_arity == PN_UNARY);
     680        1460 :             ParseNode* kid = pn_kid;
     681        1460 :             if (kid && kid->getKind() == PNK_STRING && !kid->pn_parens)
     682         113 :                 return kid->pn_atom;
     683             :         }
     684        5178 :         return nullptr;
     685             :     }
     686             : 
     687             :     /* True if pn is a parsenode representing a literal constant. */
     688         508 :     bool isLiteral() const {
     689        1013 :         return isKind(PNK_NUMBER) ||
     690         585 :                isKind(PNK_STRING) ||
     691         160 :                isKind(PNK_TRUE) ||
     692         160 :                isKind(PNK_FALSE) ||
     693         668 :                isKind(PNK_NULL) ||
     694         588 :                isKind(PNK_RAW_UNDEFINED);
     695             :     }
     696             : 
     697             :     /* Return true if this node appears in a Directive Prologue. */
     698         107 :     bool isDirectivePrologueMember() const { return pn_prologue; }
     699             : 
     700             :     // True iff this is a for-in/of loop variable declaration (var/let/const).
     701         766 :     bool isForLoopDeclaration() const {
     702         766 :         if (isKind(PNK_VAR) || isKind(PNK_LET) || isKind(PNK_CONST)) {
     703         742 :             MOZ_ASSERT(isArity(PN_LIST));
     704         742 :             MOZ_ASSERT(pn_count > 0);
     705         742 :             return true;
     706             :         }
     707             : 
     708          24 :         return false;
     709             :     }
     710             : 
     711           0 :     ParseNode* generatorExpr() const {
     712           0 :         MOZ_ASSERT(isKind(PNK_GENEXP));
     713             : 
     714           0 :         ParseNode* callee = this->pn_head;
     715           0 :         MOZ_ASSERT(callee->isKind(PNK_FUNCTION));
     716             : 
     717           0 :         ParseNode* paramsBody = callee->pn_body;
     718           0 :         MOZ_ASSERT(paramsBody->isKind(PNK_PARAMSBODY));
     719             : 
     720           0 :         ParseNode* body = paramsBody->last();
     721           0 :         MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
     722           0 :         MOZ_ASSERT(body->last()->isKind(PNK_LEXICALSCOPE) ||
     723             :                    body->last()->isKind(PNK_COMPREHENSIONFOR));
     724           0 :         return body->last();
     725             :     }
     726             : 
     727             :     /*
     728             :      * Compute a pointer to the last element in a singly-linked list. NB: list
     729             :      * must be non-empty for correct PN_LAST usage -- this is asserted!
     730             :      */
     731       11355 :     ParseNode* last() const {
     732       11355 :         MOZ_ASSERT(pn_arity == PN_LIST);
     733       11355 :         MOZ_ASSERT(pn_count != 0);
     734       11355 :         return (ParseNode*)(uintptr_t(pn_tail) - offsetof(ParseNode, pn_next));
     735             :     }
     736             : 
     737        9347 :     void initNumber(double value, DecimalPoint decimalPoint) {
     738        9347 :         MOZ_ASSERT(pn_arity == PN_NULLARY);
     739        9347 :         MOZ_ASSERT(getKind() == PNK_NUMBER);
     740        9347 :         pn_u.number.value = value;
     741        9347 :         pn_u.number.decimalPoint = decimalPoint;
     742        9347 :     }
     743             : 
     744       54475 :     void makeEmpty() {
     745       54475 :         MOZ_ASSERT(pn_arity == PN_LIST);
     746       54475 :         pn_head = nullptr;
     747       54475 :         pn_tail = &pn_head;
     748       54475 :         pn_count = 0;
     749       54475 :         pn_xflags = 0;
     750       54475 :     }
     751             : 
     752       11130 :     void initList(ParseNode* pn) {
     753       11130 :         MOZ_ASSERT(pn_arity == PN_LIST);
     754       11130 :         if (pn->pn_pos.begin < pn_pos.begin)
     755           0 :             pn_pos.begin = pn->pn_pos.begin;
     756       11130 :         pn_pos.end = pn->pn_pos.end;
     757       11130 :         pn_head = pn;
     758       11130 :         pn_tail = &pn->pn_next;
     759       11130 :         pn_count = 1;
     760       11130 :         pn_xflags = 0;
     761       11130 :     }
     762             : 
     763      146268 :     void append(ParseNode* pn) {
     764      146268 :         MOZ_ASSERT(pn_arity == PN_LIST);
     765      146268 :         MOZ_ASSERT(pn->pn_pos.begin >= pn_pos.begin);
     766      146268 :         pn_pos.end = pn->pn_pos.end;
     767      146268 :         *pn_tail = pn;
     768      146268 :         pn_tail = &pn->pn_next;
     769      146268 :         pn_count++;
     770      146268 :     }
     771             : 
     772         127 :     void prepend(ParseNode* pn) {
     773         127 :         MOZ_ASSERT(pn_arity == PN_LIST);
     774         127 :         pn->pn_next = pn_head;
     775         127 :         pn_head = pn;
     776         127 :         if (pn_tail == &pn_head)
     777           0 :             pn_tail = &pn->pn_next;
     778         127 :         pn_count++;
     779         127 :     }
     780             : 
     781             :     void checkListConsistency()
     782             : #ifndef DEBUG
     783             :     {}
     784             : #endif
     785             :     ;
     786             : 
     787             :     enum AllowConstantObjects {
     788             :         DontAllowObjects = 0,
     789             :         AllowObjects,
     790             :         ForCopyOnWriteArray
     791             :     };
     792             : 
     793             :     MOZ_MUST_USE bool getConstantValue(JSContext* cx, AllowConstantObjects allowObjects,
     794             :                                        MutableHandleValue vp, Value* compare = nullptr,
     795             :                                        size_t ncompare = 0, NewObjectKind newKind = TenuredObject);
     796             :     inline bool isConstant();
     797             : 
     798             :     template <class NodeType>
     799       43575 :     inline bool is() const {
     800       43575 :         return NodeType::test(*this);
     801             :     }
     802             : 
     803             :     /* Casting operations. */
     804             :     template <class NodeType>
     805      106296 :     inline NodeType& as() {
     806      106296 :         MOZ_ASSERT(NodeType::test(*this));
     807      106296 :         return *static_cast<NodeType*>(this);
     808             :     }
     809             : 
     810             :     template <class NodeType>
     811             :     inline const NodeType& as() const {
     812             :         MOZ_ASSERT(NodeType::test(*this));
     813             :         return *static_cast<const NodeType*>(this);
     814             :     }
     815             : 
     816             : #ifdef DEBUG
     817             :     void dump();
     818             :     void dump(int indent);
     819             : #endif
     820             : };
     821             : 
     822             : struct NullaryNode : public ParseNode
     823             : {
     824       10486 :     NullaryNode(ParseNodeKind kind, const TokenPos& pos)
     825       10486 :       : ParseNode(kind, JSOP_NOP, PN_NULLARY, pos) {}
     826         169 :     NullaryNode(ParseNodeKind kind, JSOp op, const TokenPos& pos)
     827         169 :       : ParseNode(kind, op, PN_NULLARY, pos) {}
     828             : 
     829             :     // This constructor is for a few mad uses in the emitter. It populates
     830             :     // the pn_atom field even though that field belongs to a branch in pn_u
     831             :     // that nullary nodes shouldn't use -- bogus.
     832       26573 :     NullaryNode(ParseNodeKind kind, JSOp op, const TokenPos& pos, JSAtom* atom)
     833       26573 :       : ParseNode(kind, op, PN_NULLARY, pos)
     834             :     {
     835       26573 :         pn_atom = atom;
     836       26573 :     }
     837             : 
     838             : #ifdef DEBUG
     839             :     void dump();
     840             : #endif
     841             : };
     842             : 
     843             : struct UnaryNode : public ParseNode
     844             : {
     845       33459 :     UnaryNode(ParseNodeKind kind, JSOp op, const TokenPos& pos, ParseNode* kid)
     846       33459 :       : ParseNode(kind, op, PN_UNARY, pos)
     847             :     {
     848       33459 :         pn_kid = kid;
     849       33459 :     }
     850             : 
     851             : #ifdef DEBUG
     852             :     void dump(int indent);
     853             : #endif
     854             : };
     855             : 
     856             : struct BinaryNode : public ParseNode
     857             : {
     858       17596 :     BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos& pos, ParseNode* left, ParseNode* right)
     859       17596 :       : ParseNode(kind, op, PN_BINARY, pos)
     860             :     {
     861       17596 :         pn_left = left;
     862       17596 :         pn_right = right;
     863       17596 :     }
     864             : 
     865          12 :     BinaryNode(ParseNodeKind kind, JSOp op, ParseNode* left, ParseNode* right)
     866          12 :       : ParseNode(kind, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos))
     867             :     {
     868          12 :         pn_left = left;
     869          12 :         pn_right = right;
     870          12 :     }
     871             : 
     872             : #ifdef DEBUG
     873             :     void dump(int indent);
     874             : #endif
     875             : };
     876             : 
     877             : struct TernaryNode : public ParseNode
     878             : {
     879        7496 :     TernaryNode(ParseNodeKind kind, JSOp op, ParseNode* kid1, ParseNode* kid2, ParseNode* kid3)
     880        7496 :       : ParseNode(kind, op, PN_TERNARY,
     881       14992 :                   TokenPos((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin,
     882       14992 :                            (kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end))
     883             :     {
     884        7496 :         pn_kid1 = kid1;
     885        7496 :         pn_kid2 = kid2;
     886        7496 :         pn_kid3 = kid3;
     887        7496 :     }
     888             : 
     889        1323 :     TernaryNode(ParseNodeKind kind, JSOp op, ParseNode* kid1, ParseNode* kid2, ParseNode* kid3,
     890             :                 const TokenPos& pos)
     891        1323 :       : ParseNode(kind, op, PN_TERNARY, pos)
     892             :     {
     893        1323 :         pn_kid1 = kid1;
     894        1323 :         pn_kid2 = kid2;
     895        1323 :         pn_kid3 = kid3;
     896        1323 :     }
     897             : 
     898             : #ifdef DEBUG
     899             :     void dump(int indent);
     900             : #endif
     901             : };
     902             : 
     903             : struct ListNode : public ParseNode
     904             : {
     905       16703 :     ListNode(ParseNodeKind kind, const TokenPos& pos)
     906       16703 :       : ParseNode(kind, JSOP_NOP, PN_LIST, pos)
     907             :     {
     908       16703 :         makeEmpty();
     909       16703 :     }
     910             : 
     911       37713 :     ListNode(ParseNodeKind kind, JSOp op, const TokenPos& pos)
     912       37713 :       : ParseNode(kind, op, PN_LIST, pos)
     913             :     {
     914       37713 :         makeEmpty();
     915       37713 :     }
     916             : 
     917       11130 :     ListNode(ParseNodeKind kind, JSOp op, ParseNode* kid)
     918       11130 :       : ParseNode(kind, op, PN_LIST, kid->pn_pos)
     919             :     {
     920       11130 :         initList(kid);
     921       11130 :     }
     922             : 
     923        3013 :     static bool test(const ParseNode& node) {
     924        3013 :         return node.isArity(PN_LIST);
     925             :     }
     926             : 
     927             : #ifdef DEBUG
     928             :     void dump(int indent);
     929             : #endif
     930             : };
     931             : 
     932             : struct CodeNode : public ParseNode
     933             : {
     934        7161 :     CodeNode(ParseNodeKind kind, JSOp op, const TokenPos& pos)
     935        7161 :       : ParseNode(kind, op, PN_CODE, pos)
     936             :     {
     937        7161 :         MOZ_ASSERT(kind == PNK_FUNCTION || kind == PNK_MODULE);
     938        7161 :         MOZ_ASSERT_IF(kind == PNK_MODULE, op == JSOP_NOP);
     939        7161 :         MOZ_ASSERT(op == JSOP_NOP || // statement, module
     940             :                    op == JSOP_LAMBDA_ARROW || // arrow function
     941             :                    op == JSOP_LAMBDA); // expression, method, comprehension, accessor, &c.
     942        7161 :         MOZ_ASSERT(!pn_body);
     943        7161 :         MOZ_ASSERT(!pn_objbox);
     944        7161 :     }
     945             : 
     946             :   public:
     947             : #ifdef DEBUG
     948             :     void dump(int indent);
     949             : #endif
     950             : };
     951             : 
     952             : struct NameNode : public ParseNode
     953             : {
     954       91188 :     NameNode(ParseNodeKind kind, JSOp op, JSAtom* atom, const TokenPos& pos)
     955       91188 :       : ParseNode(kind, op, PN_NAME, pos)
     956             :     {
     957       91188 :         pn_atom = atom;
     958       91188 :         pn_expr = nullptr;
     959       91188 :     }
     960             : 
     961             : #ifdef DEBUG
     962             :     void dump(int indent);
     963             : #endif
     964             : };
     965             : 
     966             : struct LexicalScopeNode : public ParseNode
     967             : {
     968       12798 :     LexicalScopeNode(LexicalScope::Data* bindings, ParseNode* body)
     969       12798 :       : ParseNode(PNK_LEXICALSCOPE, JSOP_NOP, PN_SCOPE, body->pn_pos)
     970             :     {
     971       12798 :         pn_u.scope.bindings = bindings;
     972       12798 :         pn_u.scope.body = body;
     973       12798 :     }
     974             : 
     975          84 :     static bool test(const ParseNode& node) {
     976          84 :         return node.isKind(PNK_LEXICALSCOPE);
     977             :     }
     978             : 
     979             : #ifdef DEBUG
     980             :     void dump(int indent);
     981             : #endif
     982             : };
     983             : 
     984             : class LabeledStatement : public ParseNode
     985             : {
     986             :   public:
     987           0 :     LabeledStatement(PropertyName* label, ParseNode* stmt, uint32_t begin)
     988           0 :       : ParseNode(PNK_LABEL, JSOP_NOP, PN_NAME, TokenPos(begin, stmt->pn_pos.end))
     989             :     {
     990           0 :         pn_atom = label;
     991           0 :         pn_expr = stmt;
     992           0 :     }
     993             : 
     994           0 :     PropertyName* label() const {
     995           0 :         return pn_atom->asPropertyName();
     996             :     }
     997             : 
     998           0 :     ParseNode* statement() const {
     999           0 :         return pn_expr;
    1000             :     }
    1001             : 
    1002           0 :     static bool test(const ParseNode& node) {
    1003           0 :         bool match = node.isKind(PNK_LABEL);
    1004           0 :         MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
    1005           0 :         MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP));
    1006           0 :         return match;
    1007             :     }
    1008             : };
    1009             : 
    1010             : // Inside a switch statement, a CaseClause is a case-label and the subsequent
    1011             : // statements. The same node type is used for DefaultClauses. The only
    1012             : // difference is that their caseExpression() is null.
    1013             : class CaseClause : public BinaryNode
    1014             : {
    1015             :   public:
    1016        1112 :     CaseClause(ParseNode* expr, ParseNode* stmts, uint32_t begin)
    1017        1112 :       : BinaryNode(PNK_CASE, JSOP_NOP, TokenPos(begin, stmts->pn_pos.end), expr, stmts) {}
    1018             : 
    1019        4578 :     ParseNode* caseExpression() const { return pn_left; }
    1020        2770 :     bool isDefault() const { return !caseExpression(); }
    1021        1116 :     ParseNode* statementList() const { return pn_right; }
    1022             : 
    1023             :     // The next CaseClause in the same switch statement.
    1024        3342 :     CaseClause* next() const { return pn_next ? &pn_next->as<CaseClause>() : nullptr; }
    1025             : 
    1026             :     // Scratch space used by the emitter.
    1027        1059 :     uint32_t offset() const { return pn_u.binary.offset; }
    1028        1622 :     void setOffset(uint32_t u) { pn_u.binary.offset = u; }
    1029             : 
    1030        2926 :     static bool test(const ParseNode& node) {
    1031        2926 :         bool match = node.isKind(PNK_CASE);
    1032        2926 :         MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
    1033        2926 :         MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP));
    1034        2926 :         return match;
    1035             :     }
    1036             : };
    1037             : 
    1038             : class LoopControlStatement : public ParseNode
    1039             : {
    1040             :   protected:
    1041         597 :     LoopControlStatement(ParseNodeKind kind, PropertyName* label, const TokenPos& pos)
    1042         597 :       : ParseNode(kind, JSOP_NOP, PN_NULLARY, pos)
    1043             :     {
    1044         597 :         MOZ_ASSERT(kind == PNK_BREAK || kind == PNK_CONTINUE);
    1045         597 :         pn_u.loopControl.label = label;
    1046         597 :     }
    1047             : 
    1048             :   public:
    1049             :     /* Label associated with this break/continue statement, if any. */
    1050         600 :     PropertyName* label() const {
    1051         600 :         return pn_u.loopControl.label;
    1052             :     }
    1053             : 
    1054           0 :     static bool test(const ParseNode& node) {
    1055           0 :         bool match = node.isKind(PNK_BREAK) || node.isKind(PNK_CONTINUE);
    1056           0 :         MOZ_ASSERT_IF(match, node.isArity(PN_NULLARY));
    1057           0 :         MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP));
    1058           0 :         return match;
    1059             :     }
    1060             : };
    1061             : 
    1062             : class BreakStatement : public LoopControlStatement
    1063             : {
    1064             :   public:
    1065         476 :     BreakStatement(PropertyName* label, const TokenPos& pos)
    1066         476 :       : LoopControlStatement(PNK_BREAK, label, pos)
    1067         476 :     { }
    1068             : 
    1069         479 :     static bool test(const ParseNode& node) {
    1070         479 :         bool match = node.isKind(PNK_BREAK);
    1071         479 :         MOZ_ASSERT_IF(match, node.isArity(PN_NULLARY));
    1072         479 :         MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP));
    1073         479 :         return match;
    1074             :     }
    1075             : };
    1076             : 
    1077             : class ContinueStatement : public LoopControlStatement
    1078             : {
    1079             :   public:
    1080         121 :     ContinueStatement(PropertyName* label, const TokenPos& pos)
    1081         121 :       : LoopControlStatement(PNK_CONTINUE, label, pos)
    1082         121 :     { }
    1083             : 
    1084         121 :     static bool test(const ParseNode& node) {
    1085         121 :         bool match = node.isKind(PNK_CONTINUE);
    1086         121 :         MOZ_ASSERT_IF(match, node.isArity(PN_NULLARY));
    1087         121 :         MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP));
    1088         121 :         return match;
    1089             :     }
    1090             : };
    1091             : 
    1092             : class DebuggerStatement : public ParseNode
    1093             : {
    1094             :   public:
    1095           0 :     explicit DebuggerStatement(const TokenPos& pos)
    1096           0 :       : ParseNode(PNK_DEBUGGER, JSOP_NOP, PN_NULLARY, pos)
    1097           0 :     { }
    1098             : };
    1099             : 
    1100             : class ConditionalExpression : public ParseNode
    1101             : {
    1102             :   public:
    1103         652 :     ConditionalExpression(ParseNode* condition, ParseNode* thenExpr, ParseNode* elseExpr)
    1104         652 :       : ParseNode(PNK_CONDITIONAL, JSOP_NOP, PN_TERNARY,
    1105         652 :                   TokenPos(condition->pn_pos.begin, elseExpr->pn_pos.end))
    1106             :     {
    1107         652 :         MOZ_ASSERT(condition);
    1108         652 :         MOZ_ASSERT(thenExpr);
    1109         652 :         MOZ_ASSERT(elseExpr);
    1110         652 :         pn_u.ternary.kid1 = condition;
    1111         652 :         pn_u.ternary.kid2 = thenExpr;
    1112         652 :         pn_u.ternary.kid3 = elseExpr;
    1113         652 :     }
    1114             : 
    1115         657 :     ParseNode& condition() const {
    1116         657 :         return *pn_u.ternary.kid1;
    1117             :     }
    1118             : 
    1119         657 :     ParseNode& thenExpression() const {
    1120         657 :         return *pn_u.ternary.kid2;
    1121             :     }
    1122             : 
    1123         657 :     ParseNode& elseExpression() const {
    1124         657 :         return *pn_u.ternary.kid3;
    1125             :     }
    1126             : 
    1127         657 :     static bool test(const ParseNode& node) {
    1128         657 :         bool match = node.isKind(PNK_CONDITIONAL);
    1129         657 :         MOZ_ASSERT_IF(match, node.isArity(PN_TERNARY));
    1130         657 :         MOZ_ASSERT_IF(match, node.isOp(JSOP_NOP));
    1131         657 :         return match;
    1132             :     }
    1133             : };
    1134             : 
    1135             : class ThisLiteral : public UnaryNode
    1136             : {
    1137             :   public:
    1138        7628 :     ThisLiteral(const TokenPos& pos, ParseNode* thisName)
    1139        7628 :       : UnaryNode(PNK_THIS, JSOP_NOP, pos, thisName)
    1140        7628 :     { }
    1141             : };
    1142             : 
    1143             : class NullLiteral : public ParseNode
    1144             : {
    1145             :   public:
    1146        2043 :     explicit NullLiteral(const TokenPos& pos) : ParseNode(PNK_NULL, JSOP_NULL, PN_NULLARY, pos) { }
    1147             : };
    1148             : 
    1149             : // This is only used internally, currently just for tagged templates.
    1150             : // It represents the value 'undefined' (aka `void 0`), like NullLiteral
    1151             : // represents the value 'null'.
    1152             : class RawUndefinedLiteral : public ParseNode
    1153             : {
    1154             :   public:
    1155           0 :     explicit RawUndefinedLiteral(const TokenPos& pos)
    1156           0 :       : ParseNode(PNK_RAW_UNDEFINED, JSOP_UNDEFINED, PN_NULLARY, pos) { }
    1157             : };
    1158             : 
    1159             : class BooleanLiteral : public ParseNode
    1160             : {
    1161             :   public:
    1162        2325 :     BooleanLiteral(bool b, const TokenPos& pos)
    1163        2325 :       : ParseNode(b ? PNK_TRUE : PNK_FALSE, b ? JSOP_TRUE : JSOP_FALSE, PN_NULLARY, pos)
    1164        2325 :     { }
    1165             : };
    1166             : 
    1167             : class RegExpLiteral : public NullaryNode
    1168             : {
    1169             :   public:
    1170         169 :     RegExpLiteral(ObjectBox* reobj, const TokenPos& pos)
    1171         169 :       : NullaryNode(PNK_REGEXP, JSOP_REGEXP, pos)
    1172             :     {
    1173         169 :         pn_objbox = reobj;
    1174         169 :     }
    1175             : 
    1176         172 :     ObjectBox* objbox() const { return pn_objbox; }
    1177             : 
    1178         172 :     static bool test(const ParseNode& node) {
    1179         172 :         bool match = node.isKind(PNK_REGEXP);
    1180         172 :         MOZ_ASSERT_IF(match, node.isArity(PN_NULLARY));
    1181         172 :         MOZ_ASSERT_IF(match, node.isOp(JSOP_REGEXP));
    1182         172 :         return match;
    1183             :     }
    1184             : };
    1185             : 
    1186             : class PropertyAccess : public ParseNode
    1187             : {
    1188             :   public:
    1189       28199 :     PropertyAccess(ParseNode* lhs, PropertyName* name, uint32_t begin, uint32_t end)
    1190       28199 :       : ParseNode(PNK_DOT, JSOP_NOP, PN_NAME, TokenPos(begin, end))
    1191             :     {
    1192       28199 :         MOZ_ASSERT(lhs != nullptr);
    1193       28199 :         MOZ_ASSERT(name != nullptr);
    1194       28199 :         pn_u.name.expr = lhs;
    1195       28199 :         pn_u.name.atom = name;
    1196       28199 :     }
    1197             : 
    1198      113719 :     static bool test(const ParseNode& node) {
    1199      113719 :         bool match = node.isKind(PNK_DOT);
    1200      113719 :         MOZ_ASSERT_IF(match, node.isArity(PN_NAME));
    1201      113719 :         return match;
    1202             :     }
    1203             : 
    1204       81781 :     ParseNode& expression() const {
    1205       81781 :         return *pn_u.name.expr;
    1206             :     }
    1207             : 
    1208       10838 :     PropertyName& name() const {
    1209       10838 :         return *pn_u.name.atom->asPropertyName();
    1210             :     }
    1211             : 
    1212       81768 :     bool isSuper() const {
    1213             :         // PNK_SUPERBASE cannot result from any expression syntax.
    1214       81768 :         return expression().isKind(PNK_SUPERBASE);
    1215             :     }
    1216             : };
    1217             : 
    1218             : class PropertyByValue : public ParseNode
    1219             : {
    1220             :   public:
    1221        3043 :     PropertyByValue(ParseNode* lhs, ParseNode* propExpr, uint32_t begin, uint32_t end)
    1222        3043 :       : ParseNode(PNK_ELEM, JSOP_NOP, PN_BINARY, TokenPos(begin, end))
    1223             :     {
    1224        3043 :         pn_u.binary.left = lhs;
    1225        3043 :         pn_u.binary.right = propExpr;
    1226        3043 :     }
    1227             : 
    1228        6011 :     static bool test(const ParseNode& node) {
    1229        6011 :         bool match = node.isKind(PNK_ELEM);
    1230        6011 :         MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
    1231        6011 :         return match;
    1232             :     }
    1233             : 
    1234        6011 :     bool isSuper() const {
    1235        6011 :         return pn_left->isKind(PNK_SUPERBASE);
    1236             :     }
    1237             : };
    1238             : 
    1239             : /*
    1240             :  * A CallSiteNode represents the implicit call site object argument in a TaggedTemplate.
    1241             :  */
    1242             : struct CallSiteNode : public ListNode {
    1243           1 :     explicit CallSiteNode(uint32_t begin): ListNode(PNK_CALLSITEOBJ, TokenPos(begin, begin + 1)) {}
    1244             : 
    1245           1 :     static bool test(const ParseNode& node) {
    1246           1 :         return node.isKind(PNK_CALLSITEOBJ);
    1247             :     }
    1248             : 
    1249           1 :     MOZ_MUST_USE bool getRawArrayValue(JSContext* cx, MutableHandleValue vp) {
    1250           1 :         return pn_head->getConstantValue(cx, AllowObjects, vp);
    1251             :     }
    1252             : };
    1253             : 
    1254             : struct ClassMethod : public BinaryNode {
    1255             :     /*
    1256             :      * Method defintions often keep a name and function body that overlap,
    1257             :      * so explicitly define the beginning and end here.
    1258             :      */
    1259         156 :     ClassMethod(ParseNode* name, ParseNode* body, JSOp op, bool isStatic)
    1260         156 :       : BinaryNode(PNK_CLASSMETHOD, op, TokenPos(name->pn_pos.begin, body->pn_pos.end), name, body)
    1261             :     {
    1262         156 :         pn_u.binary.isStatic = isStatic;
    1263         156 :     }
    1264             : 
    1265         218 :     static bool test(const ParseNode& node) {
    1266         218 :         bool match = node.isKind(PNK_CLASSMETHOD);
    1267         218 :         MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
    1268         218 :         return match;
    1269             :     }
    1270             : 
    1271          31 :     ParseNode& name() const {
    1272          31 :         return *pn_u.binary.left;
    1273             :     }
    1274          31 :     ParseNode& method() const {
    1275          31 :         return *pn_u.binary.right;
    1276             :     }
    1277         218 :     bool isStatic() const {
    1278         218 :         return pn_u.binary.isStatic;
    1279             :     }
    1280             : };
    1281             : 
    1282             : struct ClassNames : public BinaryNode {
    1283          26 :     ClassNames(ParseNode* outerBinding, ParseNode* innerBinding, const TokenPos& pos)
    1284          26 :       : BinaryNode(PNK_CLASSNAMES, JSOP_NOP, pos, outerBinding, innerBinding)
    1285             :     {
    1286          26 :         MOZ_ASSERT_IF(outerBinding, outerBinding->isKind(PNK_NAME));
    1287          26 :         MOZ_ASSERT(innerBinding->isKind(PNK_NAME));
    1288          26 :         MOZ_ASSERT_IF(outerBinding, innerBinding->pn_atom == outerBinding->pn_atom);
    1289          26 :     }
    1290             : 
    1291          52 :     static bool test(const ParseNode& node) {
    1292          52 :         bool match = node.isKind(PNK_CLASSNAMES);
    1293          52 :         MOZ_ASSERT_IF(match, node.isArity(PN_BINARY));
    1294          52 :         return match;
    1295             :     }
    1296             : 
    1297             :     /*
    1298             :      * Classes require two definitions: The first "outer" binding binds the
    1299             :      * class into the scope in which it was declared. the outer binding is a
    1300             :      * mutable lexial binding. The second "inner" binding binds the class by
    1301             :      * name inside a block in which the methods are evaulated. It is immutable,
    1302             :      * giving the methods access to the static members of the class even if
    1303             :      * the outer binding has been overwritten.
    1304             :      */
    1305          26 :     ParseNode* outerBinding() const {
    1306          26 :         return pn_u.binary.left;
    1307             :     }
    1308          27 :     ParseNode* innerBinding() const {
    1309          27 :         return pn_u.binary.right;
    1310             :     }
    1311             : };
    1312             : 
    1313             : struct ClassNode : public TernaryNode {
    1314          32 :     ClassNode(ParseNode* names, ParseNode* heritage, ParseNode* methodsOrBlock,
    1315             :               const TokenPos& pos)
    1316          32 :       : TernaryNode(PNK_CLASS, JSOP_NOP, names, heritage, methodsOrBlock, pos)
    1317             :     {
    1318          32 :         MOZ_ASSERT_IF(names, names->is<ClassNames>());
    1319          32 :         MOZ_ASSERT(methodsOrBlock->is<LexicalScopeNode>() ||
    1320             :                    methodsOrBlock->isKind(PNK_CLASSMETHODLIST));
    1321          32 :     }
    1322             : 
    1323       22448 :     static bool test(const ParseNode& node) {
    1324       22448 :         bool match = node.isKind(PNK_CLASS);
    1325       22448 :         MOZ_ASSERT_IF(match, node.isArity(PN_TERNARY));
    1326       22448 :         return match;
    1327             :     }
    1328             : 
    1329          38 :     ClassNames* names() const {
    1330          38 :         return pn_kid1 ? &pn_kid1->as<ClassNames>() : nullptr;
    1331             :     }
    1332          32 :     ParseNode* heritage() const {
    1333          32 :         return pn_kid2;
    1334             :     }
    1335          32 :     ParseNode* methodList() const {
    1336          32 :         if (pn_kid3->isKind(PNK_CLASSMETHODLIST))
    1337           6 :             return pn_kid3;
    1338             : 
    1339          26 :         MOZ_ASSERT(pn_kid3->is<LexicalScopeNode>());
    1340          26 :         ParseNode* list = pn_kid3->scopeBody();
    1341          26 :         MOZ_ASSERT(list->isKind(PNK_CLASSMETHODLIST));
    1342          26 :         return list;
    1343             :     }
    1344          26 :     Handle<LexicalScope::Data*> scopeBindings() const {
    1345          26 :         MOZ_ASSERT(pn_kid3->is<LexicalScopeNode>());
    1346          26 :         return pn_kid3->scopeBindings();
    1347             :     }
    1348             : };
    1349             : 
    1350             : #ifdef DEBUG
    1351             : void DumpParseTree(ParseNode* pn, int indent = 0);
    1352             : #endif
    1353             : 
    1354             : class ParseNodeAllocator
    1355             : {
    1356             :   public:
    1357        1690 :     explicit ParseNodeAllocator(JSContext* cx, LifoAlloc& alloc)
    1358        1690 :       : cx(cx), alloc(alloc), freelist(nullptr)
    1359        1690 :     {}
    1360             : 
    1361             :     void* allocNode();
    1362             :     void freeNode(ParseNode* pn);
    1363             :     ParseNode* freeTree(ParseNode* pn);
    1364             :     void prepareNodeForMutation(ParseNode* pn);
    1365             : 
    1366             :   private:
    1367             :     JSContext* cx;
    1368             :     LifoAlloc& alloc;
    1369             :     ParseNode* freelist;
    1370             : };
    1371             : 
    1372             : inline bool
    1373        9258 : ParseNode::isConstant()
    1374             : {
    1375        9258 :     switch (pn_type) {
    1376             :       case PNK_NUMBER:
    1377             :       case PNK_STRING:
    1378             :       case PNK_TEMPLATE_STRING:
    1379             :       case PNK_NULL:
    1380             :       case PNK_RAW_UNDEFINED:
    1381             :       case PNK_FALSE:
    1382             :       case PNK_TRUE:
    1383        5251 :         return true;
    1384             :       case PNK_ARRAY:
    1385             :       case PNK_OBJECT:
    1386        1357 :         MOZ_ASSERT(isOp(JSOP_NEWINIT));
    1387        1357 :         return !(pn_xflags & PNX_NONCONST);
    1388             :       default:
    1389        2650 :         return false;
    1390             :     }
    1391             : }
    1392             : 
    1393             : class ObjectBox
    1394             : {
    1395             :   public:
    1396             :     JSObject* object;
    1397             : 
    1398             :     ObjectBox(JSObject* object, ObjectBox* traceLink);
    1399        7633 :     bool isFunctionBox() { return object->is<JSFunction>(); }
    1400             :     FunctionBox* asFunctionBox();
    1401             :     virtual void trace(JSTracer* trc);
    1402             : 
    1403             :     static void TraceList(JSTracer* trc, ObjectBox* listHead);
    1404             : 
    1405             :   protected:
    1406             :     friend struct CGObjectList;
    1407             : 
    1408             :     ObjectBox* traceLink;
    1409             :     ObjectBox* emitLink;
    1410             : 
    1411             :     ObjectBox(JSFunction* function, ObjectBox* traceLink);
    1412             : };
    1413             : 
    1414             : enum ParseReportKind
    1415             : {
    1416             :     ParseError,
    1417             :     ParseWarning,
    1418             :     ParseExtraWarning,
    1419             :     ParseStrictError
    1420             : };
    1421             : 
    1422             : enum FunctionSyntaxKind
    1423             : {
    1424             :     Expression,
    1425             :     Statement,
    1426             :     Arrow,
    1427             :     Method,
    1428             :     ClassConstructor,
    1429             :     DerivedClassConstructor,
    1430             :     Getter,
    1431             :     GetterNoExpressionClosure,
    1432             :     Setter,
    1433             :     SetterNoExpressionClosure
    1434             : };
    1435             : 
    1436             : static inline bool
    1437        4913 : IsConstructorKind(FunctionSyntaxKind kind)
    1438             : {
    1439        4913 :     return kind == ClassConstructor || kind == DerivedClassConstructor;
    1440             : }
    1441             : 
    1442             : static inline bool
    1443        9765 : IsGetterKind(FunctionSyntaxKind kind)
    1444             : {
    1445        9765 :     return kind == Getter || kind == GetterNoExpressionClosure;
    1446             : }
    1447             : 
    1448             : static inline bool
    1449       15103 : IsSetterKind(FunctionSyntaxKind kind)
    1450             : {
    1451       15103 :     return kind == Setter || kind == SetterNoExpressionClosure;
    1452             : }
    1453             : 
    1454             : static inline bool
    1455        7373 : IsMethodDefinitionKind(FunctionSyntaxKind kind)
    1456             : {
    1457        9787 :     return kind == Method || IsConstructorKind(kind) ||
    1458       16767 :            IsGetterKind(kind) || IsSetterKind(kind);
    1459             : }
    1460             : 
    1461             : static inline ParseNode*
    1462           0 : FunctionFormalParametersList(ParseNode* fn, unsigned* numFormals)
    1463             : {
    1464           0 :     MOZ_ASSERT(fn->isKind(PNK_FUNCTION));
    1465           0 :     ParseNode* argsBody = fn->pn_body;
    1466           0 :     MOZ_ASSERT(argsBody->isKind(PNK_PARAMSBODY));
    1467           0 :     *numFormals = argsBody->pn_count;
    1468           0 :     if (*numFormals > 0 &&
    1469           0 :         argsBody->last()->isKind(PNK_LEXICALSCOPE) &&
    1470           0 :         argsBody->last()->scopeBody()->isKind(PNK_STATEMENTLIST))
    1471             :     {
    1472           0 :         (*numFormals)--;
    1473             :     }
    1474           0 :     MOZ_ASSERT(argsBody->isArity(PN_LIST));
    1475           0 :     return argsBody->pn_head;
    1476             : }
    1477             : 
    1478             : bool
    1479             : IsAnonymousFunctionDefinition(ParseNode* pn);
    1480             : 
    1481             : } /* namespace frontend */
    1482             : } /* namespace js */
    1483             : 
    1484             : #endif /* frontend_ParseNode_h */

Generated by: LCOV version 1.13