js/src/frontend/FullParseHandler.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     7 #ifndef frontend_FullParseHandler_h
     8 #define frontend_FullParseHandler_h
    10 #include "mozilla/PodOperations.h"
    12 #include "frontend/ParseNode.h"
    13 #include "frontend/SharedContext.h"
    15 namespace js {
    16 namespace frontend {
    18 template <typename ParseHandler>
    19 class Parser;
    21 class SyntaxParseHandler;
    23 // Parse handler used when generating a full parse tree for all code which the
    24 // parser encounters.
    25 class FullParseHandler
    26 {
    27     ParseNodeAllocator allocator;
    28     TokenStream &tokenStream;
    29     bool foldConstants;
    31     ParseNode *allocParseNode(size_t size) {
    32         JS_ASSERT(size == sizeof(ParseNode));
    33         return static_cast<ParseNode *>(allocator.allocNode());
    34     }
    36     ParseNode *cloneNode(const ParseNode &other) {
    37         ParseNode *node = allocParseNode(sizeof(ParseNode));
    38         if (!node)
    39             return nullptr;
    40         mozilla::PodAssign(node, &other);
    41         return node;
    42     }
    44     /*
    45      * If this is a full parse to construct the bytecode for a function that
    46      * was previously lazily parsed, that lazy function and the current index
    47      * into its inner functions. We do not want to reparse the inner functions.
    48      */
    49     LazyScript * const lazyOuterFunction_;
    50     size_t lazyInnerFunctionIndex;
    52     const TokenPos &pos() {
    53         return tokenStream.currentToken().pos;
    54     }
    56   public:
    58     /*
    59      * If non-nullptr, points to a syntax parser which can be used for inner
    60      * functions. Cleared if language features not handled by the syntax parser
    61      * are encountered, in which case all future activity will use the full
    62      * parser.
    63      */
    64     Parser<SyntaxParseHandler> *syntaxParser;
    66     /* new_ methods for creating parse nodes. These report OOM on context. */
    67     JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
    69     typedef ParseNode *Node;
    70     typedef Definition *DefinitionNode;
    72     FullParseHandler(ExclusiveContext *cx, LifoAlloc &alloc,
    73                      TokenStream &tokenStream, bool foldConstants,
    74                      Parser<SyntaxParseHandler> *syntaxParser, LazyScript *lazyOuterFunction)
    75       : allocator(cx, alloc),
    76         tokenStream(tokenStream),
    77         foldConstants(foldConstants),
    78         lazyOuterFunction_(lazyOuterFunction),
    79         lazyInnerFunctionIndex(0),
    80         syntaxParser(syntaxParser)
    81     {}
    83     static ParseNode *null() { return nullptr; }
    85     ParseNode *freeTree(ParseNode *pn) { return allocator.freeTree(pn); }
    86     void prepareNodeForMutation(ParseNode *pn) { return allocator.prepareNodeForMutation(pn); }
    87     const Token &currentToken() { return tokenStream.currentToken(); }
    89     ParseNode *newName(PropertyName *name, uint32_t blockid, const TokenPos &pos) {
    90         return new_<NameNode>(PNK_NAME, JSOP_NAME, name, blockid, pos);
    91     }
    93     Definition *newPlaceholder(JSAtom *atom, uint32_t blockid, const TokenPos &pos) {
    94         Definition *dn =
    95             (Definition *) new_<NameNode>(PNK_NAME, JSOP_NOP, atom, blockid, pos);
    96         if (!dn)
    97             return nullptr;
    98         dn->setDefn(true);
    99         dn->pn_dflags |= PND_PLACEHOLDER;
   100         return dn;
   101     }
   103     ParseNode *newIdentifier(JSAtom *atom, const TokenPos &pos) {
   104         return new_<NullaryNode>(PNK_NAME, JSOP_NOP, pos, atom);
   105     }
   107     ParseNode *newNumber(double value, DecimalPoint decimalPoint, const TokenPos &pos) {
   108         ParseNode *pn = new_<NullaryNode>(PNK_NUMBER, pos);
   109         if (!pn)
   110             return nullptr;
   111         pn->initNumber(value, decimalPoint);
   112         return pn;
   113     }
   115     ParseNode *newBooleanLiteral(bool cond, const TokenPos &pos) {
   116         return new_<BooleanLiteral>(cond, pos);
   117     }
   119     ParseNode *newStringLiteral(JSAtom *atom, const TokenPos &pos) {
   120         return new_<NullaryNode>(PNK_STRING, JSOP_STRING, pos, atom);
   121     }
   123     ParseNode *newThisLiteral(const TokenPos &pos) {
   124         return new_<ThisLiteral>(pos);
   125     }
   127     ParseNode *newNullLiteral(const TokenPos &pos) {
   128         return new_<NullLiteral>(pos);
   129     }
   131     // The Boxer object here is any object that can allocate ObjectBoxes.
   132     // Specifically, a Boxer has a .newObjectBox(T) method that accepts a
   133     // Rooted<RegExpObject*> argument and returns an ObjectBox*.
   134     template <class Boxer>
   135     ParseNode *newRegExp(HandleObject reobj, const TokenPos &pos, Boxer &boxer) {
   136         ObjectBox *objbox = boxer.newObjectBox(reobj);
   137         if (!objbox)
   138             return null();
   139         return new_<RegExpLiteral>(objbox, pos);
   140     }
   142     ParseNode *newConditional(ParseNode *cond, ParseNode *thenExpr, ParseNode *elseExpr) {
   143         return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
   144     }
   146     void markAsSetCall(ParseNode *pn) {
   147         pn->pn_xflags |= PNX_SETCALL;
   148     }
   150     ParseNode *newDelete(uint32_t begin, ParseNode *expr) {
   151         if (expr->getKind() == PNK_NAME) {
   152             expr->pn_dflags |= PND_DEOPTIMIZED;
   153             expr->setOp(JSOP_DELNAME);
   154         }
   155         return newUnary(PNK_DELETE, JSOP_NOP, begin, expr);
   156     }
   158     ParseNode *newNullary(ParseNodeKind kind, JSOp op, const TokenPos &pos) {
   159         return new_<NullaryNode>(kind, op, pos);
   160     }
   162     ParseNode *newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, ParseNode *kid) {
   163         TokenPos pos(begin, kid ? kid->pn_pos.end : begin + 1);
   164         return new_<UnaryNode>(kind, op, pos, kid);
   165     }
   167     ParseNode *newBinary(ParseNodeKind kind, JSOp op = JSOP_NOP) {
   168         return new_<BinaryNode>(kind, op, pos(), (ParseNode *) nullptr, (ParseNode *) nullptr);
   169     }
   170     ParseNode *newBinary(ParseNodeKind kind, ParseNode *left,
   171                          JSOp op = JSOP_NOP) {
   172         return new_<BinaryNode>(kind, op, left->pn_pos, left, (ParseNode *) nullptr);
   173     }
   174     ParseNode *newBinary(ParseNodeKind kind, ParseNode *left, ParseNode *right,
   175                          JSOp op = JSOP_NOP) {
   176         TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
   177         return new_<BinaryNode>(kind, op, pos, left, right);
   178     }
   179     ParseNode *newBinaryOrAppend(ParseNodeKind kind, ParseNode *left, ParseNode *right,
   180                                  ParseContext<FullParseHandler> *pc, JSOp op = JSOP_NOP)
   181     {
   182         return ParseNode::newBinaryOrAppend(kind, op, left, right, this, pc, foldConstants);
   183     }
   185     ParseNode *newTernary(ParseNodeKind kind,
   186                           ParseNode *first, ParseNode *second, ParseNode *third,
   187                           JSOp op = JSOP_NOP)
   188     {
   189         return new_<TernaryNode>(kind, op, first, second, third);
   190     }
   192     // Expressions
   194     ParseNode *newArrayComprehension(ParseNode *body, unsigned blockid, const TokenPos &pos) {
   195         JS_ASSERT(pos.begin <= body->pn_pos.begin);
   196         JS_ASSERT(body->pn_pos.end <= pos.end);
   197         ParseNode *pn = new_<ListNode>(PNK_ARRAYCOMP, pos);
   198         if (!pn)
   199             return nullptr;
   200         pn->pn_blockid = blockid;
   201         pn->append(body);
   202         return pn;
   203     }
   205     ParseNode *newArrayLiteral(uint32_t begin, unsigned blockid) {
   206         ParseNode *literal = new_<ListNode>(PNK_ARRAY, TokenPos(begin, begin + 1));
   207         // Later in this stack: remove dependency on this opcode.
   208         if (literal) {
   209             literal->setOp(JSOP_NEWINIT);
   210             literal->pn_blockid = blockid;
   211         }
   212         return literal;
   213     }
   215     bool addElision(ParseNode *literal, const TokenPos &pos) {
   216         ParseNode *elision = new_<NullaryNode>(PNK_ELISION, pos);
   217         if (!elision)
   218             return false;
   219         literal->append(elision);
   220         literal->pn_xflags |= PNX_SPECIALARRAYINIT | PNX_NONCONST;
   221         return true;
   222     }
   224     bool addSpreadElement(ParseNode *literal, uint32_t begin, ParseNode *inner) {
   225         TokenPos pos(begin, inner->pn_pos.end);
   226         ParseNode *spread = new_<UnaryNode>(PNK_SPREAD, JSOP_NOP, pos, inner);
   227         if (!spread)
   228             return null();
   229         literal->append(spread);
   230         literal->pn_xflags |= PNX_SPECIALARRAYINIT | PNX_NONCONST;
   231         return true;
   232     }
   234     bool addArrayElement(ParseNode *literal, ParseNode *element) {
   235         if (!element->isConstant())
   236             literal->pn_xflags |= PNX_NONCONST;
   237         literal->append(element);
   238         return true;
   239     }
   241     ParseNode *newObjectLiteral(uint32_t begin) {
   242         ParseNode *literal = new_<ListNode>(PNK_OBJECT, TokenPos(begin, begin + 1));
   243         // Later in this stack: remove dependency on this opcode.
   244         if (literal)
   245             literal->setOp(JSOP_NEWINIT);
   246         return literal;
   247     }
   249     bool addPropertyDefinition(ParseNode *literal, ParseNode *name, ParseNode *expr) {
   250         ParseNode *propdef = newBinary(PNK_COLON, name, expr, JSOP_INITPROP);
   251         if (!propdef)
   252             return false;
   253         literal->append(propdef);
   254         return true;
   255     }
   257     bool addShorthandPropertyDefinition(ParseNode *literal, ParseNode *name) {
   258         JS_ASSERT(literal->isArity(PN_LIST));
   259         literal->pn_xflags |= PNX_DESTRUCT | PNX_NONCONST;  // XXX why PNX_DESTRUCT?
   260         return addPropertyDefinition(literal, name, name);
   261     }
   263     bool addAccessorPropertyDefinition(ParseNode *literal, ParseNode *name, ParseNode *fn, JSOp op)
   264     {
   265         JS_ASSERT(literal->isArity(PN_LIST));
   266         literal->pn_xflags |= PNX_NONCONST;
   268         ParseNode *propdef = newBinary(PNK_COLON, name, fn, op);
   269         if (!propdef)
   270             return false;
   271         literal->append(propdef);
   272         return true;
   273     }
   275     // Statements
   277     ParseNode *newStatementList(unsigned blockid, const TokenPos &pos) {
   278         ParseNode *pn = new_<ListNode>(PNK_STATEMENTLIST, pos);
   279         if (pn)
   280             pn->pn_blockid = blockid;
   281         return pn;
   282     }
   284     template <typename PC>
   285     void addStatementToList(ParseNode *list, ParseNode *stmt, PC *pc) {
   286         JS_ASSERT(list->isKind(PNK_STATEMENTLIST));
   288         if (stmt->isKind(PNK_FUNCTION)) {
   289             if (pc->atBodyLevel()) {
   290                 // PNX_FUNCDEFS notifies the emitter that the block contains
   291                 // body-level function definitions that should be processed
   292                 // before the rest of nodes.
   293                 list->pn_xflags |= PNX_FUNCDEFS;
   294             } else {
   295                 // General deoptimization was done in Parser::functionDef.
   296                 JS_ASSERT_IF(pc->sc->isFunctionBox(),
   297                              pc->sc->asFunctionBox()->hasExtensibleScope());
   298             }
   299         }
   301         list->append(stmt);
   302     }
   304     ParseNode *newEmptyStatement(const TokenPos &pos) {
   305         return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
   306     }
   308     ParseNode *newImportDeclaration(ParseNode *importSpecSet,
   309                                     ParseNode *moduleSpec, const TokenPos &pos)
   310     {
   311         ParseNode *pn = new_<BinaryNode>(PNK_IMPORT, JSOP_NOP, pos,
   312                                          importSpecSet, moduleSpec);
   313         if (!pn)
   314             return null();
   315         return pn;
   316     }
   318     ParseNode *newExportDeclaration(ParseNode *kid, const TokenPos &pos) {
   319         return new_<UnaryNode>(PNK_EXPORT, JSOP_NOP, pos, kid);
   320     }
   322     ParseNode *newExportFromDeclaration(uint32_t begin, ParseNode *exportSpecSet,
   323                                         ParseNode *moduleSpec)
   324     {
   325         ParseNode *pn = new_<BinaryNode>(PNK_EXPORT_FROM, JSOP_NOP, exportSpecSet, moduleSpec);
   326         if (!pn)
   327             return null();
   328         pn->pn_pos.begin = begin;
   329         return pn;
   330     }
   332     ParseNode *newExprStatement(ParseNode *expr, uint32_t end) {
   333         JS_ASSERT(expr->pn_pos.end <= end);
   334         return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, TokenPos(expr->pn_pos.begin, end), expr);
   335     }
   337     ParseNode *newIfStatement(uint32_t begin, ParseNode *cond, ParseNode *thenBranch,
   338                               ParseNode *elseBranch)
   339     {
   340         ParseNode *pn = new_<TernaryNode>(PNK_IF, JSOP_NOP, cond, thenBranch, elseBranch);
   341         if (!pn)
   342             return null();
   343         pn->pn_pos.begin = begin;
   344         return pn;
   345     }
   347     ParseNode *newDoWhileStatement(ParseNode *body, ParseNode *cond, const TokenPos &pos) {
   348         return new_<BinaryNode>(PNK_DOWHILE, JSOP_NOP, pos, body, cond);
   349     }
   351     ParseNode *newWhileStatement(uint32_t begin, ParseNode *cond, ParseNode *body) {
   352         TokenPos pos(begin, body->pn_pos.end);
   353         return new_<BinaryNode>(PNK_WHILE, JSOP_NOP, pos, cond, body);
   354     }
   356     ParseNode *newForStatement(uint32_t begin, ParseNode *forHead, ParseNode *body,
   357                                unsigned iflags)
   358     {
   359         /* A FOR node is binary, left is loop control and right is the body. */
   360         JSOp op = forHead->isKind(PNK_FORIN) ? JSOP_ITER : JSOP_NOP;
   361         BinaryNode *pn = new_<BinaryNode>(PNK_FOR, op, TokenPos(begin, body->pn_pos.end),
   362                                           forHead, body);
   363         if (!pn)
   364             return null();
   365         pn->pn_iflags = iflags;
   366         return pn;
   367     }
   369     ParseNode *newForHead(ParseNodeKind kind, ParseNode *pn1, ParseNode *pn2, ParseNode *pn3,
   370                           const TokenPos &pos)
   371     {
   372         JS_ASSERT(kind == PNK_FORIN || kind == PNK_FOROF || kind == PNK_FORHEAD);
   373         return new_<TernaryNode>(kind, JSOP_NOP, pn1, pn2, pn3, pos);
   374     }
   376     ParseNode *newSwitchStatement(uint32_t begin, ParseNode *discriminant, ParseNode *caseList) {
   377         TokenPos pos(begin, caseList->pn_pos.end);
   378         return new_<BinaryNode>(PNK_SWITCH, JSOP_NOP, pos, discriminant, caseList);
   379     }
   381     ParseNode *newCaseOrDefault(uint32_t begin, ParseNode *expr, ParseNode *body) {
   382         TokenPos pos(begin, body->pn_pos.end);
   383         return new_<BinaryNode>(expr ? PNK_CASE : PNK_DEFAULT, JSOP_NOP, pos, expr, body);
   384     }
   386     ParseNode *newContinueStatement(PropertyName *label, const TokenPos &pos) {
   387         return new_<ContinueStatement>(label, pos);
   388     }
   390     ParseNode *newBreakStatement(PropertyName *label, const TokenPos &pos) {
   391         return new_<BreakStatement>(label, pos);
   392     }
   394     ParseNode *newReturnStatement(ParseNode *expr, const TokenPos &pos) {
   395         JS_ASSERT_IF(expr, pos.encloses(expr->pn_pos));
   396         return new_<UnaryNode>(PNK_RETURN, JSOP_RETURN, pos, expr);
   397     }
   399     ParseNode *newWithStatement(uint32_t begin, ParseNode *expr, ParseNode *body,
   400                                 ObjectBox *staticWith) {
   401         return new_<BinaryObjNode>(PNK_WITH, JSOP_NOP, TokenPos(begin, body->pn_pos.end),
   402                                    expr, body, staticWith);
   403     }
   405     ParseNode *newLabeledStatement(PropertyName *label, ParseNode *stmt, uint32_t begin) {
   406         return new_<LabeledStatement>(label, stmt, begin);
   407     }
   409     ParseNode *newThrowStatement(ParseNode *expr, const TokenPos &pos) {
   410         JS_ASSERT(pos.encloses(expr->pn_pos));
   411         return new_<UnaryNode>(PNK_THROW, JSOP_THROW, pos, expr);
   412     }
   414     ParseNode *newTryStatement(uint32_t begin, ParseNode *body, ParseNode *catchList,
   415                                ParseNode *finallyBlock) {
   416         TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end);
   417         return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos);
   418     }
   420     ParseNode *newDebuggerStatement(const TokenPos &pos) {
   421         return new_<DebuggerStatement>(pos);
   422     }
   424     ParseNode *newPropertyAccess(ParseNode *pn, PropertyName *name, uint32_t end) {
   425         return new_<PropertyAccess>(pn, name, pn->pn_pos.begin, end);
   426     }
   428     ParseNode *newPropertyByValue(ParseNode *lhs, ParseNode *index, uint32_t end) {
   429         return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
   430     }
   432     inline bool addCatchBlock(ParseNode *catchList, ParseNode *letBlock,
   433                               ParseNode *catchName, ParseNode *catchGuard, ParseNode *catchBody);
   435     inline void setLastFunctionArgumentDefault(ParseNode *funcpn, ParseNode *pn);
   436     inline ParseNode *newFunctionDefinition();
   437     void setFunctionBody(ParseNode *pn, ParseNode *kid) {
   438         pn->pn_body = kid;
   439     }
   440     void setFunctionBox(ParseNode *pn, FunctionBox *funbox) {
   441         JS_ASSERT(pn->isKind(PNK_FUNCTION));
   442         pn->pn_funbox = funbox;
   443     }
   444     void addFunctionArgument(ParseNode *pn, ParseNode *argpn) {
   445         pn->pn_body->append(argpn);
   446     }
   448     inline ParseNode *newLexicalScope(ObjectBox *blockbox);
   449     inline void setLexicalScopeBody(ParseNode *block, ParseNode *body);
   451     bool isOperationWithoutParens(ParseNode *pn, ParseNodeKind kind) {
   452         return pn->isKind(kind) && !pn->isInParens();
   453     }
   455     inline bool finishInitializerAssignment(ParseNode *pn, ParseNode *init, JSOp op);
   457     void setBeginPosition(ParseNode *pn, ParseNode *oth) {
   458         setBeginPosition(pn, oth->pn_pos.begin);
   459     }
   460     void setBeginPosition(ParseNode *pn, uint32_t begin) {
   461         pn->pn_pos.begin = begin;
   462         JS_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
   463     }
   465     void setEndPosition(ParseNode *pn, ParseNode *oth) {
   466         setEndPosition(pn, oth->pn_pos.end);
   467     }
   468     void setEndPosition(ParseNode *pn, uint32_t end) {
   469         pn->pn_pos.end = end;
   470         JS_ASSERT(pn->pn_pos.begin <= pn->pn_pos.end);
   471     }
   473     void setPosition(ParseNode *pn, const TokenPos &pos) {
   474         pn->pn_pos = pos;
   475     }
   476     TokenPos getPosition(ParseNode *pn) {
   477         return pn->pn_pos;
   478     }
   480     ParseNode *newList(ParseNodeKind kind, ParseNode *kid = nullptr, JSOp op = JSOP_NOP) {
   481         ParseNode *pn = ListNode::create(kind, this);
   482         if (!pn)
   483             return nullptr;
   484         pn->setOp(op);
   485         pn->makeEmpty();
   486         if (kid) {
   487             pn->pn_pos.begin = kid->pn_pos.begin;
   488             pn->append(kid);
   489         }
   490         return pn;
   491     }
   492     void addList(ParseNode *pn, ParseNode *kid) {
   493         pn->append(kid);
   494     }
   496     bool isUnparenthesizedYield(ParseNode *pn) {
   497         return pn->isKind(PNK_YIELD) && !pn->isInParens();
   498     }
   500     void setOp(ParseNode *pn, JSOp op) {
   501         pn->setOp(op);
   502     }
   503     void setBlockId(ParseNode *pn, unsigned blockid) {
   504         pn->pn_blockid = blockid;
   505     }
   506     void setFlag(ParseNode *pn, unsigned flag) {
   507         pn->pn_dflags |= flag;
   508     }
   509     void setListFlag(ParseNode *pn, unsigned flag) {
   510         JS_ASSERT(pn->isArity(PN_LIST));
   511         pn->pn_xflags |= flag;
   512     }
   513     ParseNode *setInParens(ParseNode *pn) {
   514         pn->setInParens(true);
   515         return pn;
   516     }
   517     void setPrologue(ParseNode *pn) {
   518         pn->pn_prologue = true;
   519     }
   521     bool isConstant(ParseNode *pn) {
   522         return pn->isConstant();
   523     }
   524     PropertyName *isName(ParseNode *pn) {
   525         return pn->isKind(PNK_NAME) ? pn->pn_atom->asPropertyName() : nullptr;
   526     }
   527     bool isCall(ParseNode *pn) {
   528         return pn->isKind(PNK_CALL);
   529     }
   530     PropertyName *isGetProp(ParseNode *pn) {
   531         return pn->is<PropertyAccess>() ? &pn->as<PropertyAccess>().name() : nullptr;
   532     }
   533     JSAtom *isStringExprStatement(ParseNode *pn, TokenPos *pos) {
   534         if (JSAtom *atom = pn->isStringExprStatement()) {
   535             *pos = pn->pn_kid->pn_pos;
   536             return atom;
   537         }
   538         return nullptr;
   539     }
   541     inline ParseNode *makeAssignment(ParseNode *pn, ParseNode *rhs);
   543     static Definition *getDefinitionNode(Definition *dn) {
   544         return dn;
   545     }
   546     static Definition::Kind getDefinitionKind(Definition *dn) {
   547         return dn->kind();
   548     }
   549     void linkUseToDef(ParseNode *pn, Definition *dn)
   550     {
   551         JS_ASSERT(!pn->isUsed());
   552         JS_ASSERT(!pn->isDefn());
   553         JS_ASSERT(pn != dn->dn_uses);
   554         JS_ASSERT(dn->isDefn());
   555         pn->pn_link = dn->dn_uses;
   556         dn->dn_uses = pn;
   557         dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
   558         pn->setUsed(true);
   559         pn->pn_lexdef = dn;
   560     }
   561     Definition *resolve(Definition *dn) {
   562         return dn->resolve();
   563     }
   564     void deoptimizeUsesWithin(Definition *dn, const TokenPos &pos)
   565     {
   566         for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
   567             JS_ASSERT(pnu->isUsed());
   568             JS_ASSERT(!pnu->isDefn());
   569             if (pnu->pn_pos.begin >= pos.begin && pnu->pn_pos.end <= pos.end)
   570                 pnu->pn_dflags |= PND_DEOPTIMIZED;
   571         }
   572     }
   573     bool dependencyCovered(ParseNode *pn, unsigned blockid, bool functionScope) {
   574         return pn->pn_blockid >= blockid;
   575     }
   577     static uintptr_t definitionToBits(Definition *dn) {
   578         return uintptr_t(dn);
   579     }
   580     static Definition *definitionFromBits(uintptr_t bits) {
   581         return (Definition *) bits;
   582     }
   583     static Definition *nullDefinition() {
   584         return nullptr;
   585     }
   586     void disableSyntaxParser() {
   587         syntaxParser = nullptr;
   588     }
   590     LazyScript *lazyOuterFunction() {
   591         return lazyOuterFunction_;
   592     }
   593     JSFunction *nextLazyInnerFunction() {
   594         JS_ASSERT(lazyInnerFunctionIndex < lazyOuterFunction()->numInnerFunctions());
   595         return lazyOuterFunction()->innerFunctions()[lazyInnerFunctionIndex++];
   596     }
   597 };
   599 inline bool
   600 FullParseHandler::addCatchBlock(ParseNode *catchList, ParseNode *letBlock,
   601                                 ParseNode *catchName, ParseNode *catchGuard, ParseNode *catchBody)
   602 {
   603     ParseNode *catchpn = newTernary(PNK_CATCH, catchName, catchGuard, catchBody);
   604     if (!catchpn)
   605         return false;
   607     catchList->append(letBlock);
   608     letBlock->pn_expr = catchpn;
   609     return true;
   610 }
   612 inline void
   613 FullParseHandler::setLastFunctionArgumentDefault(ParseNode *funcpn, ParseNode *defaultValue)
   614 {
   615     ParseNode *arg = funcpn->pn_body->last();
   616     arg->pn_dflags |= PND_DEFAULT;
   617     arg->pn_expr = defaultValue;
   618 }
   620 inline ParseNode *
   621 FullParseHandler::newFunctionDefinition()
   622 {
   623     ParseNode *pn = CodeNode::create(PNK_FUNCTION, this);
   624     if (!pn)
   625         return nullptr;
   626     pn->pn_body = nullptr;
   627     pn->pn_funbox = nullptr;
   628     pn->pn_cookie.makeFree();
   629     pn->pn_dflags = 0;
   630     return pn;
   631 }
   633 inline ParseNode *
   634 FullParseHandler::newLexicalScope(ObjectBox *blockbox)
   635 {
   636     ParseNode *pn = LexicalScopeNode::create(PNK_LEXICALSCOPE, this);
   637     if (!pn)
   638         return nullptr;
   640     pn->pn_objbox = blockbox;
   641     pn->pn_cookie.makeFree();
   642     pn->pn_dflags = 0;
   643     return pn;
   644 }
   646 inline void
   647 FullParseHandler::setLexicalScopeBody(ParseNode *block, ParseNode *kid)
   648 {
   649     block->pn_expr = kid;
   650 }
   652 inline bool
   653 FullParseHandler::finishInitializerAssignment(ParseNode *pn, ParseNode *init, JSOp op)
   654 {
   655     if (pn->isUsed()) {
   656         pn = makeAssignment(pn, init);
   657         if (!pn)
   658             return false;
   659     } else {
   660         pn->pn_expr = init;
   661     }
   663     pn->setOp((pn->pn_dflags & PND_BOUND)
   664               ? JSOP_SETLOCAL
   665               : (op == JSOP_DEFCONST)
   666               ? JSOP_SETCONST
   667               : JSOP_SETNAME);
   669     pn->markAsAssigned();
   671     /* The declarator's position must include the initializer. */
   672     pn->pn_pos.end = init->pn_pos.end;
   673     return true;
   674 }
   676 inline ParseNode *
   677 FullParseHandler::makeAssignment(ParseNode *pn, ParseNode *rhs)
   678 {
   679     ParseNode *lhs = cloneNode(*pn);
   680     if (!lhs)
   681         return nullptr;
   683     if (pn->isUsed()) {
   684         Definition *dn = pn->pn_lexdef;
   685         ParseNode **pnup = &dn->dn_uses;
   687         while (*pnup != pn)
   688             pnup = &(*pnup)->pn_link;
   689         *pnup = lhs;
   690         lhs->pn_link = pn->pn_link;
   691         pn->pn_link = nullptr;
   692     }
   694     pn->setKind(PNK_ASSIGN);
   695     pn->setOp(JSOP_NOP);
   696     pn->setArity(PN_BINARY);
   697     pn->setInParens(false);
   698     pn->setUsed(false);
   699     pn->setDefn(false);
   700     pn->pn_left = lhs;
   701     pn->pn_right = rhs;
   702     pn->pn_pos.end = rhs->pn_pos.end;
   703     return lhs;
   704 }
   706 } // frontend
   707 } // js
   709 #endif /* frontend_FullParseHandler_h */

mercurial