js/src/frontend/FullParseHandler.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/frontend/FullParseHandler.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,709 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef frontend_FullParseHandler_h
    1.11 +#define frontend_FullParseHandler_h
    1.12 +
    1.13 +#include "mozilla/PodOperations.h"
    1.14 +
    1.15 +#include "frontend/ParseNode.h"
    1.16 +#include "frontend/SharedContext.h"
    1.17 +
    1.18 +namespace js {
    1.19 +namespace frontend {
    1.20 +
    1.21 +template <typename ParseHandler>
    1.22 +class Parser;
    1.23 +
    1.24 +class SyntaxParseHandler;
    1.25 +
    1.26 +// Parse handler used when generating a full parse tree for all code which the
    1.27 +// parser encounters.
    1.28 +class FullParseHandler
    1.29 +{
    1.30 +    ParseNodeAllocator allocator;
    1.31 +    TokenStream &tokenStream;
    1.32 +    bool foldConstants;
    1.33 +
    1.34 +    ParseNode *allocParseNode(size_t size) {
    1.35 +        JS_ASSERT(size == sizeof(ParseNode));
    1.36 +        return static_cast<ParseNode *>(allocator.allocNode());
    1.37 +    }
    1.38 +
    1.39 +    ParseNode *cloneNode(const ParseNode &other) {
    1.40 +        ParseNode *node = allocParseNode(sizeof(ParseNode));
    1.41 +        if (!node)
    1.42 +            return nullptr;
    1.43 +        mozilla::PodAssign(node, &other);
    1.44 +        return node;
    1.45 +    }
    1.46 +
    1.47 +    /*
    1.48 +     * If this is a full parse to construct the bytecode for a function that
    1.49 +     * was previously lazily parsed, that lazy function and the current index
    1.50 +     * into its inner functions. We do not want to reparse the inner functions.
    1.51 +     */
    1.52 +    LazyScript * const lazyOuterFunction_;
    1.53 +    size_t lazyInnerFunctionIndex;
    1.54 +
    1.55 +    const TokenPos &pos() {
    1.56 +        return tokenStream.currentToken().pos;
    1.57 +    }
    1.58 +
    1.59 +  public:
    1.60 +
    1.61 +    /*
    1.62 +     * If non-nullptr, points to a syntax parser which can be used for inner
    1.63 +     * functions. Cleared if language features not handled by the syntax parser
    1.64 +     * are encountered, in which case all future activity will use the full
    1.65 +     * parser.
    1.66 +     */
    1.67 +    Parser<SyntaxParseHandler> *syntaxParser;
    1.68 +
    1.69 +    /* new_ methods for creating parse nodes. These report OOM on context. */
    1.70 +    JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
    1.71 +
    1.72 +    typedef ParseNode *Node;
    1.73 +    typedef Definition *DefinitionNode;
    1.74 +
    1.75 +    FullParseHandler(ExclusiveContext *cx, LifoAlloc &alloc,
    1.76 +                     TokenStream &tokenStream, bool foldConstants,
    1.77 +                     Parser<SyntaxParseHandler> *syntaxParser, LazyScript *lazyOuterFunction)
    1.78 +      : allocator(cx, alloc),
    1.79 +        tokenStream(tokenStream),
    1.80 +        foldConstants(foldConstants),
    1.81 +        lazyOuterFunction_(lazyOuterFunction),
    1.82 +        lazyInnerFunctionIndex(0),
    1.83 +        syntaxParser(syntaxParser)
    1.84 +    {}
    1.85 +
    1.86 +    static ParseNode *null() { return nullptr; }
    1.87 +
    1.88 +    ParseNode *freeTree(ParseNode *pn) { return allocator.freeTree(pn); }
    1.89 +    void prepareNodeForMutation(ParseNode *pn) { return allocator.prepareNodeForMutation(pn); }
    1.90 +    const Token &currentToken() { return tokenStream.currentToken(); }
    1.91 +
    1.92 +    ParseNode *newName(PropertyName *name, uint32_t blockid, const TokenPos &pos) {
    1.93 +        return new_<NameNode>(PNK_NAME, JSOP_NAME, name, blockid, pos);
    1.94 +    }
    1.95 +
    1.96 +    Definition *newPlaceholder(JSAtom *atom, uint32_t blockid, const TokenPos &pos) {
    1.97 +        Definition *dn =
    1.98 +            (Definition *) new_<NameNode>(PNK_NAME, JSOP_NOP, atom, blockid, pos);
    1.99 +        if (!dn)
   1.100 +            return nullptr;
   1.101 +        dn->setDefn(true);
   1.102 +        dn->pn_dflags |= PND_PLACEHOLDER;
   1.103 +        return dn;
   1.104 +    }
   1.105 +
   1.106 +    ParseNode *newIdentifier(JSAtom *atom, const TokenPos &pos) {
   1.107 +        return new_<NullaryNode>(PNK_NAME, JSOP_NOP, pos, atom);
   1.108 +    }
   1.109 +
   1.110 +    ParseNode *newNumber(double value, DecimalPoint decimalPoint, const TokenPos &pos) {
   1.111 +        ParseNode *pn = new_<NullaryNode>(PNK_NUMBER, pos);
   1.112 +        if (!pn)
   1.113 +            return nullptr;
   1.114 +        pn->initNumber(value, decimalPoint);
   1.115 +        return pn;
   1.116 +    }
   1.117 +
   1.118 +    ParseNode *newBooleanLiteral(bool cond, const TokenPos &pos) {
   1.119 +        return new_<BooleanLiteral>(cond, pos);
   1.120 +    }
   1.121 +
   1.122 +    ParseNode *newStringLiteral(JSAtom *atom, const TokenPos &pos) {
   1.123 +        return new_<NullaryNode>(PNK_STRING, JSOP_STRING, pos, atom);
   1.124 +    }
   1.125 +
   1.126 +    ParseNode *newThisLiteral(const TokenPos &pos) {
   1.127 +        return new_<ThisLiteral>(pos);
   1.128 +    }
   1.129 +
   1.130 +    ParseNode *newNullLiteral(const TokenPos &pos) {
   1.131 +        return new_<NullLiteral>(pos);
   1.132 +    }
   1.133 +
   1.134 +    // The Boxer object here is any object that can allocate ObjectBoxes.
   1.135 +    // Specifically, a Boxer has a .newObjectBox(T) method that accepts a
   1.136 +    // Rooted<RegExpObject*> argument and returns an ObjectBox*.
   1.137 +    template <class Boxer>
   1.138 +    ParseNode *newRegExp(HandleObject reobj, const TokenPos &pos, Boxer &boxer) {
   1.139 +        ObjectBox *objbox = boxer.newObjectBox(reobj);
   1.140 +        if (!objbox)
   1.141 +            return null();
   1.142 +        return new_<RegExpLiteral>(objbox, pos);
   1.143 +    }
   1.144 +
   1.145 +    ParseNode *newConditional(ParseNode *cond, ParseNode *thenExpr, ParseNode *elseExpr) {
   1.146 +        return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
   1.147 +    }
   1.148 +
   1.149 +    void markAsSetCall(ParseNode *pn) {
   1.150 +        pn->pn_xflags |= PNX_SETCALL;
   1.151 +    }
   1.152 +
   1.153 +    ParseNode *newDelete(uint32_t begin, ParseNode *expr) {
   1.154 +        if (expr->getKind() == PNK_NAME) {
   1.155 +            expr->pn_dflags |= PND_DEOPTIMIZED;
   1.156 +            expr->setOp(JSOP_DELNAME);
   1.157 +        }
   1.158 +        return newUnary(PNK_DELETE, JSOP_NOP, begin, expr);
   1.159 +    }
   1.160 +
   1.161 +    ParseNode *newNullary(ParseNodeKind kind, JSOp op, const TokenPos &pos) {
   1.162 +        return new_<NullaryNode>(kind, op, pos);
   1.163 +    }
   1.164 +
   1.165 +    ParseNode *newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, ParseNode *kid) {
   1.166 +        TokenPos pos(begin, kid ? kid->pn_pos.end : begin + 1);
   1.167 +        return new_<UnaryNode>(kind, op, pos, kid);
   1.168 +    }
   1.169 +
   1.170 +    ParseNode *newBinary(ParseNodeKind kind, JSOp op = JSOP_NOP) {
   1.171 +        return new_<BinaryNode>(kind, op, pos(), (ParseNode *) nullptr, (ParseNode *) nullptr);
   1.172 +    }
   1.173 +    ParseNode *newBinary(ParseNodeKind kind, ParseNode *left,
   1.174 +                         JSOp op = JSOP_NOP) {
   1.175 +        return new_<BinaryNode>(kind, op, left->pn_pos, left, (ParseNode *) nullptr);
   1.176 +    }
   1.177 +    ParseNode *newBinary(ParseNodeKind kind, ParseNode *left, ParseNode *right,
   1.178 +                         JSOp op = JSOP_NOP) {
   1.179 +        TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
   1.180 +        return new_<BinaryNode>(kind, op, pos, left, right);
   1.181 +    }
   1.182 +    ParseNode *newBinaryOrAppend(ParseNodeKind kind, ParseNode *left, ParseNode *right,
   1.183 +                                 ParseContext<FullParseHandler> *pc, JSOp op = JSOP_NOP)
   1.184 +    {
   1.185 +        return ParseNode::newBinaryOrAppend(kind, op, left, right, this, pc, foldConstants);
   1.186 +    }
   1.187 +
   1.188 +    ParseNode *newTernary(ParseNodeKind kind,
   1.189 +                          ParseNode *first, ParseNode *second, ParseNode *third,
   1.190 +                          JSOp op = JSOP_NOP)
   1.191 +    {
   1.192 +        return new_<TernaryNode>(kind, op, first, second, third);
   1.193 +    }
   1.194 +
   1.195 +    // Expressions
   1.196 +
   1.197 +    ParseNode *newArrayComprehension(ParseNode *body, unsigned blockid, const TokenPos &pos) {
   1.198 +        JS_ASSERT(pos.begin <= body->pn_pos.begin);
   1.199 +        JS_ASSERT(body->pn_pos.end <= pos.end);
   1.200 +        ParseNode *pn = new_<ListNode>(PNK_ARRAYCOMP, pos);
   1.201 +        if (!pn)
   1.202 +            return nullptr;
   1.203 +        pn->pn_blockid = blockid;
   1.204 +        pn->append(body);
   1.205 +        return pn;
   1.206 +    }
   1.207 +
   1.208 +    ParseNode *newArrayLiteral(uint32_t begin, unsigned blockid) {
   1.209 +        ParseNode *literal = new_<ListNode>(PNK_ARRAY, TokenPos(begin, begin + 1));
   1.210 +        // Later in this stack: remove dependency on this opcode.
   1.211 +        if (literal) {
   1.212 +            literal->setOp(JSOP_NEWINIT);
   1.213 +            literal->pn_blockid = blockid;
   1.214 +        }
   1.215 +        return literal;
   1.216 +    }
   1.217 +
   1.218 +    bool addElision(ParseNode *literal, const TokenPos &pos) {
   1.219 +        ParseNode *elision = new_<NullaryNode>(PNK_ELISION, pos);
   1.220 +        if (!elision)
   1.221 +            return false;
   1.222 +        literal->append(elision);
   1.223 +        literal->pn_xflags |= PNX_SPECIALARRAYINIT | PNX_NONCONST;
   1.224 +        return true;
   1.225 +    }
   1.226 +
   1.227 +    bool addSpreadElement(ParseNode *literal, uint32_t begin, ParseNode *inner) {
   1.228 +        TokenPos pos(begin, inner->pn_pos.end);
   1.229 +        ParseNode *spread = new_<UnaryNode>(PNK_SPREAD, JSOP_NOP, pos, inner);
   1.230 +        if (!spread)
   1.231 +            return null();
   1.232 +        literal->append(spread);
   1.233 +        literal->pn_xflags |= PNX_SPECIALARRAYINIT | PNX_NONCONST;
   1.234 +        return true;
   1.235 +    }
   1.236 +
   1.237 +    bool addArrayElement(ParseNode *literal, ParseNode *element) {
   1.238 +        if (!element->isConstant())
   1.239 +            literal->pn_xflags |= PNX_NONCONST;
   1.240 +        literal->append(element);
   1.241 +        return true;
   1.242 +    }
   1.243 +
   1.244 +    ParseNode *newObjectLiteral(uint32_t begin) {
   1.245 +        ParseNode *literal = new_<ListNode>(PNK_OBJECT, TokenPos(begin, begin + 1));
   1.246 +        // Later in this stack: remove dependency on this opcode.
   1.247 +        if (literal)
   1.248 +            literal->setOp(JSOP_NEWINIT);
   1.249 +        return literal;
   1.250 +    }
   1.251 +
   1.252 +    bool addPropertyDefinition(ParseNode *literal, ParseNode *name, ParseNode *expr) {
   1.253 +        ParseNode *propdef = newBinary(PNK_COLON, name, expr, JSOP_INITPROP);
   1.254 +        if (!propdef)
   1.255 +            return false;
   1.256 +        literal->append(propdef);
   1.257 +        return true;
   1.258 +    }
   1.259 +
   1.260 +    bool addShorthandPropertyDefinition(ParseNode *literal, ParseNode *name) {
   1.261 +        JS_ASSERT(literal->isArity(PN_LIST));
   1.262 +        literal->pn_xflags |= PNX_DESTRUCT | PNX_NONCONST;  // XXX why PNX_DESTRUCT?
   1.263 +        return addPropertyDefinition(literal, name, name);
   1.264 +    }
   1.265 +
   1.266 +    bool addAccessorPropertyDefinition(ParseNode *literal, ParseNode *name, ParseNode *fn, JSOp op)
   1.267 +    {
   1.268 +        JS_ASSERT(literal->isArity(PN_LIST));
   1.269 +        literal->pn_xflags |= PNX_NONCONST;
   1.270 +
   1.271 +        ParseNode *propdef = newBinary(PNK_COLON, name, fn, op);
   1.272 +        if (!propdef)
   1.273 +            return false;
   1.274 +        literal->append(propdef);
   1.275 +        return true;
   1.276 +    }
   1.277 +
   1.278 +    // Statements
   1.279 +
   1.280 +    ParseNode *newStatementList(unsigned blockid, const TokenPos &pos) {
   1.281 +        ParseNode *pn = new_<ListNode>(PNK_STATEMENTLIST, pos);
   1.282 +        if (pn)
   1.283 +            pn->pn_blockid = blockid;
   1.284 +        return pn;
   1.285 +    }
   1.286 +
   1.287 +    template <typename PC>
   1.288 +    void addStatementToList(ParseNode *list, ParseNode *stmt, PC *pc) {
   1.289 +        JS_ASSERT(list->isKind(PNK_STATEMENTLIST));
   1.290 +
   1.291 +        if (stmt->isKind(PNK_FUNCTION)) {
   1.292 +            if (pc->atBodyLevel()) {
   1.293 +                // PNX_FUNCDEFS notifies the emitter that the block contains
   1.294 +                // body-level function definitions that should be processed
   1.295 +                // before the rest of nodes.
   1.296 +                list->pn_xflags |= PNX_FUNCDEFS;
   1.297 +            } else {
   1.298 +                // General deoptimization was done in Parser::functionDef.
   1.299 +                JS_ASSERT_IF(pc->sc->isFunctionBox(),
   1.300 +                             pc->sc->asFunctionBox()->hasExtensibleScope());
   1.301 +            }
   1.302 +        }
   1.303 +
   1.304 +        list->append(stmt);
   1.305 +    }
   1.306 +
   1.307 +    ParseNode *newEmptyStatement(const TokenPos &pos) {
   1.308 +        return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
   1.309 +    }
   1.310 +
   1.311 +    ParseNode *newImportDeclaration(ParseNode *importSpecSet,
   1.312 +                                    ParseNode *moduleSpec, const TokenPos &pos)
   1.313 +    {
   1.314 +        ParseNode *pn = new_<BinaryNode>(PNK_IMPORT, JSOP_NOP, pos,
   1.315 +                                         importSpecSet, moduleSpec);
   1.316 +        if (!pn)
   1.317 +            return null();
   1.318 +        return pn;
   1.319 +    }
   1.320 +
   1.321 +    ParseNode *newExportDeclaration(ParseNode *kid, const TokenPos &pos) {
   1.322 +        return new_<UnaryNode>(PNK_EXPORT, JSOP_NOP, pos, kid);
   1.323 +    }
   1.324 +
   1.325 +    ParseNode *newExportFromDeclaration(uint32_t begin, ParseNode *exportSpecSet,
   1.326 +                                        ParseNode *moduleSpec)
   1.327 +    {
   1.328 +        ParseNode *pn = new_<BinaryNode>(PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet, moduleSpec);
   1.329 +        if (!pn)
   1.330 +            return null();
   1.331 +        pn->pn_pos.begin = begin;
   1.332 +        return pn;
   1.333 +    }
   1.334 +
   1.335 +    ParseNode *newExprStatement(ParseNode *expr, uint32_t end) {
   1.336 +        JS_ASSERT(expr->pn_pos.end <= end);
   1.337 +        return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr);
   1.338 +    }
   1.339 +
   1.340 +    ParseNode *newIfStatement(uint32_t begin, ParseNode *cond, ParseNode *thenBranch,
   1.341 +                              ParseNode *elseBranch)
   1.342 +    {
   1.343 +        ParseNode *pn = new_<TernaryNode>(PNK_IF, JSOP_NOP, cond, thenBranch, elseBranch);
   1.344 +        if (!pn)
   1.345 +            return null();
   1.346 +        pn->pn_pos.begin = begin;
   1.347 +        return pn;
   1.348 +    }
   1.349 +
   1.350 +    ParseNode *newDoWhileStatement(ParseNode *body, ParseNode *cond, const TokenPos &pos) {
   1.351 +        return new_<BinaryNode>(PNK_DOWHILE, JSOP_NOP, pos, body, cond);
   1.352 +    }
   1.353 +
   1.354 +    ParseNode *newWhileStatement(uint32_t begin, ParseNode *cond, ParseNode *body) {
   1.355 +        TokenPos pos(begin, body->pn_pos.end);
   1.356 +        return new_<BinaryNode>(PNK_WHILE, JSOP_NOP, pos, cond, body);
   1.357 +    }
   1.358 +
   1.359 +    ParseNode *newForStatement(uint32_t begin, ParseNode *forHead, ParseNode *body,
   1.360 +                               unsigned iflags)
   1.361 +    {
   1.362 +        /* A FOR node is binary, left is loop control and right is the body. */
   1.363 +        JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP;
   1.364 +        BinaryNode *pn = new_<BinaryNode>(PNK_FOR, op, TokenPos(begin, body->pn_pos.end),
   1.365 +                                          forHead, body);
   1.366 +        if (!pn)
   1.367 +            return null();
   1.368 +        pn->pn_iflags = iflags;
   1.369 +        return pn;
   1.370 +    }
   1.371 +
   1.372 +    ParseNode *newForHead(ParseNodeKind kind, ParseNode *pn1, ParseNode *pn2, ParseNode *pn3,
   1.373 +                          const TokenPos &pos)
   1.374 +    {
   1.375 +        JS_ASSERT(kind == PNK_FORIN || kind == PNK_FOROF || kind == PNK_FORHEAD);
   1.376 +        return new_<TernaryNode>(kind, JSOP_NOP, pn1, pn2, pn3, pos);
   1.377 +    }
   1.378 +
   1.379 +    ParseNode *newSwitchStatement(uint32_t begin, ParseNode *discriminant, ParseNode *caseList) {
   1.380 +        TokenPos pos(begin, caseList->pn_pos.end);
   1.381 +        return new_<BinaryNode>(PNK_SWITCH, JSOP_NOP, pos, discriminant, caseList);
   1.382 +    }
   1.383 +
   1.384 +    ParseNode *newCaseOrDefault(uint32_t begin, ParseNode *expr, ParseNode *body) {
   1.385 +        TokenPos pos(begin, body->pn_pos.end);
   1.386 +        return new_<BinaryNode>(expr ? PNK_CASE : PNK_DEFAULT, JSOP_NOP, pos, expr, body);
   1.387 +    }
   1.388 +
   1.389 +    ParseNode *newContinueStatement(PropertyName *label, const TokenPos &pos) {
   1.390 +        return new_<ContinueStatement>(label, pos);
   1.391 +    }
   1.392 +
   1.393 +    ParseNode *newBreakStatement(PropertyName *label, const TokenPos &pos) {
   1.394 +        return new_<BreakStatement>(label, pos);
   1.395 +    }
   1.396 +
   1.397 +    ParseNode *newReturnStatement(ParseNode *expr, const TokenPos &pos) {
   1.398 +        JS_ASSERT_IF(expr, pos.encloses(expr->pn_pos));
   1.399 +        return new_<UnaryNode>(PNK_RETURN, JSOP_RETURN, pos, expr);
   1.400 +    }
   1.401 +
   1.402 +    ParseNode *newWithStatement(uint32_t begin, ParseNode *expr, ParseNode *body,
   1.403 +                                ObjectBox *staticWith) {
   1.404 +        return new_<BinaryObjNode>(PNK_WITH, JSOP_NOP, TokenPos(begin, body->pn_pos.end),
   1.405 +                                   expr, body, staticWith);
   1.406 +    }
   1.407 +
   1.408 +    ParseNode *newLabeledStatement(PropertyName *label, ParseNode *stmt, uint32_t begin) {
   1.409 +        return new_<LabeledStatement>(label, stmt, begin);
   1.410 +    }
   1.411 +
   1.412 +    ParseNode *newThrowStatement(ParseNode *expr, const TokenPos &pos) {
   1.413 +        JS_ASSERT(pos.encloses(expr->pn_pos));
   1.414 +        return new_<UnaryNode>(PNK_THROW, JSOP_THROW, pos, expr);
   1.415 +    }
   1.416 +
   1.417 +    ParseNode *newTryStatement(uint32_t begin, ParseNode *body, ParseNode *catchList,
   1.418 +                               ParseNode *finallyBlock) {
   1.419 +        TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end);
   1.420 +        return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos);
   1.421 +    }
   1.422 +
   1.423 +    ParseNode *newDebuggerStatement(const TokenPos &pos) {
   1.424 +        return new_<DebuggerStatement>(pos);
   1.425 +    }
   1.426 +
   1.427 +    ParseNode *newPropertyAccess(ParseNode *pn, PropertyName *name, uint32_t end) {
   1.428 +        return new_<PropertyAccess>(pn, name, pn->pn_pos.begin, end);
   1.429 +    }
   1.430 +
   1.431 +    ParseNode *newPropertyByValue(ParseNode *lhs, ParseNode *index, uint32_t end) {
   1.432 +        return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
   1.433 +    }
   1.434 +
   1.435 +    inline bool addCatchBlock(ParseNode *catchList, ParseNode *letBlock,
   1.436 +                              ParseNode *catchName, ParseNode *catchGuard, ParseNode *catchBody);
   1.437 +
   1.438 +    inline void setLastFunctionArgumentDefault(ParseNode *funcpn, ParseNode *pn);
   1.439 +    inline ParseNode *newFunctionDefinition();
   1.440 +    void setFunctionBody(ParseNode *pn, ParseNode *kid) {
   1.441 +        pn->pn_body = kid;
   1.442 +    }
   1.443 +    void setFunctionBox(ParseNode *pn, FunctionBox *funbox) {
   1.444 +        JS_ASSERT(pn->isKind(PNK_FUNCTION));
   1.445 +        pn->pn_funbox = funbox;
   1.446 +    }
   1.447 +    void addFunctionArgument(ParseNode *pn, ParseNode *argpn) {
   1.448 +        pn->pn_body->append(argpn);
   1.449 +    }
   1.450 +
   1.451 +    inline ParseNode *newLexicalScope(ObjectBox *blockbox);
   1.452 +    inline void setLexicalScopeBody(ParseNode *block, ParseNode *body);
   1.453 +
   1.454 +    bool isOperationWithoutParens(ParseNode *pn, ParseNodeKind kind) {
   1.455 +        return pn->isKind(kind) && !pn->isInParens();
   1.456 +    }
   1.457 +
   1.458 +    inline bool finishInitializerAssignment(ParseNode *pn, ParseNode *init, JSOp op);
   1.459 +
   1.460 +    void setBeginPosition(ParseNode *pn, ParseNode *oth) {
   1.461 +        setBeginPosition(pn, oth->pn_pos.begin);
   1.462 +    }
   1.463 +    void setBeginPosition(ParseNode *pn, uint32_t begin) {
   1.464 +        pn->pn_pos.begin = begin;
   1.465 +        JS_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
   1.466 +    }
   1.467 +
   1.468 +    void setEndPosition(ParseNode *pn, ParseNode *oth) {
   1.469 +        setEndPosition(pn, oth->pn_pos.end);
   1.470 +    }
   1.471 +    void setEndPosition(ParseNode *pn, uint32_t end) {
   1.472 +        pn->pn_pos.end = end;
   1.473 +        JS_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
   1.474 +    }
   1.475 +
   1.476 +    void setPosition(ParseNode *pn, const TokenPos &pos) {
   1.477 +        pn->pn_pos = pos;
   1.478 +    }
   1.479 +    TokenPos getPosition(ParseNode *pn) {
   1.480 +        return pn->pn_pos;
   1.481 +    }
   1.482 +
   1.483 +    ParseNode *newList(ParseNodeKind kind, ParseNode *kid = nullptr, JSOp op = JSOP_NOP) {
   1.484 +        ParseNode *pn = ListNode::create(kind, this);
   1.485 +        if (!pn)
   1.486 +            return nullptr;
   1.487 +        pn->setOp(op);
   1.488 +        pn->makeEmpty();
   1.489 +        if (kid) {
   1.490 +            pn->pn_pos.begin = kid->pn_pos.begin;
   1.491 +            pn->append(kid);
   1.492 +        }
   1.493 +        return pn;
   1.494 +    }
   1.495 +    void addList(ParseNode *pn, ParseNode *kid) {
   1.496 +        pn->append(kid);
   1.497 +    }
   1.498 +
   1.499 +    bool isUnparenthesizedYield(ParseNode *pn) {
   1.500 +        return pn->isKind(PNK_YIELD) && !pn->isInParens();
   1.501 +    }
   1.502 +
   1.503 +    void setOp(ParseNode *pn, JSOp op) {
   1.504 +        pn->setOp(op);
   1.505 +    }
   1.506 +    void setBlockId(ParseNode *pn, unsigned blockid) {
   1.507 +        pn->pn_blockid = blockid;
   1.508 +    }
   1.509 +    void setFlag(ParseNode *pn, unsigned flag) {
   1.510 +        pn->pn_dflags |= flag;
   1.511 +    }
   1.512 +    void setListFlag(ParseNode *pn, unsigned flag) {
   1.513 +        JS_ASSERT(pn->isArity(PN_LIST));
   1.514 +        pn->pn_xflags |= flag;
   1.515 +    }
   1.516 +    ParseNode *setInParens(ParseNode *pn) {
   1.517 +        pn->setInParens(true);
   1.518 +        return pn;
   1.519 +    }
   1.520 +    void setPrologue(ParseNode *pn) {
   1.521 +        pn->pn_prologue = true;
   1.522 +    }
   1.523 +
   1.524 +    bool isConstant(ParseNode *pn) {
   1.525 +        return pn->isConstant();
   1.526 +    }
   1.527 +    PropertyName *isName(ParseNode *pn) {
   1.528 +        return pn->isKind(PNK_NAME) ? pn->pn_atom->asPropertyName() : nullptr;
   1.529 +    }
   1.530 +    bool isCall(ParseNode *pn) {
   1.531 +        return pn->isKind(PNK_CALL);
   1.532 +    }
   1.533 +    PropertyName *isGetProp(ParseNode *pn) {
   1.534 +        return pn->is<PropertyAccess>() ? &pn->as<PropertyAccess>().name() : nullptr;
   1.535 +    }
   1.536 +    JSAtom *isStringExprStatement(ParseNode *pn, TokenPos *pos) {
   1.537 +        if (JSAtom *atom = pn->isStringExprStatement()) {
   1.538 +            *pos = pn->pn_kid->pn_pos;
   1.539 +            return atom;
   1.540 +        }
   1.541 +        return nullptr;
   1.542 +    }
   1.543 +
   1.544 +    inline ParseNode *makeAssignment(ParseNode *pn, ParseNode *rhs);
   1.545 +
   1.546 +    static Definition *getDefinitionNode(Definition *dn) {
   1.547 +        return dn;
   1.548 +    }
   1.549 +    static Definition::Kind getDefinitionKind(Definition *dn) {
   1.550 +        return dn->kind();
   1.551 +    }
   1.552 +    void linkUseToDef(ParseNode *pn, Definition *dn)
   1.553 +    {
   1.554 +        JS_ASSERT(!pn->isUsed());
   1.555 +        JS_ASSERT(!pn->isDefn());
   1.556 +        JS_ASSERT(pn != dn->dn_uses);
   1.557 +        JS_ASSERT(dn->isDefn());
   1.558 +        pn->pn_link = dn->dn_uses;
   1.559 +        dn->dn_uses = pn;
   1.560 +        dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
   1.561 +        pn->setUsed(true);
   1.562 +        pn->pn_lexdef = dn;
   1.563 +    }
   1.564 +    Definition *resolve(Definition *dn) {
   1.565 +        return dn->resolve();
   1.566 +    }
   1.567 +    void deoptimizeUsesWithin(Definition *dn, const TokenPos &pos)
   1.568 +    {
   1.569 +        for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
   1.570 +            JS_ASSERT(pnu->isUsed());
   1.571 +            JS_ASSERT(!pnu->isDefn());
   1.572 +            if (pnu->pn_pos.begin >= pos.begin && pnu->pn_pos.end <= pos.end)
   1.573 +                pnu->pn_dflags |= PND_DEOPTIMIZED;
   1.574 +        }
   1.575 +    }
   1.576 +    bool dependencyCovered(ParseNode *pn, unsigned blockid, bool functionScope) {
   1.577 +        return pn->pn_blockid >= blockid;
   1.578 +    }
   1.579 +
   1.580 +    static uintptr_t definitionToBits(Definition *dn) {
   1.581 +        return uintptr_t(dn);
   1.582 +    }
   1.583 +    static Definition *definitionFromBits(uintptr_t bits) {
   1.584 +        return (Definition *) bits;
   1.585 +    }
   1.586 +    static Definition *nullDefinition() {
   1.587 +        return nullptr;
   1.588 +    }
   1.589 +    void disableSyntaxParser() {
   1.590 +        syntaxParser = nullptr;
   1.591 +    }
   1.592 +
   1.593 +    LazyScript *lazyOuterFunction() {
   1.594 +        return lazyOuterFunction_;
   1.595 +    }
   1.596 +    JSFunction *nextLazyInnerFunction() {
   1.597 +        JS_ASSERT(lazyInnerFunctionIndex < lazyOuterFunction()->numInnerFunctions());
   1.598 +        return lazyOuterFunction()->innerFunctions()[lazyInnerFunctionIndex++];
   1.599 +    }
   1.600 +};
   1.601 +
   1.602 +inline bool
   1.603 +FullParseHandler::addCatchBlock(ParseNode *catchList, ParseNode *letBlock,
   1.604 +                                ParseNode *catchName, ParseNode *catchGuard, ParseNode *catchBody)
   1.605 +{
   1.606 +    ParseNode *catchpn = newTernary(PNK_CATCH, catchName, catchGuard, catchBody);
   1.607 +    if (!catchpn)
   1.608 +        return false;
   1.609 +
   1.610 +    catchList->append(letBlock);
   1.611 +    letBlock->pn_expr = catchpn;
   1.612 +    return true;
   1.613 +}
   1.614 +
   1.615 +inline void
   1.616 +FullParseHandler::setLastFunctionArgumentDefault(ParseNode *funcpn, ParseNode *defaultValue)
   1.617 +{
   1.618 +    ParseNode *arg = funcpn->pn_body->last();
   1.619 +    arg->pn_dflags |= PND_DEFAULT;
   1.620 +    arg->pn_expr = defaultValue;
   1.621 +}
   1.622 +
   1.623 +inline ParseNode *
   1.624 +FullParseHandler::newFunctionDefinition()
   1.625 +{
   1.626 +    ParseNode *pn = CodeNode::create(PNK_FUNCTION, this);
   1.627 +    if (!pn)
   1.628 +        return nullptr;
   1.629 +    pn->pn_body = nullptr;
   1.630 +    pn->pn_funbox = nullptr;
   1.631 +    pn->pn_cookie.makeFree();
   1.632 +    pn->pn_dflags = 0;
   1.633 +    return pn;
   1.634 +}
   1.635 +
   1.636 +inline ParseNode *
   1.637 +FullParseHandler::newLexicalScope(ObjectBox *blockbox)
   1.638 +{
   1.639 +    ParseNode *pn = LexicalScopeNode::create(PNK_LEXICALSCOPE, this);
   1.640 +    if (!pn)
   1.641 +        return nullptr;
   1.642 +
   1.643 +    pn->pn_objbox = blockbox;
   1.644 +    pn->pn_cookie.makeFree();
   1.645 +    pn->pn_dflags = 0;
   1.646 +    return pn;
   1.647 +}
   1.648 +
   1.649 +inline void
   1.650 +FullParseHandler::setLexicalScopeBody(ParseNode *block, ParseNode *kid)
   1.651 +{
   1.652 +    block->pn_expr = kid;
   1.653 +}
   1.654 +
   1.655 +inline bool
   1.656 +FullParseHandler::finishInitializerAssignment(ParseNode *pn, ParseNode *init, JSOp op)
   1.657 +{
   1.658 +    if (pn->isUsed()) {
   1.659 +        pn = makeAssignment(pn, init);
   1.660 +        if (!pn)
   1.661 +            return false;
   1.662 +    } else {
   1.663 +        pn->pn_expr = init;
   1.664 +    }
   1.665 +
   1.666 +    pn->setOp((pn->pn_dflags & PND_BOUND)
   1.667 +              ? JSOP_SETLOCAL
   1.668 +              : (op == JSOP_DEFCONST)
   1.669 +              ? JSOP_SETCONST
   1.670 +              : JSOP_SETNAME);
   1.671 +
   1.672 +    pn->markAsAssigned();
   1.673 +
   1.674 +    /* The declarator's position must include the initializer. */
   1.675 +    pn->pn_pos.end = init->pn_pos.end;
   1.676 +    return true;
   1.677 +}
   1.678 +
   1.679 +inline ParseNode *
   1.680 +FullParseHandler::makeAssignment(ParseNode *pn, ParseNode *rhs)
   1.681 +{
   1.682 +    ParseNode *lhs = cloneNode(*pn);
   1.683 +    if (!lhs)
   1.684 +        return nullptr;
   1.685 +
   1.686 +    if (pn->isUsed()) {
   1.687 +        Definition *dn = pn->pn_lexdef;
   1.688 +        ParseNode **pnup = &dn->dn_uses;
   1.689 +
   1.690 +        while (*pnup != pn)
   1.691 +            pnup = &(*pnup)->pn_link;
   1.692 +        *pnup = lhs;
   1.693 +        lhs->pn_link = pn->pn_link;
   1.694 +        pn->pn_link = nullptr;
   1.695 +    }
   1.696 +
   1.697 +    pn->setKind(PNK_ASSIGN);
   1.698 +    pn->setOp(JSOP_NOP);
   1.699 +    pn->setArity(PN_BINARY);
   1.700 +    pn->setInParens(false);
   1.701 +    pn->setUsed(false);
   1.702 +    pn->setDefn(false);
   1.703 +    pn->pn_left = lhs;
   1.704 +    pn->pn_right = rhs;
   1.705 +    pn->pn_pos.end = rhs->pn_pos.end;
   1.706 +    return lhs;
   1.707 +}
   1.708 +
   1.709 +} // frontend
   1.710 +} // js
   1.711 +
   1.712 +#endif /* frontend_FullParseHandler_h */

mercurial