X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/93a3786624b2768d89bfa27e46598dc64e2fb70a..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/parser/Nodes.h diff --git a/parser/Nodes.h b/parser/Nodes.h index 2eeaae9..f29a510 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, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013, 2015 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel @@ -76,11 +76,11 @@ namespace JSC { }; inline FallThroughMode invert(FallThroughMode fallThroughMode) { return static_cast(!fallThroughMode); } - typedef HashSet, IdentifierRepHash> IdentifierSet; + typedef HashSet, IdentifierRepHash> IdentifierSet; namespace DeclarationStacks { enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; - typedef Vector > VarStack; + typedef Vector> VarStack; typedef Vector FunctionStack; } @@ -94,7 +94,7 @@ namespace JSC { 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*); + void* operator new(size_t, ParserArena&); }; class ParserArenaDeletable { @@ -103,23 +103,20 @@ namespace JSC { // ParserArenaDeletable objects are deleted when the arena is deleted. // Clients must not call delete directly on such objects. - void* operator new(size_t, VM*); + void* operator new(size_t, ParserArena&); }; - template - struct ParserArenaData : ParserArenaDeletable { - T data; - }; - - class ParserArenaRefCounted : public RefCounted { + class ParserArenaRoot { + WTF_MAKE_FAST_ALLOCATED; protected: - ParserArenaRefCounted(VM*); + ParserArenaRoot(ParserArena&); public: - virtual ~ParserArenaRefCounted() - { - ASSERT(deletionHasBegun()); - } + ParserArena& parserArena() { return m_arena; } + virtual ~ParserArenaRoot() { } + + protected: + ParserArena m_arena; }; class Node : public ParserArenaFreeable { @@ -129,14 +126,17 @@ namespace JSC { public: virtual ~Node() { } - int lineNo() const { return m_lineNumber; } - int startOffset() const { return m_startOffset; } - int lineStartOffset() const { return m_lineStartOffset; } + int firstLine() const { return m_position.line; } + int startOffset() const { return m_position.offset; } + int endOffset() const { return m_endOffset; } + int lineStartOffset() const { return m_position.lineStartOffset; } + const JSTextPosition& position() const { return m_position; } + void setEndOffset(int offset) { m_endOffset = offset; } + void setStartOffset(int offset) { m_position.offset = offset; } protected: - int m_lineNumber; - int m_startOffset; - int m_lineStartOffset; + JSTextPosition m_position; + int m_endOffset; }; class ExpressionNode : public Node { @@ -152,15 +152,19 @@ namespace JSC { 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 isDestructuringNode() 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 bool isSuperNode() const { return false; } virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, FallThroughMode); @@ -180,29 +184,33 @@ namespace JSC { virtual void emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset); - unsigned firstLine() const { return lineNo(); } unsigned lastLine() const { return m_lastLine; } + StatementNode* next() { return m_next; } + void setNext(StatementNode* next) { m_next = next; } + 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; } + virtual bool isFuncDeclNode() const { return false; } - private: + protected: + StatementNode* m_next; int m_lastLine; }; class ConstantNode : public ExpressionNode { public: ConstantNode(const JSTokenLocation&, ResultType); - virtual bool isPure(BytecodeGenerator&) const { return true; } - virtual bool isConstant() const { return true; } + 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); - void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; }; class NullNode : public ConstantNode { @@ -210,8 +218,8 @@ namespace JSC { NullNode(const JSTokenLocation&); private: - virtual bool isNull() const { return true; } - virtual JSValue jsValue(BytecodeGenerator&) const { return jsNull(); } + virtual bool isNull() const override { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNull(); } }; class BooleanNode : public ConstantNode { @@ -220,8 +228,8 @@ namespace JSC { bool value() { return m_value; } private: - virtual bool isBoolean() const { return true; } - virtual JSValue jsValue(BytecodeGenerator&) const { return jsBoolean(m_value); } + virtual bool isBoolean() const override { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override { return jsBoolean(m_value); } bool m_value; }; @@ -229,74 +237,84 @@ namespace JSC { class NumberNode : public ConstantNode { public: NumberNode(const JSTokenLocation&, double value); - double value() { return m_value; } - void setValue(double value) { m_value = value; } + double value() const { return m_value; } + virtual bool isIntegerNode() const = 0; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override final; private: - virtual bool isNumber() const { return true; } - virtual JSValue jsValue(BytecodeGenerator&) const { return jsNumber(m_value); } + virtual bool isNumber() const override final { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNumber(m_value); } double m_value; }; + class DoubleNode : public NumberNode { + public: + DoubleNode(const JSTokenLocation&, double value); + + private: + virtual bool isIntegerNode() const override { return false; } + }; + + // An integer node represent a number represented as an integer (e.g. 42 instead of 42., 42.0, 42e0) + class IntegerNode : public DoubleNode { + public: + IntegerNode(const JSTokenLocation&, double value); + virtual bool isIntegerNode() const override final { return true; } + }; + class StringNode : public ConstantNode { public: StringNode(const JSTokenLocation&, const Identifier&); const Identifier& value() { return m_value; } private: - virtual bool isString() const { return true; } - virtual JSValue jsValue(BytecodeGenerator&) const; + virtual bool isString() const override { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override; const Identifier& m_value; }; - + class ThrowableExpressionData { public: ThrowableExpressionData() - : m_divot(static_cast(-1)) - , m_divotStartOffset(static_cast(-1)) - , m_divotEndOffset(static_cast(-1)) - , m_divotLine(static_cast(-1)) - , m_divotLineStart(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, unsigned divotLine, unsigned divotLineStart) + ThrowableExpressionData(const JSTextPosition& divot, const JSTextPosition& start, const JSTextPosition& end) : m_divot(divot) - , m_divotStartOffset(startOffset) - , m_divotEndOffset(endOffset) - , m_divotLine(divotLine) - , m_divotLineStart(divotLineStart) + , m_divotStart(start) + , m_divotEnd(end) { - ASSERT(m_divot >= m_divotLineStart); + 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, unsigned divotLine, unsigned divotLineStart) + + void setExceptionSourceCode(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd) { - ASSERT(divot >= divotLineStart); + ASSERT(divot.offset >= divot.lineStartOffset); + ASSERT(divotStart.offset >= divotStart.lineStartOffset); + ASSERT(divotEnd.offset >= divotEnd.lineStartOffset); m_divot = divot; - m_divotStartOffset = startOffset; - m_divotEndOffset = endOffset; - m_divotLine = divotLine; - m_divotLineStart = divotLineStart; + m_divotStart = divotStart; + m_divotEnd = divotEnd; } - uint32_t divot() const { return m_divot; } - uint16_t divotStartOffset() const { return m_divotStartOffset; } - uint16_t divotEndOffset() const { return m_divotEndOffset; } - uint32_t divotLine() const { return m_divotLine; } - uint32_t divotLineStart() const { return m_divotLineStart; } + const JSTextPosition& divot() const { return m_divot; } + const JSTextPosition& divotStart() const { return m_divotStart; } + const JSTextPosition& divotEnd() const { return m_divotEnd; } protected: RegisterID* emitThrowReferenceError(BytecodeGenerator&, const String& message); private: - uint32_t m_divot; - uint16_t m_divotStartOffset; - uint16_t m_divotEndOffset; - uint32_t m_divotLine; - uint32_t m_divotLineStart; + JSTextPosition m_divot; + JSTextPosition m_divotStart; + JSTextPosition m_divotEnd; }; class ThrowableSubExpressionData : public ThrowableExpressionData { @@ -309,8 +327,8 @@ namespace JSC { { } - ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) - : ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) + ThrowableSubExpressionData(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd) + : ThrowableExpressionData(divot, divotStart, divotEnd) , m_subexpressionDivotOffset(0) , m_subexpressionEndOffset(0) , m_subexpressionLineOffset(0) @@ -318,28 +336,34 @@ namespace JSC { { } - void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset, uint32_t subexpressionLine, uint32_t subexpressionLineStart) + void setSubexpressionInfo(const JSTextPosition& subexpressionDivot, int subexpressionOffset) { - ASSERT(subexpressionDivot <= 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) & ~0xFFFF) + if ((divot() - subexpressionDivot.offset) & ~0xFFFF) return; - if ((divotLine() - subexpressionLine) & ~0xFFFF) + if ((divot().line - subexpressionDivot.line) & ~0xFFFF) return; - if ((divotLineStart() - subexpressionLineStart) & ~0xFFFF) + if ((divot().lineStartOffset - subexpressionDivot.lineStartOffset) & ~0xFFFF) return; - m_subexpressionDivotOffset = divot() - subexpressionDivot; - m_subexpressionEndOffset = subexpressionOffset; - m_subexpressionLineOffset = divotLine() - subexpressionLine; - m_subexpressionLineStartOffset = divotLineStart() - subexpressionLineStart; + if ((divotEnd() - subexpressionOffset) & ~0xFFFF) + return; + m_subexpressionDivotOffset = divot() - subexpressionDivot.offset; + m_subexpressionEndOffset = divotEnd() - subexpressionOffset; + m_subexpressionLineOffset = divot().line - subexpressionDivot.line; + m_subexpressionLineStartOffset = divot().lineStartOffset - subexpressionDivot.lineStartOffset; } - unsigned subexpressionDivot() { return divot() - m_subexpressionDivotOffset; } - unsigned subexpressionStartOffset() { return divotStartOffset() - m_subexpressionDivotOffset; } - unsigned subexpressionEndOffset() { return m_subexpressionEndOffset; } - unsigned subexpressionLine() { return divotLine() - m_subexpressionLineOffset; } - unsigned subexpressionLineStart() { return divotLineStart() - m_subexpressionLineStartOffset; } + 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; @@ -358,8 +382,8 @@ namespace JSC { { } - ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) - : ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) + ThrowablePrefixedSubExpressionData(const JSTextPosition& divot, const JSTextPosition& start, const JSTextPosition& end) + : ThrowableExpressionData(divot, start, end) , m_subexpressionDivotOffset(0) , m_subexpressionStartOffset(0) , m_subexpressionLineOffset(0) @@ -367,28 +391,34 @@ namespace JSC { { } - void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset, uint32_t subexpressionLine, uint32_t subexpressionLineStart) + void setSubexpressionInfo(const JSTextPosition& subexpressionDivot, int subexpressionOffset) { - ASSERT(subexpressionDivot >= 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 - divot()) & ~0xFFFF) + if ((subexpressionDivot.offset - divot()) & ~0xFFFF) + return; + if ((subexpressionDivot.line - divot().line) & ~0xFFFF) return; - if ((subexpressionLine - divotLine()) & ~0xFFFF) + if ((subexpressionDivot.lineStartOffset - divot().lineStartOffset) & ~0xFFFF) return; - if ((subexpressionLineStart - divotLineStart()) & ~0xFFFF) + if ((subexpressionOffset - divotStart()) & ~0xFFFF) return; - m_subexpressionDivotOffset = subexpressionDivot - divot(); - m_subexpressionStartOffset = subexpressionOffset; - m_subexpressionLineOffset = subexpressionLine - divotLine(); - m_subexpressionLineStartOffset = subexpressionLineStart - divotLineStart(); + m_subexpressionDivotOffset = subexpressionDivot.offset - divot(); + m_subexpressionStartOffset = subexpressionOffset - divotStart(); + m_subexpressionLineOffset = subexpressionDivot.line - divot().line; + m_subexpressionLineStartOffset = subexpressionDivot.lineStartOffset - divot().lineStartOffset; } - unsigned subexpressionDivot() { return divot() + m_subexpressionDivotOffset; } - unsigned subexpressionStartOffset() { return m_subexpressionStartOffset; } - unsigned subexpressionEndOffset() { return divotEndOffset() + m_subexpressionDivotOffset; } - unsigned subexpressionLine() { return divotLine() + m_subexpressionLineOffset; } - unsigned subexpressionLineStart() { return divotLineStart() + m_subexpressionLineStartOffset; } + 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; @@ -397,12 +427,82 @@ namespace JSC { uint16_t m_subexpressionLineStartOffset; }; +#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX) + class TemplateExpressionListNode : public ParserArenaFreeable { + public: + TemplateExpressionListNode(ExpressionNode*); + TemplateExpressionListNode(TemplateExpressionListNode*, ExpressionNode*); + + ExpressionNode* value() { return m_node; } + TemplateExpressionListNode* next() { return m_next; } + + private: + TemplateExpressionListNode* m_next { nullptr }; + ExpressionNode* m_node { nullptr }; + }; + + class TemplateStringNode : public ExpressionNode { + public: + TemplateStringNode(const JSTokenLocation&, const Identifier& cooked, const Identifier& raw); + + const Identifier& cooked() { return m_cooked; } + const Identifier& raw() { return m_raw; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_cooked; + const Identifier& m_raw; + }; + + class TemplateStringListNode : public ParserArenaFreeable { + public: + TemplateStringListNode(TemplateStringNode*); + TemplateStringListNode(TemplateStringListNode*, TemplateStringNode*); + + TemplateStringNode* value() { return m_node; } + TemplateStringListNode* next() { return m_next; } + + private: + TemplateStringListNode* m_next { nullptr }; + TemplateStringNode* m_node { nullptr }; + }; + + class TemplateLiteralNode : public ExpressionNode { + public: + TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*); + TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*, TemplateExpressionListNode*); + + TemplateStringListNode* templateStrings() const { return m_templateStrings; } + TemplateExpressionListNode* templateExpressions() const { return m_templateExpressions; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + TemplateStringListNode* m_templateStrings; + TemplateExpressionListNode* m_templateExpressions; + }; + + class TaggedTemplateNode : public ExpressionNode, public ThrowableExpressionData { + public: + TaggedTemplateNode(const JSTokenLocation&, ExpressionNode*, TemplateLiteralNode*); + + TemplateLiteralNode* templateLiteral() const { return m_templateLiteral; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_tag; + TemplateLiteralNode* m_templateLiteral; + }; +#endif + class RegExpNode : public ExpressionNode, public ThrowableExpressionData { public: RegExpNode(const JSTokenLocation&, const Identifier& pattern, const Identifier& flags); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_pattern; const Identifier& m_flags; @@ -410,29 +510,38 @@ namespace JSC { class ThisNode : public ExpressionNode { public: - ThisNode(const JSTokenLocation&); + ThisNode(const JSTokenLocation&, ThisTDZMode); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + bool m_shouldAlwaysEmitTDZCheck; + }; + + class SuperNode final : public ExpressionNode { + public: + SuperNode(const JSTokenLocation&); + + private: + virtual bool isSuperNode() const override { return true; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ResolveNode : public ExpressionNode { public: - ResolveNode(const JSTokenLocation&, const Identifier&, unsigned startOffset, unsigned divotLine, unsigned divotLineStart); + 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; } const Identifier& m_ident; - uint32_t m_startOffset; - uint32_t m_divotLine; - uint32_t m_divotLineStart; + JSTextPosition m_start; }; class ElementNode : public ParserArenaFreeable { @@ -456,12 +565,13 @@ namespace JSC { ArrayNode(const JSTokenLocation&, ElementNode*); ArrayNode(const JSTokenLocation&, int elision, ElementNode*); - ArgumentListNode* toArgumentList(VM*, int, int) const; + ArgumentListNode* toArgumentList(ParserArena&, 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; @@ -470,19 +580,27 @@ namespace JSC { class PropertyNode : public ParserArenaFreeable { public: - enum Type { Constant = 1, Getter = 2, Setter = 4 }; + enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16 }; + enum PutType { Unknown, KnownDirect }; + + PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding); + PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType); - PropertyNode(VM*, const Identifier&, ExpressionNode*, Type); - PropertyNode(VM*, double, 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; } + Type type() const { return static_cast(m_type); } + bool needsSuperBinding() const { return m_needsSuperBinding; } + PutType putType() const { return static_cast(m_putType); } private: friend class PropertyListNode; - const Identifier& m_name; + const Identifier* m_name; + ExpressionNode* m_expression; ExpressionNode* m_assign; - Type m_type; + unsigned m_type : 5; + unsigned m_needsSuperBinding : 1; + unsigned m_putType : 1; }; class PropertyListNode : public ExpressionNode { @@ -490,9 +608,10 @@ namespace JSC { PropertyListNode(const JSTokenLocation&, PropertyNode*); PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitPutConstantProperty(BytecodeGenerator&, RegisterID*, PropertyNode&); + PropertyNode* m_node; PropertyListNode* m_next; }; @@ -503,7 +622,7 @@ namespace JSC { ObjectLiteralNode(const JSTokenLocation&, PropertyListNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; PropertyListNode* m_list; }; @@ -518,10 +637,10 @@ namespace JSC { 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; @@ -536,15 +655,28 @@ namespace JSC { 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; const Identifier& m_ident; }; + class SpreadExpressionNode : public ExpressionNode, public ThrowableExpressionData { + public: + 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*); @@ -554,7 +686,7 @@ namespace JSC { ExpressionNode* m_expr; private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ArgumentsNode : public ParserArenaFreeable { @@ -571,7 +703,7 @@ namespace JSC { 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; @@ -579,20 +711,20 @@ namespace JSC { class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { public: - EvalFunctionCallNode(const JSTokenLocation&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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; @@ -600,10 +732,10 @@ namespace JSC { class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallResolveNode(const JSTokenLocation&, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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; const Identifier& m_ident; ArgumentsNode* m_args; @@ -611,22 +743,23 @@ namespace JSC { class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments, 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; ArgumentsNode* m_args; + bool m_subscriptHasAssignments; }; class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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; @@ -634,38 +767,58 @@ namespace JSC { ArgumentsNode* m_args; }; + class BytecodeIntrinsicNode : public ExpressionNode, public ThrowableExpressionData { + public: + typedef RegisterID* (BytecodeIntrinsicNode::* EmitterType)(BytecodeGenerator&, RegisterID*); + + BytecodeIntrinsicNode(const JSTokenLocation&, EmitterType, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); + + const Identifier& identifier() const { return m_ident; } + +#define JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS(name) RegisterID* emit_intrinsic_##name(BytecodeGenerator&, RegisterID*); + JSC_COMMON_BYTECODE_INTRINSICS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS) +#undef JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + EmitterType m_emitter; + const Identifier& m_ident; + ArgumentsNode* m_args; + }; + class CallFunctionCallDotNode : public FunctionCallDotNode { public: - CallFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + ApplyFunctionCallDotNode(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 DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteResolveNode(const JSTokenLocation&, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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; const Identifier& m_ident; }; class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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; @@ -673,10 +826,10 @@ namespace JSC { class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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; const Identifier& m_ident; @@ -687,7 +840,7 @@ namespace JSC { DeleteValueNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; @@ -697,7 +850,7 @@ namespace JSC { VoidNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; @@ -709,7 +862,7 @@ namespace JSC { const Identifier& identifier() const { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; }; @@ -719,17 +872,17 @@ namespace JSC { TypeOfValueNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; class PrefixNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { public: - PrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + PrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); protected: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + 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); @@ -740,13 +893,13 @@ namespace JSC { class PostfixNode : public PrefixNode { public: - PostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + PostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitDot(BytecodeGenerator&, RegisterID* = 0); + 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 { @@ -758,7 +911,7 @@ namespace JSC { 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; } @@ -771,7 +924,7 @@ namespace JSC { UnaryPlusNode(const JSTokenLocation&, ExpressionNode*); private: - virtual ExpressionNode* stripUnaryPlus() { return expr(); } + virtual ExpressionNode* stripUnaryPlus() override { return expr(); } }; class NegateNode : public UnaryOpNode { @@ -788,7 +941,7 @@ namespace JSC { const ExpressionNode* expr() const { return m_expr; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; @@ -797,7 +950,7 @@ namespace JSC { public: LogicalNotNode(const JSTokenLocation&, ExpressionNode*); private: - void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode); + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; }; class BinaryOpNode : public ExpressionNode { @@ -806,14 +959,14 @@ namespace JSC { BinaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); - void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode); + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; ExpressionNode* lhs() { return m_expr1; }; ExpressionNode* rhs() { return m_expr2; }; private: void tryFoldToBranch(BytecodeGenerator&, TriState& branchCondition, ExpressionNode*& branchExpression); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; protected: OpcodeID opcodeID() const { return m_opcodeID; } @@ -846,14 +999,14 @@ namespace JSC { public: 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(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual bool isSubtract() const { return true; } + virtual bool isSubtract() const override { return true; } }; class LeftShiftNode : public BinaryOpNode { @@ -897,7 +1050,7 @@ namespace JSC { 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 { @@ -905,7 +1058,7 @@ namespace JSC { 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 { @@ -918,7 +1071,7 @@ namespace JSC { 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 { @@ -931,7 +1084,7 @@ namespace JSC { 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 { @@ -960,8 +1113,8 @@ namespace JSC { LogicalOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; ExpressionNode* m_expr1; ExpressionNode* m_expr2; @@ -974,7 +1127,7 @@ namespace JSC { 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; @@ -983,10 +1136,10 @@ namespace JSC { class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - ReadModifyResolveNode(const JSTokenLocation&, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned line, unsigned lineStart); + 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; const Identifier& m_ident; ExpressionNode* m_right; @@ -999,7 +1152,7 @@ namespace JSC { AssignResolveNode(const JSTokenLocation&, const Identifier&, ExpressionNode* right); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; ExpressionNode* m_right; @@ -1007,25 +1160,25 @@ namespace JSC { class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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; @@ -1036,10 +1189,10 @@ namespace JSC { class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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; const Identifier& m_ident; @@ -1049,41 +1202,39 @@ namespace JSC { class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + 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; 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(const JSTokenLocation&, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + AssignErrorNode(const JSTokenLocation&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; - typedef Vector ExpressionVector; - - class CommaNode : public ExpressionNode, public ParserArenaDeletable { + class CommaNode final : public ExpressionNode { public: - CommaNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2); - - using ParserArenaDeletable::operator new; + CommaNode(const JSTokenLocation&, ExpressionNode*); - void append(ExpressionNode* expr) { m_expressions.append(expr); } + void setNext(CommaNode* next) { m_next = next; } + CommaNode* next() { return m_next; } 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; + ExpressionNode* m_expr; + CommaNode* m_next; }; class ConstDeclNode : public ExpressionNode { @@ -1094,7 +1245,7 @@ namespace JSC { const Identifier& ident() { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; virtual RegisterID* emitCodeSingle(BytecodeGenerator&); const Identifier& m_ident; @@ -1111,12 +1262,12 @@ namespace JSC { ConstStatementNode(const JSTokenLocation&, ConstDeclNode* next); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ConstDeclNode* m_next; }; - class SourceElements : public ParserArenaDeletable { + class SourceElements final : public ParserArenaFreeable { public: SourceElements(); @@ -1128,7 +1279,8 @@ namespace JSC { void emitBytecode(BytecodeGenerator&, RegisterID* destination); private: - Vector m_statements; + StatementNode* m_head; + StatementNode* m_tail; }; class BlockNode : public StatementNode { @@ -1139,9 +1291,9 @@ namespace JSC { StatementNode* lastStatement() const; private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isBlock() const { return true; } + virtual bool isBlock() const override { return true; } SourceElements* m_statements; }; @@ -1151,9 +1303,9 @@ namespace JSC { EmptyStatementNode(const JSTokenLocation&); private: - virtual void 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 { @@ -1161,7 +1313,7 @@ namespace JSC { DebuggerStatementNode(const JSTokenLocation&); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ExprStatementNode : public StatementNode { @@ -1171,9 +1323,9 @@ namespace JSC { ExpressionNode* expr() const { return m_expr; } private: - virtual bool isExprStatement() const { return true; } + virtual bool isExprStatement() const override { return true; } - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; @@ -1182,17 +1334,28 @@ namespace JSC { public: VarStatementNode(const JSTokenLocation&, ExpressionNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; + class EmptyVarExpression : public ExpressionNode { + public: + EmptyVarExpression(const JSTokenLocation&, const Identifier&); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_ident; + }; + + class IfElseNode : public StatementNode { public: IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; bool tryFoldBreakAndContinue(BytecodeGenerator&, StatementNode* ifBlock, Label*& trueTarget, FallThroughMode&); @@ -1206,7 +1369,7 @@ namespace JSC { DoWhileNode(const JSTokenLocation&, StatementNode*, ExpressionNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; StatementNode* m_statement; ExpressionNode* m_expr; @@ -1217,7 +1380,7 @@ namespace JSC { WhileNode(const JSTokenLocation&, ExpressionNode*, StatementNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; StatementNode* m_statement; @@ -1228,50 +1391,66 @@ namespace JSC { ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr1; ExpressionNode* m_expr2; ExpressionNode* m_expr3; StatementNode* m_statement; }; - - class ForInNode : public StatementNode, public ThrowableExpressionData { + + class DestructuringPatternNode; + + class EnumerationNode : public StatementNode, public ThrowableExpressionData { + public: + EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); + + protected: + ExpressionNode* m_lexpr; + ExpressionNode* m_expr; + StatementNode* m_statement; + }; + + class ForInNode : public EnumerationNode { public: ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); - ForInNode(VM*, const JSTokenLocation&, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, unsigned divot, int startOffset, int endOffset, unsigned divotLine, unsigned divotLineStart); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + RegisterID* tryGetBoundLocal(BytecodeGenerator&); + void emitLoopHeader(BytecodeGenerator&, RegisterID* propertyName); + void emitMultiLoopBytecode(BytecodeGenerator&, RegisterID* dst); - ExpressionNode* m_init; - ExpressionNode* m_lexpr; - ExpressionNode* m_expr; - StatementNode* m_statement; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + }; + + class ForOfNode : public EnumerationNode { + public: + ForOfNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); + + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ContinueNode : public StatementNode, public ThrowableExpressionData { public: - ContinueNode(VM*, const JSTokenLocation&); ContinueNode(const JSTokenLocation&, const Identifier&); Label* trivialTarget(BytecodeGenerator&); private: - virtual bool isContinue() const { return true; } - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isContinue() const override { return true; } + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; }; class BreakNode : public StatementNode, public ThrowableExpressionData { public: - BreakNode(VM*, const JSTokenLocation&); BreakNode(const JSTokenLocation&, const Identifier&); Label* trivialTarget(BytecodeGenerator&); private: - virtual bool isBreak() const { return true; } - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isBreak() const override { return true; } + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; }; @@ -1283,25 +1462,23 @@ namespace JSC { ExpressionNode* value() { return m_value; } private: - virtual void 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(const JSTokenLocation&, ExpressionNode*, StatementNode*, uint32_t divot, unsigned divotLine, unsigned divotLineStart, uint32_t expressionLength); + WithNode(const JSTokenLocation&, ExpressionNode*, StatementNode*, const JSTextPosition& divot, uint32_t expressionLength); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; StatementNode* m_statement; - uint32_t m_divot; - uint32_t m_divotLine; - uint32_t m_divotLineStart; + JSTextPosition m_divot; uint32_t m_expressionLength; }; @@ -1310,7 +1487,7 @@ namespace JSC { LabelNode(const JSTokenLocation&, const Identifier& name, StatementNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_name; StatementNode* m_statement; @@ -1321,7 +1498,7 @@ namespace JSC { ThrowNode(const JSTokenLocation&, ExpressionNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; @@ -1331,45 +1508,36 @@ namespace JSC { TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; StatementNode* m_tryBlock; - const Identifier& m_exceptionIdent; + const Identifier& m_thrownValueIdent; StatementNode* m_catchBlock; StatementNode* m_finallyBlock; }; - class ParameterNode : public ParserArenaFreeable { + class ParameterNode : public ParserArenaDeletable { public: - ParameterNode(const Identifier&); - ParameterNode(ParameterNode*, const Identifier&); + ParameterNode(PassRefPtr); + ParameterNode(ParameterNode*, PassRefPtr); - const Identifier& ident() const { return m_ident; } + DestructuringPatternNode* pattern() const { return m_pattern.get(); } ParameterNode* nextParam() const { return m_next; } private: - const Identifier& m_ident; + RefPtr m_pattern; ParameterNode* m_next; }; - class ScopeNode : public StatementNode, public ParserArenaRefCounted { + class ScopeNode : public StatementNode, public ParserArenaRoot { public: typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - 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); + ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, bool inStrictContext); + ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VarStack&, FunctionStack&, IdentifierSet&, CodeFeatures, int numConstants); - using ParserArenaRefCounted::operator new; - - void destroyData() - { - m_arena.reset(); - m_varStack.clear(); - m_functionStack.clear(); - m_statements = 0; - m_capturedVariables.clear(); - } + using ParserArenaRoot::operator new; const SourceCode& source() const { return m_source; } const String& sourceURL() const { return m_source.provider()->url(); } @@ -1384,6 +1552,8 @@ namespace JSC { bool usesEval() const { return m_features & EvalFeature; } bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); } + bool modifiesParameter() const { return m_features & ModifiedParameterFeature; } + bool modifiesArguments() const { return m_features & (EvalFeature | ModifiedArgumentsFeature); } bool isStrictMode() const { return m_features & StrictModeFeature; } void setUsesArguments() { m_features |= ArgumentsFeature; } bool usesThis() const { return m_features & ThisFeature; } @@ -1391,7 +1561,9 @@ namespace JSC { 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(); } - bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); } + const IdentifierSet& capturedVariables() const { return m_capturedVariables; } + bool captures(UniquedStringImpl* uid) { return m_capturedVariables.contains(uid); } + bool captures(const Identifier& ident) { return captures(ident.impl()); } VarStack& varStack() { return m_varStack; } FunctionStack& functionStack() { return m_functionStack; } @@ -1406,11 +1578,10 @@ namespace JSC { StatementNode* singleStatement() const; void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination); + + void setClosedVariables(Vector>&&) { } protected: - void setSource(const SourceCode& source) { m_source = source; } - ParserArena m_arena; - int m_startLineNumber; unsigned m_startStartOffset; unsigned m_startLineStartOffset; @@ -1427,92 +1598,135 @@ namespace JSC { class ProgramNode : public ScopeNode { public: - static const bool isFunctionNode = false; - static PassRefPtr create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack&, FunctionStack&, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - unsigned startColumn() { return m_startColumn; } + unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } static const bool scopeIsFunction = false; - private: - ProgramNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + void setClosedVariables(Vector>&&); + const Vector>& closedVariables() const { return m_closedVariables; } + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + Vector> m_closedVariables; unsigned m_startColumn; + unsigned m_endColumn; }; class EvalNode : public ScopeNode { public: - static const bool isFunctionNode = false; - static PassRefPtr create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack&, FunctionStack&, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - unsigned startColumn() { return 1; } + ALWAYS_INLINE unsigned startColumn() const { return 0; } + unsigned endColumn() const { return m_endColumn; } static const bool scopeIsFunction = false; private: - EvalNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + unsigned m_endColumn; }; class FunctionParameters : public RefCounted { WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(FunctionParameters); public: - static PassRefPtr create(ParameterNode*); + static Ref create(ParameterNode*); ~FunctionParameters(); unsigned size() const { return m_size; } - const Identifier& at(unsigned index) const { ASSERT(index < m_size); return identifiers()[index]; } + DestructuringPatternNode* at(unsigned index) { ASSERT(index < m_size); return patterns()[index]; } private: FunctionParameters(ParameterNode*, unsigned size); - Identifier* identifiers() { return reinterpret_cast(&m_storage); } - const Identifier* identifiers() const { return reinterpret_cast(&m_storage); } + DestructuringPatternNode** patterns() { return &m_storage; } unsigned m_size; - void* m_storage; + DestructuringPatternNode* m_storage; }; - class FunctionBodyNode : public ScopeNode { + class FunctionBodyNode final : public StatementNode, public ParserArenaDeletable { public: - static const bool isFunctionNode = true; - static FunctionBodyNode* create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, bool isStrictMode); - static PassRefPtr create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + using ParserArenaDeletable::operator new; + + FunctionBodyNode( + ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, + unsigned startColumn, unsigned endColumn, int functionKeywordStart, + int functionNameStart, int parametersStart, bool isInStrictContext, + ConstructorKind); FunctionParameters* parameters() const { return m_parameters.get(); } - size_t parameterCount() const { return m_parameters->size(); } - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - void finishParsing(const SourceCode&, ParameterNode*, const Identifier&, FunctionNameIsInScopeToggle); - void finishParsing(PassRefPtr, const Identifier&, FunctionNameIsInScopeToggle); + void finishParsing(const SourceCode&, ParameterNode*, 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; } - bool functionNameIsInScope() { return m_functionNameIsInScopeToggle == FunctionNameIsInScope; } - FunctionNameIsInScopeToggle functionNameIsInScopeToggle() { return m_functionNameIsInScopeToggle; } + FunctionMode functionMode() { return m_functionMode; } - void setFunctionStart(int functionStart) { m_functionStart = functionStart; } - int functionStart() const { return m_functionStart; } + int functionNameStart() const { return m_functionNameStart; } + int functionKeywordStart() const { return m_functionKeywordStart; } + int parametersStart() const { return m_parametersStart; } unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } - static const bool scopeIsFunction = true; + void setEndPosition(JSTextPosition); - private: - FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, bool inStrictContext); - FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + const SourceCode& source() const { return m_source; } + int startStartOffset() const { return m_startStartOffset; } + bool isInStrictContext() const { return m_isInStrictContext; } + ConstructorKind constructorKind() { return static_cast(m_constructorKind); } + + protected: Identifier m_ident; Identifier m_inferredName; - FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle; + FunctionMode m_functionMode; + RefPtr m_parameters; + unsigned m_startColumn; + unsigned m_endColumn; + int m_functionKeywordStart; + int m_functionNameStart; + int m_parametersStart; + SourceCode m_source; + int m_startStartOffset; + unsigned m_isInStrictContext : 1; + unsigned m_constructorKind : 2; + }; + + class FunctionNode final : public ScopeNode { + public: + FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack&, FunctionStack&, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + FunctionParameters* parameters() const { return m_parameters.get(); } + + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + void finishParsing(PassRefPtr, const Identifier&, FunctionMode); + + const Identifier& ident() { return m_ident; } + + FunctionMode functionMode() { return m_functionMode; } + + unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } + + static const bool scopeIsFunction = true; + + private: + Identifier m_ident; + FunctionMode m_functionMode; RefPtr m_parameters; - int m_functionStart; unsigned m_startColumn; + unsigned m_endColumn; }; class FuncExprNode : public ExpressionNode { @@ -1522,25 +1736,164 @@ namespace JSC { FunctionBodyNode* body() { return m_body; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isFuncExprNode() const { return true; } + virtual bool isFuncExprNode() const override { return true; } FunctionBodyNode* m_body; }; +#if ENABLE(ES6_CLASS_SYNTAX) + class ClassExprNode final : public ExpressionNode { + public: + ClassExprNode(const JSTokenLocation&, const Identifier&, ExpressionNode* constructorExpresssion, + ExpressionNode* parentClass, PropertyListNode* instanceMethods, PropertyListNode* staticMethods); + + const Identifier& name() { return m_name; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_name; + ExpressionNode* m_constructorExpression; + ExpressionNode* m_classHeritage; + PropertyListNode* m_instanceMethods; + PropertyListNode* m_staticMethods; + }; +#endif + + class DestructuringPatternNode : public RefCounted { + WTF_MAKE_NONCOPYABLE(DestructuringPatternNode); + 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; } + + virtual ~DestructuringPatternNode() = 0; + + protected: + DestructuringPatternNode(); + }; + + class ArrayPatternNode : public DestructuringPatternNode, public ThrowableExpressionData { + public: + enum class BindingType { + Elision, + Element, + RestElement + }; + + static Ref create(); + void appendIndex(BindingType bindingType, const JSTokenLocation&, DestructuringPatternNode* node, ExpressionNode* defaultValue) + { + m_targetPatterns.append({ bindingType, node, defaultValue }); + } + + private: + struct Entry { + BindingType bindingType; + RefPtr pattern; + ExpressionNode* defaultValue; + }; + ArrayPatternNode(); + 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 DestructuringPatternNode { + public: + static Ref create(); + void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue) + { + m_targetPatterns.append(Entry{ identifier, wasString, pattern, defaultValue }); + } + + private: + ObjectPatternNode(); + virtual void collectBoundIdentifiers(Vector&) const override; + virtual void bindValue(BytecodeGenerator&, RegisterID*) const override; + virtual void toString(StringBuilder&) const override; + struct Entry { + Identifier propertyName; + bool wasString; + RefPtr pattern; + ExpressionNode* defaultValue; + }; + Vector m_targetPatterns; + }; + + class BindingNode : public DestructuringPatternNode { + public: + static Ref create(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: + BindingNode(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; } + + JSTextPosition m_divotStart; + JSTextPosition m_divotEnd; + Identifier m_boundProperty; + }; + + class DestructuringAssignmentNode : public ExpressionNode, public ParserArenaDeletable { + public: + DestructuringAssignmentNode(const JSTokenLocation&, PassRefPtr, ExpressionNode*); + DestructuringPatternNode* bindings() { return m_bindings.get(); } + + using ParserArenaDeletable::operator new; + + private: + virtual bool isAssignmentLocation() const override { return true; } + virtual bool isDestructuringNode() const override { return true; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + RefPtr m_bindings; + ExpressionNode* m_initializer; + }; + class FuncDeclNode : public StatementNode { public: FuncDeclNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + virtual bool isFuncDeclNode() const override { return true; } FunctionBodyNode* body() { return m_body; } private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; FunctionBodyNode* m_body; }; +#if ENABLE(ES6_CLASS_SYNTAX) + class ClassDeclNode final : public StatementNode { + public: + ClassDeclNode(const JSTokenLocation&, ExpressionNode* classExpression); + + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_classDeclaration; + }; +#endif + class CaseClauseNode : public ParserArenaFreeable { public: CaseClauseNode(ExpressionNode*, SourceElements* = 0); @@ -1548,10 +1901,12 @@ namespace JSC { ExpressionNode* expr() const { return m_expr; } void emitBytecode(BytecodeGenerator&, RegisterID* destination); + void setStartOffset(int offset) { m_startOffset = offset; } private: ExpressionNode* m_expr; SourceElements* m_statements; + int m_startOffset; }; class ClauseListNode : public ParserArenaFreeable { @@ -1575,7 +1930,7 @@ namespace JSC { private: SwitchInfo::SwitchType tryTableSwitch(Vector& literalVector, int32_t& min_num, int32_t& max_num); - static const size_t s_tableSwitchMinimum = 10; + static const size_t s_tableSwitchMinimum = 3; ClauseListNode* m_list1; CaseClauseNode* m_defaultClause; ClauseListNode* m_list2; @@ -1586,7 +1941,7 @@ namespace JSC { SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; CaseBlockNode* m_block;