X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..40a37d088818fc2fbeba2ef850dbcaaf294befbf:/parser/Nodes.h diff --git a/parser/Nodes.h b/parser/Nodes.h index a9f88b7..a3b4153 100644 --- a/parser/Nodes.h +++ b/parser/Nodes.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel @@ -30,37 +30,23 @@ #include "JITCode.h" #include "Opcode.h" #include "ParserArena.h" +#include "ParserTokens.h" #include "ResultType.h" #include "SourceCode.h" #include "SymbolTable.h" #include -#include namespace JSC { class ArgumentListNode; - class CodeBlock; class BytecodeGenerator; - class FuncDeclNode; - class EvalCodeBlock; - class JSFunction; - class ProgramCodeBlock; + class FunctionBodyNode; + class Label; class PropertyListNode; class ReadModifyResolveNode; class RegisterID; - class ScopeChainNode; - - typedef unsigned CodeFeatures; - - const CodeFeatures NoFeatures = 0; - const CodeFeatures EvalFeature = 1 << 0; - const CodeFeatures ClosureFeature = 1 << 1; - const CodeFeatures AssignFeature = 1 << 2; - const CodeFeatures ArgumentsFeature = 1 << 3; - const CodeFeatures WithFeature = 1 << 4; - const CodeFeatures CatchFeature = 1 << 5; - const CodeFeatures ThisFeature = 1 << 6; - const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature; + class JSScope; + class ScopeNode; enum Operator { OpEqual, @@ -84,10 +70,18 @@ namespace JSC { OpLogicalOr }; + enum FallThroughMode { + FallThroughMeansTrue = 0, + FallThroughMeansFalse = 1 + }; + inline FallThroughMode invert(FallThroughMode fallThroughMode) { return static_cast(!fallThroughMode); } + + typedef HashSet, IdentifierRepHash> IdentifierSet; + namespace DeclarationStacks { enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; - typedef Vector > VarStack; - typedef Vector FunctionStack; + typedef Vector> VarStack; + typedef Vector FunctionStack; } struct SwitchInfo { @@ -96,24 +90,31 @@ namespace JSC { SwitchType switchType; }; - class ParserArenaDeletable { - protected: - ParserArenaDeletable() { } + class ParserArenaFreeable { + public: + // ParserArenaFreeable objects are are freed when the arena is deleted. + // Destructors are not called. Clients must not call delete on such objects. + void* operator new(size_t, VM*); + }; + class ParserArenaDeletable { public: virtual ~ParserArenaDeletable() { } - // Objects created with this version of new are deleted when the arena is deleted. - void* operator new(size_t, JSGlobalData*); + // ParserArenaDeletable objects are deleted when the arena is deleted. + // Clients must not call delete directly on such objects. + void* operator new(size_t, VM*); + }; - // Objects created with this version of new are not deleted when the arena is deleted. - // Other arrangements must be made. - void* operator new(size_t); + template + struct ParserArenaData : ParserArenaDeletable { + T data; }; class ParserArenaRefCounted : public RefCounted { + WTF_MAKE_FAST_ALLOCATED; protected: - ParserArenaRefCounted(JSGlobalData*); + ParserArenaRefCounted(VM*); public: virtual ~ParserArenaRefCounted() @@ -122,277 +123,329 @@ namespace JSC { } }; - class Node : public ParserArenaDeletable { + class Node : public ParserArenaFreeable { protected: - Node(JSGlobalData*); + Node(const JSTokenLocation&); public: - /* - Return value: The register holding the production's value. - dst: An optional parameter specifying the most efficient - destination at which to store the production's value. - The callee must honor dst. - - dst provides for a crude form of copy propagation. For example, - - x = 1 - - becomes - - load r[x], 1 - - instead of + virtual ~Node() { } - load r0, 1 - mov r[x], r0 - - because the assignment node, "x =", passes r[x] as dst to the number - node, "1". - */ - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) = 0; - - int lineNo() const { return m_line; } + int lineNo() const { return m_position.line; } + int startOffset() const { return m_position.offset; } + int lineStartOffset() const { return m_position.lineStartOffset; } + const JSTextPosition& position() const { return m_position; } protected: - int m_line; + JSTextPosition m_position; }; class ExpressionNode : public Node { + protected: + ExpressionNode(const JSTokenLocation&, ResultType = ResultType::unknownType()); + public: - ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType()); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; virtual bool isNumber() const { return false; } virtual bool isString() const { return false; } virtual bool isNull() const { return false; } virtual bool isPure(BytecodeGenerator&) const { return false; } + virtual bool isConstant() const { return false; } virtual bool isLocation() const { return false; } + virtual bool isAssignmentLocation() const { return isLocation(); } virtual bool isResolveNode() const { return false; } virtual bool isBracketAccessorNode() const { return false; } virtual bool isDotAccessorNode() const { return false; } + virtual bool isDeconstructionNode() const { return false; } virtual bool isFuncExprNode() const { return false; } virtual bool isCommaNode() const { return false; } virtual bool isSimpleArray() const { return false; } virtual bool isAdd() const { return false; } + virtual bool isSubtract() const { return false; } + virtual bool isBoolean() const { return false; } + virtual bool isSpreadExpression() const { return false; } + + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, FallThroughMode); virtual ExpressionNode* stripUnaryPlus() { return this; } ResultType resultDescriptor() const { return m_resultType; } - // This needs to be in public in order to compile using GCC 3.x - typedef enum { EvalOperator, FunctionCall } CallerType; - private: ResultType m_resultType; }; class StatementNode : public Node { + protected: + StatementNode(const JSTokenLocation&); + public: - StatementNode(JSGlobalData*); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; - void setLoc(int line0, int line1); - int firstLine() const { return lineNo(); } - int lastLine() const { return m_lastLine; } + void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset); + unsigned firstLine() const { return lineNo(); } + unsigned lastLine() const { return m_lastLine; } virtual bool isEmptyStatement() const { return false; } virtual bool isReturnNode() const { return false; } virtual bool isExprStatement() const { return false; } - + virtual bool isBreak() const { return false; } + virtual bool isContinue() const { return false; } virtual bool isBlock() const { return false; } - private: + protected: int m_lastLine; }; - class NullNode : public ExpressionNode { + class ConstantNode : public ExpressionNode { public: - NullNode(JSGlobalData*); - + ConstantNode(const JSTokenLocation&, ResultType); + virtual bool isPure(BytecodeGenerator&) const override { return true; } + virtual bool isConstant() const override { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const = 0; private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - virtual bool isNull() const { return true; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; }; - class BooleanNode : public ExpressionNode { + class NullNode : public ConstantNode { public: - BooleanNode(JSGlobalData*, bool value); + NullNode(const JSTokenLocation&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isNull() const override { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNull(); } + }; - virtual bool isPure(BytecodeGenerator&) const { return true; } + class BooleanNode : public ConstantNode { + public: + BooleanNode(const JSTokenLocation&, bool value); + bool value() { return m_value; } + + private: + virtual bool isBoolean() const override { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override { return jsBoolean(m_value); } bool m_value; }; - class NumberNode : public ExpressionNode { + class NumberNode : public ConstantNode { public: - NumberNode(JSGlobalData*, double v); - - double value() const { return m_double; } - void setValue(double d) { m_double = d; } + NumberNode(const JSTokenLocation&, double value); + double value() { return m_value; } + void setValue(double value) { m_value = value; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isNumber() const override { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNumber(m_value); } - virtual bool isNumber() const { return true; } - virtual bool isPure(BytecodeGenerator&) const { return true; } - - double m_double; + double m_value; }; - class StringNode : public ExpressionNode { + class StringNode : public ConstantNode { public: - StringNode(JSGlobalData*, const Identifier& v); - + StringNode(const JSTokenLocation&, const Identifier&); const Identifier& value() { return m_value; } - virtual bool isPure(BytecodeGenerator&) const { return true; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - virtual bool isString() const { return true; } + virtual bool isString() const override { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override; - Identifier m_value; + const Identifier& m_value; }; class ThrowableExpressionData { public: ThrowableExpressionData() - : m_divot(static_cast(-1)) - , m_startOffset(static_cast(-1)) - , m_endOffset(static_cast(-1)) + : m_divot(-1, -1, -1) + , m_divotStart(-1, -1, -1) + , m_divotEnd(-1, -1, -1) { } - ThrowableExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) + ThrowableExpressionData(const JSTextPosition& divot, const JSTextPosition& start, const JSTextPosition& end) : m_divot(divot) - , m_startOffset(startOffset) - , m_endOffset(endOffset) + , m_divotStart(start) + , m_divotEnd(end) { + ASSERT(m_divot.offset >= m_divot.lineStartOffset); + ASSERT(m_divotStart.offset >= m_divotStart.lineStartOffset); + ASSERT(m_divotEnd.offset >= m_divotEnd.lineStartOffset); } - - void setExceptionSourceCode(unsigned divot, unsigned startOffset, unsigned endOffset) + + void setExceptionSourceCode(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd) { + ASSERT(divot.offset >= divot.lineStartOffset); + ASSERT(divotStart.offset >= divotStart.lineStartOffset); + ASSERT(divotEnd.offset >= divotEnd.lineStartOffset); m_divot = divot; - m_startOffset = startOffset; - m_endOffset = endOffset; + m_divotStart = divotStart; + m_divotEnd = divotEnd; } - uint32_t divot() const { return m_divot; } - uint16_t startOffset() const { return m_startOffset; } - uint16_t endOffset() const { return m_endOffset; } + const JSTextPosition& divot() const { return m_divot; } + const JSTextPosition& divotStart() const { return m_divotStart; } + const JSTextPosition& divotEnd() const { return m_divotEnd; } protected: - RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg); - RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg, const Identifier&); + RegisterID* emitThrowReferenceError(BytecodeGenerator&, const String& message); private: - uint32_t m_divot; - uint16_t m_startOffset; - uint16_t m_endOffset; + JSTextPosition m_divot; + JSTextPosition m_divotStart; + JSTextPosition m_divotEnd; }; class ThrowableSubExpressionData : public ThrowableExpressionData { public: ThrowableSubExpressionData() - : ThrowableExpressionData() - , m_subexpressionDivotOffset(0) + : m_subexpressionDivotOffset(0) , m_subexpressionEndOffset(0) + , m_subexpressionLineOffset(0) + , m_subexpressionLineStartOffset(0) { } - ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) - : ThrowableExpressionData(divot, startOffset, endOffset) + ThrowableSubExpressionData(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd) + : ThrowableExpressionData(divot, divotStart, divotEnd) , m_subexpressionDivotOffset(0) , m_subexpressionEndOffset(0) + , m_subexpressionLineOffset(0) + , m_subexpressionLineStartOffset(0) { } - void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + void setSubexpressionInfo(const JSTextPosition& subexpressionDivot, int subexpressionOffset) { - ASSERT(subexpressionDivot <= divot()); - if ((divot() - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + ASSERT(subexpressionDivot.offset <= divot().offset); + // Overflow means we can't do this safely, so just point at the primary divot, + // divotLine, or divotLineStart. + if ((divot() - subexpressionDivot.offset) & ~0xFFFF) + return; + if ((divot().line - subexpressionDivot.line) & ~0xFFFF) + return; + if ((divot().lineStartOffset - subexpressionDivot.lineStartOffset) & ~0xFFFF) + return; + if ((divotEnd() - subexpressionOffset) & ~0xFFFF) return; - m_subexpressionDivotOffset = divot() - subexpressionDivot; - m_subexpressionEndOffset = subexpressionOffset; + m_subexpressionDivotOffset = divot() - subexpressionDivot.offset; + m_subexpressionEndOffset = divotEnd() - subexpressionOffset; + m_subexpressionLineOffset = divot().line - subexpressionDivot.line; + m_subexpressionLineStartOffset = divot().lineStartOffset - subexpressionDivot.lineStartOffset; } + JSTextPosition subexpressionDivot() + { + int newLine = divot().line - m_subexpressionLineOffset; + int newOffset = divot().offset - m_subexpressionDivotOffset; + int newLineStartOffset = divot().lineStartOffset - m_subexpressionLineStartOffset; + return JSTextPosition(newLine, newOffset, newLineStartOffset); + } + JSTextPosition subexpressionStart() { return divotStart(); } + JSTextPosition subexpressionEnd() { return divotEnd() - static_cast(m_subexpressionEndOffset); } + protected: uint16_t m_subexpressionDivotOffset; uint16_t m_subexpressionEndOffset; + uint16_t m_subexpressionLineOffset; + uint16_t m_subexpressionLineStartOffset; }; class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData { public: ThrowablePrefixedSubExpressionData() - : ThrowableExpressionData() - , m_subexpressionDivotOffset(0) + : m_subexpressionDivotOffset(0) , m_subexpressionStartOffset(0) + , m_subexpressionLineOffset(0) + , m_subexpressionLineStartOffset(0) { } - ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) - : ThrowableExpressionData(divot, startOffset, endOffset) + ThrowablePrefixedSubExpressionData(const JSTextPosition& divot, const JSTextPosition& start, const JSTextPosition& end) + : ThrowableExpressionData(divot, start, end) , m_subexpressionDivotOffset(0) , m_subexpressionStartOffset(0) + , m_subexpressionLineOffset(0) + , m_subexpressionLineStartOffset(0) { } - void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + void setSubexpressionInfo(const JSTextPosition& subexpressionDivot, int subexpressionOffset) { - ASSERT(subexpressionDivot >= divot()); - if ((subexpressionDivot - divot()) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + ASSERT(subexpressionDivot.offset >= divot().offset); + // Overflow means we can't do this safely, so just point at the primary divot, + // divotLine, or divotLineStart. + if ((subexpressionDivot.offset - divot()) & ~0xFFFF) return; - m_subexpressionDivotOffset = subexpressionDivot - divot(); - m_subexpressionStartOffset = subexpressionOffset; + if ((subexpressionDivot.line - divot().line) & ~0xFFFF) + return; + if ((subexpressionDivot.lineStartOffset - divot().lineStartOffset) & ~0xFFFF) + return; + if ((subexpressionOffset - divotStart()) & ~0xFFFF) + return; + m_subexpressionDivotOffset = subexpressionDivot.offset - divot(); + m_subexpressionStartOffset = subexpressionOffset - divotStart(); + m_subexpressionLineOffset = subexpressionDivot.line - divot().line; + m_subexpressionLineStartOffset = subexpressionDivot.lineStartOffset - divot().lineStartOffset; } + JSTextPosition subexpressionDivot() + { + int newLine = divot().line + m_subexpressionLineOffset; + int newOffset = divot().offset + m_subexpressionDivotOffset; + int newLineStartOffset = divot().lineStartOffset + m_subexpressionLineStartOffset; + return JSTextPosition(newLine, newOffset, newLineStartOffset); + } + JSTextPosition subexpressionStart() { return divotStart() + static_cast(m_subexpressionStartOffset); } + JSTextPosition subexpressionEnd() { return divotEnd(); } + protected: uint16_t m_subexpressionDivotOffset; uint16_t m_subexpressionStartOffset; + uint16_t m_subexpressionLineOffset; + uint16_t m_subexpressionLineStartOffset; }; class RegExpNode : public ExpressionNode, public ThrowableExpressionData { public: - RegExpNode(JSGlobalData*, const UString& pattern, const UString& flags); + RegExpNode(const JSTokenLocation&, const Identifier& pattern, const Identifier& flags); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - UString m_pattern; - UString m_flags; + const Identifier& m_pattern; + const Identifier& m_flags; }; class ThisNode : public ExpressionNode { public: - ThisNode(JSGlobalData*); + ThisNode(const JSTokenLocation&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ResolveNode : public ExpressionNode { public: - ResolveNode(JSGlobalData*, const Identifier&, int startOffset); + ResolveNode(const JSTokenLocation&, const Identifier&, const JSTextPosition& start); const Identifier& identifier() const { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isPure(BytecodeGenerator&) const ; - virtual bool isLocation() const { return true; } - virtual bool isResolveNode() const { return true; } + virtual bool isPure(BytecodeGenerator&) const override; + virtual bool isLocation() const override { return true; } + virtual bool isResolveNode() const override { return true; } - Identifier m_ident; - int32_t m_startOffset; + const Identifier& m_ident; + JSTextPosition m_start; }; - class ElementNode : public ParserArenaDeletable { + class ElementNode : public ParserArenaFreeable { public: - ElementNode(JSGlobalData*, int elision, ExpressionNode*); - ElementNode(JSGlobalData*, ElementNode*, int elision, ExpressionNode*); + ElementNode(int elision, ExpressionNode*); + ElementNode(ElementNode*, int elision, ExpressionNode*); int elision() const { return m_elision; } ExpressionNode* value() { return m_node; } @@ -406,43 +459,50 @@ namespace JSC { class ArrayNode : public ExpressionNode { public: - ArrayNode(JSGlobalData*, int elision); - ArrayNode(JSGlobalData*, ElementNode*); - ArrayNode(JSGlobalData*, int elision, ElementNode*); + ArrayNode(const JSTokenLocation&, int elision); + ArrayNode(const JSTokenLocation&, ElementNode*); + ArrayNode(const JSTokenLocation&, int elision, ElementNode*); - ArgumentListNode* toArgumentList(JSGlobalData*) const; + ArgumentListNode* toArgumentList(VM*, int, int) const; + ElementNode* elements() const { ASSERT(isSimpleArray()); return m_element; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isSimpleArray() const ; + virtual bool isSimpleArray() const override; ElementNode* m_element; int m_elision; bool m_optional; }; - class PropertyNode : public ParserArenaDeletable { + class PropertyNode : public ParserArenaFreeable { public: - enum Type { Constant, Getter, Setter }; + enum Type { Constant = 1, Getter = 2, Setter = 4 }; - PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type); + PropertyNode(VM*, const Identifier&, ExpressionNode*, Type); + PropertyNode(VM*, double, ExpressionNode*, Type); + PropertyNode(VM*, ExpressionNode* propertyName, ExpressionNode*, Type); + + ExpressionNode* expressionName() const { return m_expression; } + const Identifier* name() const { return m_name; } - const Identifier& name() const { return m_name; } + Type type() const { return m_type; } private: friend class PropertyListNode; - Identifier m_name; + const Identifier* m_name; + ExpressionNode* m_expression; ExpressionNode* m_assign; Type m_type; }; - class PropertyListNode : public Node { + class PropertyListNode : public ExpressionNode { public: - PropertyListNode(JSGlobalData*, PropertyNode*); - PropertyListNode(JSGlobalData*, PropertyNode*, PropertyListNode*); + PropertyListNode(const JSTokenLocation&, PropertyNode*); + PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; private: PropertyNode* m_node; @@ -451,27 +511,29 @@ namespace JSC { class ObjectLiteralNode : public ExpressionNode { public: - ObjectLiteralNode(JSGlobalData*); - ObjectLiteralNode(JSGlobalData*, PropertyListNode*); + ObjectLiteralNode(const JSTokenLocation&); + ObjectLiteralNode(const JSTokenLocation&, PropertyListNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; PropertyListNode* m_list; }; class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData { public: - BracketAccessorNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments); + BracketAccessorNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments); ExpressionNode* base() const { return m_base; } ExpressionNode* subscript() const { return m_subscript; } + bool subscriptHasAssignments() const { return m_subscriptHasAssignments; } + private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isLocation() const { return true; } - virtual bool isBracketAccessorNode() const { return true; } + virtual bool isLocation() const override { return true; } + virtual bool isBracketAccessorNode() const override { return true; } ExpressionNode* m_base; ExpressionNode* m_subscript; @@ -480,48 +542,61 @@ namespace JSC { class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData { public: - DotAccessorNode(JSGlobalData*, ExpressionNode* base, const Identifier&); + DotAccessorNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&); ExpressionNode* base() const { return m_base; } const Identifier& identifier() const { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isLocation() const { return true; } - virtual bool isDotAccessorNode() const { return true; } + virtual bool isLocation() const override { return true; } + virtual bool isDotAccessorNode() const override { return true; } ExpressionNode* m_base; - Identifier m_ident; + const Identifier& m_ident; }; - class ArgumentListNode : public Node { + class SpreadExpressionNode : public ExpressionNode, public ThrowableExpressionData { public: - ArgumentListNode(JSGlobalData*, ExpressionNode*); - ArgumentListNode(JSGlobalData*, ArgumentListNode*, ExpressionNode*); + SpreadExpressionNode(const JSTokenLocation&, ExpressionNode*); + + ExpressionNode* expression() const { return m_expression; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + virtual bool isSpreadExpression() const override { return true; } + ExpressionNode* m_expression; + }; + + class ArgumentListNode : public ExpressionNode { + public: + ArgumentListNode(const JSTokenLocation&, ExpressionNode*); + ArgumentListNode(const JSTokenLocation&, ArgumentListNode*, ExpressionNode*); ArgumentListNode* m_next; ExpressionNode* m_expr; private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; - class ArgumentsNode : public ParserArenaDeletable { + class ArgumentsNode : public ParserArenaFreeable { public: - ArgumentsNode(JSGlobalData*); - ArgumentsNode(JSGlobalData*, ArgumentListNode*); + ArgumentsNode(); + ArgumentsNode(ArgumentListNode*); ArgumentListNode* m_listNode; }; class NewExprNode : public ExpressionNode, public ThrowableExpressionData { public: - NewExprNode(JSGlobalData*, ExpressionNode*); - NewExprNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*); + NewExprNode(const JSTokenLocation&, ExpressionNode*); + NewExprNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; ArgumentsNode* m_args; @@ -529,20 +604,20 @@ namespace JSC { class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { public: - EvalFunctionCallNode(JSGlobalData*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + EvalFunctionCallNode(const JSTokenLocation&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ArgumentsNode* m_args; }; class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallValueNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallValueNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; ArgumentsNode* m_args; @@ -550,23 +625,21 @@ namespace JSC { class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallResolveNode(JSGlobalData*, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallResolveNode(const JSTokenLocation&, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - Identifier m_ident; + const Identifier& m_ident; ArgumentsNode* m_args; - size_t m_index; // Used by LocalVarFunctionCallNode. - size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode }; class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; ExpressionNode* m_subscript; @@ -575,102 +648,49 @@ namespace JSC { class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; protected: ExpressionNode* m_base; - const Identifier m_ident; + const Identifier& m_ident; ArgumentsNode* m_args; }; class CallFunctionCallDotNode : public FunctionCallDotNode { public: - CallFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + CallFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ApplyFunctionCallDotNode : public FunctionCallDotNode { public: - ApplyFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - }; - - class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData { - public: - PrePostResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); - - protected: - const Identifier m_ident; - }; - - class PostfixResolveNode : public PrePostResolveNode { - public: - PostfixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - Operator m_operator; - }; - - class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData { - public: - PostfixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + ApplyFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - ExpressionNode* m_base; - ExpressionNode* m_subscript; - Operator m_operator; - }; - - class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData { - public: - PostfixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - ExpressionNode* m_base; - Identifier m_ident; - Operator m_operator; - }; - - class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData { - public: - PostfixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - ExpressionNode* m_expr; - Operator m_operator; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + DeleteResolveNode(const JSTokenLocation&, const Identifier&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - Identifier m_ident; + const Identifier& m_ident; }; class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset); + DeleteBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; ExpressionNode* m_subscript; @@ -678,111 +698,92 @@ namespace JSC { class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + DeleteDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; - Identifier m_ident; + const Identifier& m_ident; }; class DeleteValueNode : public ExpressionNode { public: - DeleteValueNode(JSGlobalData*, ExpressionNode*); + DeleteValueNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; class VoidNode : public ExpressionNode { public: - VoidNode(JSGlobalData*, ExpressionNode*); + VoidNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; class TypeOfResolveNode : public ExpressionNode { public: - TypeOfResolveNode(JSGlobalData*, const Identifier&); + TypeOfResolveNode(const JSTokenLocation&, const Identifier&); const Identifier& identifier() const { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - Identifier m_ident; + const Identifier& m_ident; }; class TypeOfValueNode : public ExpressionNode { public: - TypeOfValueNode(JSGlobalData*, ExpressionNode*); + TypeOfValueNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; - class PrefixResolveNode : public PrePostResolveNode { - public: - PrefixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - Operator m_operator; - }; - - class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { - public: - PrefixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - ExpressionNode* m_base; - ExpressionNode* m_subscript; - Operator m_operator; - }; - - class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { + class PrefixNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { public: - PrefixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + virtual RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitDot(BytecodeGenerator&, RegisterID* = 0); - ExpressionNode* m_base; - Identifier m_ident; + ExpressionNode* m_expr; Operator m_operator; }; - class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData { + class PostfixNode : public PrefixNode { public: - PrefixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - ExpressionNode* m_expr; - Operator m_operator; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + virtual RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0) override; + virtual RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0) override; + virtual RegisterID* emitDot(BytecodeGenerator&, RegisterID* = 0) override; }; class UnaryOpNode : public ExpressionNode { public: - UnaryOpNode(JSGlobalData*, ResultType, ExpressionNode*, OpcodeID); + UnaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode*, OpcodeID); protected: ExpressionNode* expr() { return m_expr; } + const ExpressionNode* expr() const { return m_expr; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; OpcodeID opcodeID() const { return m_opcodeID; } @@ -792,36 +793,52 @@ namespace JSC { class UnaryPlusNode : public UnaryOpNode { public: - UnaryPlusNode(JSGlobalData*, ExpressionNode*); + UnaryPlusNode(const JSTokenLocation&, ExpressionNode*); private: - virtual ExpressionNode* stripUnaryPlus() { return expr(); } + virtual ExpressionNode* stripUnaryPlus() override { return expr(); } }; class NegateNode : public UnaryOpNode { public: - NegateNode(JSGlobalData*, ExpressionNode*); + NegateNode(const JSTokenLocation&, ExpressionNode*); }; - class BitwiseNotNode : public UnaryOpNode { + class BitwiseNotNode : public ExpressionNode { public: - BitwiseNotNode(JSGlobalData*, ExpressionNode*); - }; + BitwiseNotNode(const JSTokenLocation&, ExpressionNode*); + protected: + ExpressionNode* expr() { return m_expr; } + const ExpressionNode* expr() const { return m_expr; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; + }; + class LogicalNotNode : public UnaryOpNode { public: - LogicalNotNode(JSGlobalData*, ExpressionNode*); + LogicalNotNode(const JSTokenLocation&, ExpressionNode*); + private: + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; }; class BinaryOpNode : public ExpressionNode { public: - BinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + BinaryOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + BinaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); + RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; + + ExpressionNode* lhs() { return m_expr1; }; + ExpressionNode* rhs() { return m_expr2; }; private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + void tryFoldToBranch(BytecodeGenerator&, TriState& branchCondition, ExpressionNode*& branchExpression); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; protected: OpcodeID opcodeID() const { return m_opcodeID; } @@ -835,146 +852,141 @@ namespace JSC { bool m_rightHasAssignments; }; - class ReverseBinaryOpNode : public BinaryOpNode { - public: - ReverseBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - ReverseBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - }; - class MultNode : public BinaryOpNode { public: - MultNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + MultNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class DivNode : public BinaryOpNode { public: - DivNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + DivNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class ModNode : public BinaryOpNode { public: - ModNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + ModNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class AddNode : public BinaryOpNode { public: - AddNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + AddNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual bool isAdd() const { return true; } + virtual bool isAdd() const override { return true; } }; class SubNode : public BinaryOpNode { public: - SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + SubNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + virtual bool isSubtract() const override { return true; } }; class LeftShiftNode : public BinaryOpNode { public: - LeftShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + LeftShiftNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class RightShiftNode : public BinaryOpNode { public: - RightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + RightShiftNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class UnsignedRightShiftNode : public BinaryOpNode { public: - UnsignedRightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + UnsignedRightShiftNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class LessNode : public BinaryOpNode { public: - LessNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + LessNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; - class GreaterNode : public ReverseBinaryOpNode { + class GreaterNode : public BinaryOpNode { public: - GreaterNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + GreaterNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class LessEqNode : public BinaryOpNode { public: - LessEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + LessEqNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; - class GreaterEqNode : public ReverseBinaryOpNode { + class GreaterEqNode : public BinaryOpNode { public: - GreaterEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + GreaterEqNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData { public: - ThrowableBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - ThrowableBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + ThrowableBinaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + ThrowableBinaryOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class InstanceOfNode : public ThrowableBinaryOpNode { public: - InstanceOfNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + InstanceOfNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class InNode : public ThrowableBinaryOpNode { public: - InNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + InNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class EqualNode : public BinaryOpNode { public: - EqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + EqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class NotEqualNode : public BinaryOpNode { public: - NotEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + NotEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class StrictEqualNode : public BinaryOpNode { public: - StrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + StrictEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class NotStrictEqualNode : public BinaryOpNode { public: - NotStrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + NotStrictEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitAndNode : public BinaryOpNode { public: - BitAndNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + BitAndNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitOrNode : public BinaryOpNode { public: - BitOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + BitOrNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitXOrNode : public BinaryOpNode { public: - BitXOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + BitXOrNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; // m_expr1 && m_expr2, m_expr1 || m_expr2 class LogicalOpNode : public ExpressionNode { public: - LogicalOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); + LogicalOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; ExpressionNode* m_expr1; ExpressionNode* m_expr2; @@ -984,10 +996,10 @@ namespace JSC { // The ternary operator, "m_logical ? m_expr1 : m_expr2" class ConditionalNode : public ExpressionNode { public: - ConditionalNode(JSGlobalData*, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); + ConditionalNode(const JSTokenLocation&, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_logical; ExpressionNode* m_expr1; @@ -996,52 +1008,49 @@ namespace JSC { class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - ReadModifyResolveNode(JSGlobalData*, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + ReadModifyResolveNode(const JSTokenLocation&, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - Identifier m_ident; + const Identifier& m_ident; ExpressionNode* m_right; - size_t m_index; // Used by ReadModifyLocalVarNode. Operator m_operator; bool m_rightHasAssignments; }; class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignResolveNode(JSGlobalData*, const Identifier&, ExpressionNode* right, bool rightHasAssignments); + AssignResolveNode(const JSTokenLocation&, const Identifier&, ExpressionNode* right); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - Identifier m_ident; + const Identifier& m_ident; ExpressionNode* m_right; - size_t m_index; // Used by ReadModifyLocalVarNode. - bool m_rightHasAssignments; }; class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + ReadModifyBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; ExpressionNode* m_subscript; ExpressionNode* m_right; - Operator m_operator : 30; + unsigned m_operator : 30; bool m_subscriptHasAssignments : 1; bool m_rightHasAssignments : 1; }; class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + AssignBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; ExpressionNode* m_subscript; @@ -1052,70 +1061,68 @@ namespace JSC { class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + AssignDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; - Identifier m_ident; + const Identifier& m_ident; ExpressionNode* m_right; bool m_rightHasAssignments; }; class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + ReadModifyDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; - Identifier m_ident; + const Identifier& m_ident; ExpressionNode* m_right; - Operator m_operator : 31; + unsigned m_operator : 31; bool m_rightHasAssignments : 1; }; class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignErrorNode(JSGlobalData*, ExpressionNode* left, Operator, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset); + AssignErrorNode(const JSTokenLocation&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - ExpressionNode* m_left; - Operator m_operator; - ExpressionNode* m_right; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; typedef Vector ExpressionVector; - class CommaNode : public ExpressionNode { + class CommaNode : public ExpressionNode, public ParserArenaDeletable { public: - CommaNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2); + CommaNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2); + + using ParserArenaDeletable::operator new; - void append(ExpressionNode* expr) { m_expressions.append(expr); } + void append(ExpressionNode* expr) { ASSERT(expr); m_expressions.append(expr); } private: - virtual bool isCommaNode() const { return true; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isCommaNode() const override { return true; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionVector m_expressions; }; class ConstDeclNode : public ExpressionNode { public: - ConstDeclNode(JSGlobalData*, const Identifier&, ExpressionNode*); + ConstDeclNode(const JSTokenLocation&, const Identifier&, ExpressionNode*); bool hasInitializer() const { return m_init; } const Identifier& ident() { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; virtual RegisterID* emitCodeSingle(BytecodeGenerator&); - Identifier m_ident; + const Identifier& m_ident; public: ConstDeclNode* m_next; @@ -1126,115 +1133,105 @@ namespace JSC { class ConstStatementNode : public StatementNode { public: - ConstStatementNode(JSGlobalData*, ConstDeclNode* next); + ConstStatementNode(const JSTokenLocation&, ConstDeclNode* next); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ConstDeclNode* m_next; }; - typedef Vector StatementVector; - class SourceElements : public ParserArenaDeletable { public: - SourceElements(JSGlobalData*); + SourceElements(); void append(StatementNode*); - void releaseContentsIntoVector(StatementVector& destination) - { - ASSERT(destination.isEmpty()); - m_statements.swap(destination); - destination.shrinkToFit(); - } + + StatementNode* singleStatement() const; + StatementNode* lastStatement() const; + + void emitBytecode(BytecodeGenerator&, RegisterID* destination); private: - StatementVector m_statements; + Vector m_statements; }; class BlockNode : public StatementNode { public: - BlockNode(JSGlobalData*, SourceElements* children); + BlockNode(const JSTokenLocation&, SourceElements* = 0); - StatementVector& children() { return m_children; } + StatementNode* singleStatement() const; + StatementNode* lastStatement() const; private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isBlock() const { return true; } + virtual bool isBlock() const override { return true; } - StatementVector m_children; + SourceElements* m_statements; }; class EmptyStatementNode : public StatementNode { public: - EmptyStatementNode(JSGlobalData*); + EmptyStatementNode(const JSTokenLocation&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isEmptyStatement() const { return true; } + virtual bool isEmptyStatement() const override { return true; } }; class DebuggerStatementNode : public StatementNode { public: - DebuggerStatementNode(JSGlobalData*); + DebuggerStatementNode(const JSTokenLocation&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ExprStatementNode : public StatementNode { public: - ExprStatementNode(JSGlobalData*, ExpressionNode*); + ExprStatementNode(const JSTokenLocation&, ExpressionNode*); ExpressionNode* expr() const { return m_expr; } private: - virtual bool isExprStatement() const { return true; } + virtual bool isExprStatement() const override { return true; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; class VarStatementNode : public StatementNode { public: - VarStatementNode(JSGlobalData*, ExpressionNode*); - + VarStatementNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; - class IfNode : public StatementNode { + class IfElseNode : public StatementNode { public: - IfNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock); + IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); - protected: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + bool tryFoldBreakAndContinue(BytecodeGenerator&, StatementNode* ifBlock, + Label*& trueTarget, FallThroughMode&); ExpressionNode* m_condition; StatementNode* m_ifBlock; - }; - - class IfElseNode : public IfNode { - public: - IfElseNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - StatementNode* m_elseBlock; }; class DoWhileNode : public StatementNode { public: - DoWhileNode(JSGlobalData*, StatementNode* statement, ExpressionNode*); + DoWhileNode(const JSTokenLocation&, StatementNode*, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; StatementNode* m_statement; ExpressionNode* m_expr; @@ -1242,10 +1239,10 @@ namespace JSC { class WhileNode : public StatementNode { public: - WhileNode(JSGlobalData*, ExpressionNode*, StatementNode* statement); + WhileNode(const JSTokenLocation&, ExpressionNode*, StatementNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; StatementNode* m_statement; @@ -1253,408 +1250,470 @@ namespace JSC { class ForNode : public StatementNode { public: - ForNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl); + ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr1; ExpressionNode* m_expr2; ExpressionNode* m_expr3; StatementNode* m_statement; - bool m_expr1WasVarDecl; }; - - class ForInNode : public StatementNode, public ThrowableExpressionData { + + class DeconstructionPatternNode; + + class EnumerationNode : public StatementNode, public ThrowableExpressionData { public: - ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*); - ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset); - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - Identifier m_ident; - ExpressionNode* m_init; + EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); + EnumerationNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*); + + protected: ExpressionNode* m_lexpr; ExpressionNode* m_expr; StatementNode* m_statement; - bool m_identIsVarDecl; + }; + + class ForInNode : public EnumerationNode { + public: + ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); + ForInNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*); + + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + }; + + class ForOfNode : public EnumerationNode { + public: + ForOfNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); + ForOfNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*); + + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ContinueNode : public StatementNode, public ThrowableExpressionData { public: - ContinueNode(JSGlobalData*); - ContinueNode(JSGlobalData*, const Identifier&); + ContinueNode(VM*, const JSTokenLocation&); + ContinueNode(const JSTokenLocation&, const Identifier&); + Label* trivialTarget(BytecodeGenerator&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isContinue() const override { return true; } + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - Identifier m_ident; + const Identifier& m_ident; }; class BreakNode : public StatementNode, public ThrowableExpressionData { public: - BreakNode(JSGlobalData*); - BreakNode(JSGlobalData*, const Identifier&); + BreakNode(VM*, const JSTokenLocation&); + BreakNode(const JSTokenLocation&, const Identifier&); + Label* trivialTarget(BytecodeGenerator&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isBreak() const override { return true; } + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - Identifier m_ident; + const Identifier& m_ident; }; class ReturnNode : public StatementNode, public ThrowableExpressionData { public: - ReturnNode(JSGlobalData*, ExpressionNode* value); + ReturnNode(const JSTokenLocation&, ExpressionNode* value); + + ExpressionNode* value() { return m_value; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isReturnNode() const { return true; } + virtual bool isReturnNode() const override { return true; } ExpressionNode* m_value; }; class WithNode : public StatementNode { public: - WithNode(JSGlobalData*, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength); + WithNode(const JSTokenLocation&, ExpressionNode*, StatementNode*, const JSTextPosition& divot, uint32_t expressionLength); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; StatementNode* m_statement; - uint32_t m_divot; + JSTextPosition m_divot; uint32_t m_expressionLength; }; class LabelNode : public StatementNode, public ThrowableExpressionData { public: - LabelNode(JSGlobalData*, const Identifier& name, StatementNode*); + LabelNode(const JSTokenLocation&, const Identifier& name, StatementNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - Identifier m_name; + const Identifier& m_name; StatementNode* m_statement; }; class ThrowNode : public StatementNode, public ThrowableExpressionData { public: - ThrowNode(JSGlobalData*, ExpressionNode*); + ThrowNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; class TryNode : public StatementNode { public: - TryNode(JSGlobalData*, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock); + TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; StatementNode* m_tryBlock; - Identifier m_exceptionIdent; + const Identifier& m_exceptionIdent; StatementNode* m_catchBlock; StatementNode* m_finallyBlock; - bool m_catchHasEval; }; class ParameterNode : public ParserArenaDeletable { public: - ParameterNode(JSGlobalData*, const Identifier&); - ParameterNode(JSGlobalData*, ParameterNode*, const Identifier&); + ParameterNode(PassRefPtr); + ParameterNode(ParameterNode*, PassRefPtr); - const Identifier& ident() const { return m_ident; } + DeconstructionPatternNode* pattern() const { return m_pattern.get(); } ParameterNode* nextParam() const { return m_next; } private: - Identifier m_ident; + RefPtr m_pattern; ParameterNode* m_next; }; - struct ScopeNodeData { - typedef DeclarationStacks::VarStack VarStack; - typedef DeclarationStacks::FunctionStack FunctionStack; - - ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, int numConstants); - - ParserArena m_arena; - VarStack m_varStack; - FunctionStack m_functionStack; - int m_numConstants; - StatementVector m_children; - - void mark(); - }; - class ScopeNode : public StatementNode, public ParserArenaRefCounted { public: typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNode(JSGlobalData*); - ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants); + ScopeNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, bool inStrictContext); + ScopeNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); + + using ParserArenaRefCounted::operator new; - void adoptData(std::auto_ptr data) + void destroyData() { - ASSERT(!data->m_arena.contains(this)); - ASSERT(!m_data); - m_data.adopt(data); + m_arena.reset(); + m_varStack.clear(); + m_functionStack.clear(); + m_statements = 0; + m_capturedVariables.clear(); } - ScopeNodeData* data() const { return m_data.get(); } - void destroyData() { m_data.clear(); } const SourceCode& source() const { return m_source; } - const UString& sourceURL() const { return m_source.provider()->url(); } - intptr_t sourceID() const { return m_source.provider()->asID(); } + const String& sourceURL() const { return m_source.provider()->url(); } + intptr_t sourceID() const { return m_source.providerID(); } + + int startLine() const { return m_startLineNumber; } + int startStartOffset() const { return m_startStartOffset; } + int startLineStartOffset() const { return m_startLineStartOffset; } void setFeatures(CodeFeatures features) { m_features = features; } CodeFeatures features() { return m_features; } bool usesEval() const { return m_features & EvalFeature; } - bool usesArguments() const { return m_features & ArgumentsFeature; } + bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); } + bool modifiesParameter() const { return m_features & ModifiedParameterFeature; } + bool isStrictMode() const { return m_features & StrictModeFeature; } void setUsesArguments() { m_features |= ArgumentsFeature; } bool usesThis() const { return m_features & ThisFeature; } - bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); } - - VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } - FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } + bool needsActivationForMoreThanVariables() const { return m_features & (EvalFeature | WithFeature | CatchFeature); } + bool needsActivation() const { return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); } + bool hasCapturedVariables() const { return !!m_capturedVariables.size(); } + size_t capturedVariableCount() const { return m_capturedVariables.size(); } + const IdentifierSet& capturedVariables() const { return m_capturedVariables; } + bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); } - StatementVector& children() { ASSERT(m_data); return m_data->m_children; } + VarStack& varStack() { return m_varStack; } + FunctionStack& functionStack() { return m_functionStack; } int neededConstants() { - ASSERT(m_data); // We may need 2 more constants than the count given by the parser, // because of the various uses of jsUndefined() and jsNull(). - return m_data->m_numConstants + 2; - } - - virtual void mark() { } - -#if ENABLE(JIT) - JITCode& generatedJITCode() - { - ASSERT(m_jitCode); - return m_jitCode; + return m_numConstants + 2; } - ExecutablePool* getExecutablePool() - { - return m_jitCode.getExecutablePool(); - } + StatementNode* singleStatement() const; - void setJITCode(const JITCode jitCode) - { - m_jitCode = jitCode; - } -#endif + void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination); + + void setClosedVariables(Vector>&&) { } protected: void setSource(const SourceCode& source) { m_source = source; } + ParserArena m_arena; -#if ENABLE(JIT) - JITCode m_jitCode; -#endif + int m_startLineNumber; + unsigned m_startStartOffset; + unsigned m_startLineStartOffset; private: - OwnPtr m_data; CodeFeatures m_features; SourceCode m_source; + VarStack m_varStack; + FunctionStack m_functionStack; + int m_numConstants; + SourceElements* m_statements; + IdentifierSet m_capturedVariables; }; class ProgramNode : public ScopeNode { public: - static PassRefPtr create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + static const bool isFunctionNode = false; + static PassRefPtr create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) - { - if (!m_code) - generateBytecode(scopeChain); - return *m_code; - } + unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } -#if ENABLE(JIT) - JITCode& jitCode(ScopeChainNode* scopeChain) - { - if (!m_jitCode) - generateJITCode(scopeChain); - return m_jitCode; - } -#endif + static const bool scopeIsFunction = false; + void setClosedVariables(Vector>&&); + const Vector>& closedVariables() const { return m_closedVariables; } private: - ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); - - void generateBytecode(ScopeChainNode*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + ProgramNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); -#if ENABLE(JIT) - void generateJITCode(ScopeChainNode*); -#endif - - OwnPtr m_code; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + Vector> m_closedVariables; + unsigned m_startColumn; + unsigned m_endColumn; }; class EvalNode : public ScopeNode { public: - static PassRefPtr create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + static const bool isFunctionNode = false; + static PassRefPtr create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) - { - if (!m_code) - generateBytecode(scopeChain); - return *m_code; - } + ALWAYS_INLINE unsigned startColumn() const { return 0; } + unsigned endColumn() const { return m_endColumn; } - EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*); + static const bool scopeIsFunction = false; - virtual void mark(); + private: + EvalNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); -#if ENABLE(JIT) - JITCode& jitCode(ScopeChainNode* scopeChain) - { - if (!m_jitCode) - generateJITCode(scopeChain); - return m_jitCode; - } -#endif + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + unsigned m_endColumn; + }; + + class FunctionParameters : public RefCounted { + WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(FunctionParameters); + public: + static PassRefPtr create(ParameterNode*); + ~FunctionParameters(); + + unsigned size() const { return m_size; } + DeconstructionPatternNode* at(unsigned index) { ASSERT(index < m_size); return patterns()[index]; } private: - EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + FunctionParameters(ParameterNode*, unsigned size); - void generateBytecode(ScopeChainNode*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + DeconstructionPatternNode** patterns() { return &m_storage; } -#if ENABLE(JIT) - void generateJITCode(ScopeChainNode*); -#endif - - OwnPtr m_code; + unsigned m_size; + DeconstructionPatternNode* m_storage; }; class FunctionBodyNode : public ScopeNode { - friend class JIT; public: -#if ENABLE(JIT) - static PassRefPtr createNativeThunk(JSGlobalData*); -#endif - static FunctionBodyNode* create(JSGlobalData*); - static PassRefPtr create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); - virtual ~FunctionBodyNode(); + static const bool isFunctionNode = true; + static FunctionBodyNode* create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, bool isStrictMode); + static PassRefPtr create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - const Identifier* parameters() const { return m_parameters; } - size_t parameterCount() const { return m_parameterCount; } - UString paramString() const ; - Identifier* copyParameters(); + FunctionParameters* parameters() const { return m_parameters.get(); } + size_t parameterCount() const { return m_parameters->size(); } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - bool isGenerated() const - { - return m_code; - } + void finishParsing(const SourceCode&, ParameterNode*, const Identifier&, FunctionMode); + void finishParsing(PassRefPtr, const Identifier&, FunctionMode); + + void overrideName(const Identifier& ident) { m_ident = ident; } + const Identifier& ident() { return m_ident; } + void setInferredName(const Identifier& inferredName) { ASSERT(!inferredName.isNull()); m_inferredName = inferredName; } + const Identifier& inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; } + + FunctionMode functionMode() { return m_functionMode; } + + void setFunctionNameStart(int functionNameStart) { m_functionNameStart = functionNameStart; } + int functionNameStart() const { return m_functionNameStart; } + unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } + + void setEndPosition(JSTextPosition); - bool isHostFunction() const; + static const bool scopeIsFunction = true; - virtual void mark(); + private: + FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, bool inStrictContext); + FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + Identifier m_ident; + Identifier m_inferredName; + FunctionMode m_functionMode; + RefPtr m_parameters; + int m_functionNameStart; + unsigned m_startColumn; + unsigned m_endColumn; + }; - void finishParsing(const SourceCode&, ParameterNode*); - void finishParsing(Identifier* parameters, size_t parameterCount); + class FuncExprNode : public ExpressionNode { + public: + FuncExprNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + + FunctionBodyNode* body() { return m_body; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + virtual bool isFuncExprNode() const override { return true; } + + FunctionBodyNode* m_body; + }; + + class DeconstructionPatternNode : public RefCounted { + WTF_MAKE_NONCOPYABLE(DeconstructionPatternNode); + WTF_MAKE_FAST_ALLOCATED; + + public: + virtual void collectBoundIdentifiers(Vector&) const = 0; + virtual void bindValue(BytecodeGenerator&, RegisterID* source) const = 0; + virtual void toString(StringBuilder&) const = 0; + + virtual bool isBindingNode() const { return false; } + virtual RegisterID* emitDirectBinding(BytecodeGenerator&, RegisterID*, ExpressionNode*) { return 0; } - UString toSourceString() const { return source().toString(); } + virtual ~DeconstructionPatternNode() = 0; + + protected: + DeconstructionPatternNode(VM*); + }; - CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*); -#if ENABLE(JIT) - JITCode& jitCode(ScopeChainNode* scopeChain) + class ArrayPatternNode : public DeconstructionPatternNode { + public: + static PassRefPtr create(VM*); + void appendIndex(const JSTokenLocation&, DeconstructionPatternNode* node) { - if (!m_jitCode) - generateJITCode(scopeChain); - return m_jitCode; + m_targetPatterns.append(node); } -#endif - CodeBlock& bytecode(ScopeChainNode* scopeChain) + private: + ArrayPatternNode(VM*); + virtual void collectBoundIdentifiers(Vector&) const override; + virtual void bindValue(BytecodeGenerator&, RegisterID*) const override; + virtual RegisterID* emitDirectBinding(BytecodeGenerator&, RegisterID* dst, ExpressionNode*) override; + virtual void toString(StringBuilder&) const override; + + Vector> m_targetPatterns; + }; + + class ObjectPatternNode : public DeconstructionPatternNode { + public: + static PassRefPtr create(VM*); + void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DeconstructionPatternNode* pattern) { - ASSERT(scopeChain); - if (!m_code) - generateBytecode(scopeChain); - return *m_code; + m_targetPatterns.append(Entry(identifier, wasString, pattern)); } - CodeBlock& generatedBytecode() - { - ASSERT(m_code); - return *m_code; - } + private: + ObjectPatternNode(VM*); + virtual void collectBoundIdentifiers(Vector&) const override; + virtual void bindValue(BytecodeGenerator&, RegisterID*) const override; + virtual void toString(StringBuilder&) const override; + struct Entry { + Entry(const Identifier& propertyName, bool wasString, DeconstructionPatternNode* pattern) + : propertyName(propertyName) + , wasString(wasString) + , pattern(pattern) + { + } + Identifier propertyName; + bool wasString; + RefPtr pattern; + }; + Vector m_targetPatterns; + }; + + class BindingNode : public DeconstructionPatternNode { + public: + static PassRefPtr create(VM*, const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end); + const Identifier& boundProperty() const { return m_boundProperty; } + + const JSTextPosition& divotStart() const { return m_divotStart; } + const JSTextPosition& divotEnd() const { return m_divotEnd; } private: - FunctionBodyNode(JSGlobalData*); - FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + BindingNode(VM*, const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end); + + virtual void collectBoundIdentifiers(Vector&) const override; + virtual void bindValue(BytecodeGenerator&, RegisterID*) const override; + virtual void toString(StringBuilder&) const override; + + virtual bool isBindingNode() const override { return true; } - void generateBytecode(ScopeChainNode*); -#if ENABLE(JIT) - void generateJITCode(ScopeChainNode*); -#endif - Identifier* m_parameters; - size_t m_parameterCount; - OwnPtr m_code; + JSTextPosition m_divotStart; + JSTextPosition m_divotEnd; + Identifier m_boundProperty; }; - class FuncExprNode : public ExpressionNode, public ParserArenaRefCounted { + class DeconstructingAssignmentNode : public ExpressionNode, public ParserArenaDeletable { public: - FuncExprNode(JSGlobalData*, const Identifier&, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0); - - JSFunction* makeFunction(ExecState*, ScopeChainNode*); - - FunctionBodyNode* body() { return m_body.get(); } + DeconstructingAssignmentNode(const JSTokenLocation&, PassRefPtr, ExpressionNode*); + DeconstructionPatternNode* bindings() { return m_bindings.get(); } + + using ParserArenaDeletable::operator new; private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isAssignmentLocation() const override { return true; } + virtual bool isDeconstructionNode() const override { return true; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isFuncExprNode() const { return true; } - - Identifier m_ident; - RefPtr m_body; + RefPtr m_bindings; + ExpressionNode* m_initializer; }; - class FuncDeclNode : public StatementNode, public ParserArenaRefCounted { + class FuncDeclNode : public StatementNode { public: - FuncDeclNode(JSGlobalData*, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + FuncDeclNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); - JSFunction* makeFunction(ExecState*, ScopeChainNode*); - - Identifier m_ident; - - FunctionBodyNode* body() { return m_body.get(); } + FunctionBodyNode* body() { return m_body; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - RefPtr m_body; + FunctionBodyNode* m_body; }; - class CaseClauseNode : public ParserArenaDeletable { + class CaseClauseNode : public ParserArenaFreeable { public: - CaseClauseNode(JSGlobalData*, ExpressionNode*); - CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements*); + CaseClauseNode(ExpressionNode*, SourceElements* = 0); ExpressionNode* expr() const { return m_expr; } - StatementVector& children() { return m_children; } + + void emitBytecode(BytecodeGenerator&, RegisterID* destination); private: ExpressionNode* m_expr; - StatementVector m_children; + SourceElements* m_statements; }; - class ClauseListNode : public ParserArenaDeletable { + class ClauseListNode : public ParserArenaFreeable { public: - ClauseListNode(JSGlobalData*, CaseClauseNode*); - ClauseListNode(JSGlobalData*, ClauseListNode*, CaseClauseNode*); + ClauseListNode(CaseClauseNode*); + ClauseListNode(ClauseListNode*, CaseClauseNode*); CaseClauseNode* getClause() const { return m_clause; } ClauseListNode* getNext() const { return m_next; } @@ -1664,14 +1723,15 @@ namespace JSC { ClauseListNode* m_next; }; - class CaseBlockNode : public ParserArenaDeletable { + class CaseBlockNode : public ParserArenaFreeable { public: - CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2); + CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2); - RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0); + void emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination); private: - SwitchInfo::SwitchType tryOptimizedSwitch(Vector& literalVector, int32_t& min_num, int32_t& max_num); + SwitchInfo::SwitchType tryTableSwitch(Vector& literalVector, int32_t& min_num, int32_t& max_num); + static const size_t s_tableSwitchMinimum = 3; ClauseListNode* m_list1; CaseClauseNode* m_defaultClause; ClauseListNode* m_list2; @@ -1679,10 +1739,10 @@ namespace JSC { class SwitchNode : public StatementNode { public: - SwitchNode(JSGlobalData*, ExpressionNode*, CaseBlockNode*); + SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; CaseBlockNode* m_block;