X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/9dae56ea45a0f5f8136a5c93d6f3a7f99399ca73..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/parser/Nodes.h diff --git a/parser/Nodes.h b/parser/Nodes.h index 2496a4f..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 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 @@ -23,48 +23,30 @@ * */ -#ifndef NODES_H_ -#define NODES_H_ +#ifndef Nodes_h +#define Nodes_h #include "Error.h" +#include "JITCode.h" #include "Opcode.h" +#include "ParserArena.h" +#include "ParserTokens.h" #include "ResultType.h" #include "SourceCode.h" #include "SymbolTable.h" #include -#include -#include - -#if PLATFORM(X86) && COMPILER(GCC) -#define JSC_FAST_CALL __attribute__((regparm(3))) -#else -#define JSC_FAST_CALL -#endif namespace JSC { - class CodeBlock; + class ArgumentListNode; class BytecodeGenerator; - class FuncDeclNode; - class EvalCodeBlock; - class JSFunction; - class NodeReleaser; - 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, @@ -88,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 { @@ -100,2293 +90,1861 @@ namespace JSC { SwitchType switchType; }; - class ParserRefCounted : Noncopyable { - protected: - ParserRefCounted(JSGlobalData*) JSC_FAST_CALL; - + class ParserArenaFreeable { public: - virtual ~ParserRefCounted(); - - // Nonrecursive destruction. - virtual void releaseNodes(NodeReleaser&); - - void ref() JSC_FAST_CALL; - void deref() JSC_FAST_CALL; - bool hasOneRef() JSC_FAST_CALL; - - static void deleteNewObjects(JSGlobalData*) JSC_FAST_CALL; - - private: - JSGlobalData* m_globalData; + // 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, ParserArena&); }; - class Node : public ParserRefCounted { + class ParserArenaDeletable { public: - Node(JSGlobalData*) JSC_FAST_CALL; + virtual ~ParserArenaDeletable() { } + + // ParserArenaDeletable objects are deleted when the arena is deleted. + // Clients must not call delete directly on such objects. + void* operator new(size_t, ParserArena&); + }; - /* - 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. + class ParserArenaRoot { + WTF_MAKE_FAST_ALLOCATED; + protected: + ParserArenaRoot(ParserArena&); - dst provides for a crude form of copy propagation. For example, + public: + ParserArena& parserArena() { return m_arena; } + virtual ~ParserArenaRoot() { } - x = 1 + protected: + ParserArena m_arena; + }; - becomes - - load r[x], 1 - - instead of + class Node : public ParserArenaFreeable { + protected: + Node(const JSTokenLocation&); - 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) JSC_FAST_CALL = 0; + public: + virtual ~Node() { } - int lineNo() const { return m_line; } + 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_line; + JSTextPosition m_position; + int m_endOffset; }; class ExpressionNode : public Node { - public: - ExpressionNode(JSGlobalData* globalData, ResultType resultDesc = ResultType::unknownType()) JSC_FAST_CALL - : Node(globalData) - , m_resultDesc(resultDesc) - { - } - - virtual bool isNumber() const JSC_FAST_CALL { return false; } - virtual bool isString() const JSC_FAST_CALL { return false; } - virtual bool isNull() const JSC_FAST_CALL { return false; } - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return false; } - virtual bool isLocation() const JSC_FAST_CALL { return false; } - virtual bool isResolveNode() const JSC_FAST_CALL { return false; } - virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return false; } - virtual bool isDotAccessorNode() const JSC_FAST_CALL { return false; } - virtual bool isFuncExprNode() const JSC_FAST_CALL { return false; } + protected: + ExpressionNode(const JSTokenLocation&, ResultType = ResultType::unknownType()); + + public: + 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 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); virtual ExpressionNode* stripUnaryPlus() { return this; } - ResultType resultDescriptor() const JSC_FAST_CALL { return m_resultDesc; } - - // This needs to be in public in order to compile using GCC 3.x - typedef enum { EvalOperator, FunctionCall } CallerType; + ResultType resultDescriptor() const { return m_resultType; } private: - ResultType m_resultDesc; + ResultType m_resultType; }; class StatementNode : public Node { + protected: + StatementNode(const JSTokenLocation&); + public: - StatementNode(JSGlobalData*) JSC_FAST_CALL; - void setLoc(int line0, int line1) JSC_FAST_CALL; - int firstLine() const JSC_FAST_CALL { return lineNo(); } - int lastLine() const JSC_FAST_CALL { return m_lastLine; } + virtual void emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; - virtual bool isEmptyStatement() const JSC_FAST_CALL { return false; } - virtual bool isReturnNode() const JSC_FAST_CALL { return false; } - virtual bool isExprStatement() const JSC_FAST_CALL { return false; } + void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset); + unsigned lastLine() const { return m_lastLine; } - virtual bool isBlock() const JSC_FAST_CALL { return false; } - virtual bool isLoop() const JSC_FAST_CALL { return false; } + StatementNode* next() { return m_next; } + void setNext(StatementNode* next) { m_next = next; } - private: + 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; } + + protected: + StatementNode* m_next; int m_lastLine; }; - class NullNode : public ExpressionNode { + class ConstantNode : public ExpressionNode { public: - NullNode(JSGlobalData* globalData) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::nullType()) - { - } - - virtual bool isNull() const JSC_FAST_CALL { return true; } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + 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) override; + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; }; - class BooleanNode : public ExpressionNode { + class NullNode : public ConstantNode { public: - BooleanNode(JSGlobalData* globalData, bool value) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::booleanType()) - , m_value(value) - { - } + NullNode(const JSTokenLocation&); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual bool isNull() const override { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNull(); } + }; - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { 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* globalData, double v) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::numberType()) - , m_double(v) - { - } + NumberNode(const JSTokenLocation&, double 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 override final { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNumber(m_value); } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + double m_value; + }; - virtual bool isNumber() const JSC_FAST_CALL { return true; } - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } - double value() const JSC_FAST_CALL { return m_double; } - void setValue(double d) JSC_FAST_CALL { m_double = d; } + class DoubleNode : public NumberNode { + public: + DoubleNode(const JSTokenLocation&, double value); private: - double m_double; + virtual bool isIntegerNode() const override { return false; } }; - class StringNode : public ExpressionNode { + // An integer node represent a number represented as an integer (e.g. 42 instead of 42., 42.0, 42e0) + class IntegerNode : public DoubleNode { public: - StringNode(JSGlobalData* globalData, const Identifier& v) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::stringType()) - , m_value(v) - { - } + IntegerNode(const JSTokenLocation&, double value); + virtual bool isIntegerNode() const override final { return true; } + }; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual bool isString() const JSC_FAST_CALL { return true; } + class StringNode : public ConstantNode { + public: + StringNode(const JSTokenLocation&, const Identifier&); const Identifier& value() { return m_value; } - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } private: - Identifier m_value; + 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_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 { +#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX) + class TemplateExpressionListNode : public ParserArenaFreeable { public: - RegExpNode(JSGlobalData* globalData, const UString& pattern, const UString& flags) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_pattern(pattern) - , m_flags(flags) - { - } + TemplateExpressionListNode(ExpressionNode*); + TemplateExpressionListNode(TemplateExpressionListNode*, ExpressionNode*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ExpressionNode* value() { return m_node; } + TemplateExpressionListNode* next() { return m_next; } private: - UString m_pattern; - UString m_flags; + TemplateExpressionListNode* m_next { nullptr }; + ExpressionNode* m_node { nullptr }; }; - class ThisNode : public ExpressionNode { + class TemplateStringNode : public ExpressionNode { public: - ThisNode(JSGlobalData* globalData) JSC_FAST_CALL - : ExpressionNode(globalData) - { - } + TemplateStringNode(const JSTokenLocation&, const Identifier& cooked, const Identifier& raw); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + 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 ResolveNode : public ExpressionNode { + class TemplateStringListNode : public ParserArenaFreeable { public: - ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_ident(ident) - , m_startOffset(startOffset) - { - } + TemplateStringListNode(TemplateStringNode*); + TemplateStringListNode(TemplateStringListNode*, TemplateStringNode*); + + TemplateStringNode* value() { return m_node; } + TemplateStringListNode* next() { return m_next; } + + private: + TemplateStringListNode* m_next { nullptr }; + TemplateStringNode* m_node { nullptr }; + }; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + class TemplateLiteralNode : public ExpressionNode { + public: + TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*); + TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*, TemplateExpressionListNode*); - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL; - virtual bool isLocation() const JSC_FAST_CALL { return true; } - virtual bool isResolveNode() const JSC_FAST_CALL { return true; } - const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } + TemplateStringListNode* templateStrings() const { return m_templateStrings; } + TemplateExpressionListNode* templateExpressions() const { return m_templateExpressions; } private: - Identifier m_ident; - int32_t m_startOffset; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + TemplateStringListNode* m_templateStrings; + TemplateExpressionListNode* m_templateExpressions; }; - class ElementNode : public ParserRefCounted { + class TaggedTemplateNode : public ExpressionNode, public ThrowableExpressionData { public: - ElementNode(JSGlobalData* globalData, int elision, ExpressionNode* node) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_elision(elision) - , m_node(node) - { - } + TaggedTemplateNode(const JSTokenLocation&, ExpressionNode*, TemplateLiteralNode*); - ElementNode(JSGlobalData* globalData, ElementNode* l, int elision, ExpressionNode* node) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_elision(elision) - , m_node(node) - { - l->m_next = this; - } + TemplateLiteralNode* templateLiteral() const { return m_templateLiteral; } - virtual ~ElementNode(); - virtual void releaseNodes(NodeReleaser&); + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - int elision() const { return m_elision; } - ExpressionNode* value() { return m_node.get(); } + ExpressionNode* m_tag; + TemplateLiteralNode* m_templateLiteral; + }; +#endif - ElementNode* next() { return m_next.get(); } + class RegExpNode : public ExpressionNode, public ThrowableExpressionData { + public: + RegExpNode(const JSTokenLocation&, const Identifier& pattern, const Identifier& flags); private: - RefPtr m_next; - int m_elision; - RefPtr m_node; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_pattern; + const Identifier& m_flags; }; - class ArrayNode : public ExpressionNode { + class ThisNode : public ExpressionNode { public: - ArrayNode(JSGlobalData* globalData, int elision) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_elision(elision) - , m_optional(true) - { - } + ThisNode(const JSTokenLocation&, ThisTDZMode); - ArrayNode(JSGlobalData* globalData, ElementNode* element) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_element(element) - , m_elision(0) - , m_optional(false) - { - } + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_element(element) - , m_elision(elision) - , m_optional(true) - { - } + 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; + }; - virtual ~ArrayNode(); - virtual void releaseNodes(NodeReleaser&); + class ResolveNode : public ExpressionNode { + public: + ResolveNode(const JSTokenLocation&, const Identifier&, const JSTextPosition& start); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + const Identifier& identifier() const { return m_ident; } private: - RefPtr m_element; - int m_elision; - bool m_optional; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + virtual bool isPure(BytecodeGenerator&) const override; + virtual bool isLocation() const override { return true; } + virtual bool isResolveNode() const override { return true; } + + const Identifier& m_ident; + JSTextPosition m_start; }; - class PropertyNode : public ParserRefCounted { + class ElementNode : public ParserArenaFreeable { public: - enum Type { Constant, Getter, Setter }; + ElementNode(int elision, ExpressionNode*); + ElementNode(ElementNode*, int elision, ExpressionNode*); - PropertyNode(JSGlobalData* globalData, const Identifier& name, ExpressionNode* assign, Type type) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_name(name) - , m_assign(assign) - , m_type(type) - { - } + int elision() const { return m_elision; } + ExpressionNode* value() { return m_node; } + ElementNode* next() { return m_next; } + + private: + ElementNode* m_next; + int m_elision; + ExpressionNode* m_node; + }; - virtual ~PropertyNode(); - virtual void releaseNodes(NodeReleaser&); + class ArrayNode : public ExpressionNode { + public: + ArrayNode(const JSTokenLocation&, int elision); + ArrayNode(const JSTokenLocation&, ElementNode*); + ArrayNode(const JSTokenLocation&, int elision, ElementNode*); - const Identifier& name() const { return m_name; } + ArgumentListNode* toArgumentList(ParserArena&, int, int) const; + ElementNode* elements() const { ASSERT(isSimpleArray()); return m_element; } private: - friend class PropertyListNode; - Identifier m_name; - RefPtr m_assign; - Type m_type; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + virtual bool isSimpleArray() const override; + + ElementNode* m_element; + int m_elision; + bool m_optional; }; - class PropertyListNode : public Node { + class PropertyNode : public ParserArenaFreeable { public: - PropertyListNode(JSGlobalData* globalData, PropertyNode* node) JSC_FAST_CALL - : Node(globalData) - , m_node(node) - { - } + enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16 }; + enum PutType { Unknown, KnownDirect }; - PropertyListNode(JSGlobalData* globalData, PropertyNode* node, PropertyListNode* list) JSC_FAST_CALL - : Node(globalData) - , m_node(node) - { - list->m_next = this; - } + PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding); + PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType); - virtual ~PropertyListNode(); - virtual void releaseNodes(NodeReleaser&); + ExpressionNode* expressionName() const { return m_expression; } + const Identifier* name() const { return m_name; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + Type type() const { return static_cast(m_type); } + bool needsSuperBinding() const { return m_needsSuperBinding; } + PutType putType() const { return static_cast(m_putType); } private: - RefPtr m_node; - RefPtr m_next; + friend class PropertyListNode; + const Identifier* m_name; + ExpressionNode* m_expression; + ExpressionNode* m_assign; + unsigned m_type : 5; + unsigned m_needsSuperBinding : 1; + unsigned m_putType : 1; }; - class ObjectLiteralNode : public ExpressionNode { + class PropertyListNode : public ExpressionNode { public: - ObjectLiteralNode(JSGlobalData* globalData) JSC_FAST_CALL - : ExpressionNode(globalData) - { - } + PropertyListNode(const JSTokenLocation&, PropertyNode*); + PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*); - ObjectLiteralNode(JSGlobalData* globalData, PropertyListNode* list) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_list(list) - { - } + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitPutConstantProperty(BytecodeGenerator&, RegisterID*, PropertyNode&); - virtual ~ObjectLiteralNode(); - virtual void releaseNodes(NodeReleaser&); + PropertyNode* m_node; + PropertyListNode* m_next; + }; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + class ObjectLiteralNode : public ExpressionNode { + public: + ObjectLiteralNode(const JSTokenLocation&); + ObjectLiteralNode(const JSTokenLocation&, PropertyListNode*); private: - RefPtr m_list; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + PropertyListNode* m_list; }; class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData { public: - BracketAccessorNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_base(base) - , m_subscript(subscript) - , m_subscriptHasAssignments(subscriptHasAssignments) - { - } - - virtual ~BracketAccessorNode(); - virtual void releaseNodes(NodeReleaser&); + BracketAccessorNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ExpressionNode* base() const { return m_base; } + ExpressionNode* subscript() const { return m_subscript; } - virtual bool isLocation() const JSC_FAST_CALL { return true; } - virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return true; } - ExpressionNode* base() JSC_FAST_CALL { return m_base.get(); } - ExpressionNode* subscript() JSC_FAST_CALL { return m_subscript.get(); } + bool subscriptHasAssignments() const { return m_subscriptHasAssignments; } private: - RefPtr m_base; - RefPtr m_subscript; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + virtual bool isLocation() const override { return true; } + virtual bool isBracketAccessorNode() const override { return true; } + + ExpressionNode* m_base; + ExpressionNode* m_subscript; bool m_subscriptHasAssignments; }; class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData { public: - DotAccessorNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_base(base) - , m_ident(ident) - { - } + DotAccessorNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&); - virtual ~DotAccessorNode(); - virtual void releaseNodes(NodeReleaser&); + ExpressionNode* base() const { return m_base; } + const Identifier& identifier() const { return m_ident; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isLocation() const JSC_FAST_CALL { return true; } - virtual bool isDotAccessorNode() const JSC_FAST_CALL { return true; } - ExpressionNode* base() const JSC_FAST_CALL { return m_base.get(); } - const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } + virtual bool isLocation() const override { return true; } + virtual bool isDotAccessorNode() const override { return true; } - private: - RefPtr m_base; - Identifier m_ident; + ExpressionNode* m_base; + const Identifier& m_ident; }; - class ArgumentListNode : public Node { + class SpreadExpressionNode : public ExpressionNode, public ThrowableExpressionData { public: - ArgumentListNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : Node(globalData) - , m_expr(expr) - { - } - - ArgumentListNode(JSGlobalData* globalData, ArgumentListNode* listNode, ExpressionNode* expr) JSC_FAST_CALL - : Node(globalData) - , m_expr(expr) - { - listNode->m_next = this; - } + 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; + }; - virtual ~ArgumentListNode(); - virtual void releaseNodes(NodeReleaser&); + class ArgumentListNode : public ExpressionNode { + public: + ArgumentListNode(const JSTokenLocation&, ExpressionNode*); + ArgumentListNode(const JSTokenLocation&, ArgumentListNode*, ExpressionNode*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ArgumentListNode* m_next; + ExpressionNode* m_expr; - RefPtr m_next; - RefPtr m_expr; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; - class ArgumentsNode : public ParserRefCounted { + class ArgumentsNode : public ParserArenaFreeable { public: - ArgumentsNode(JSGlobalData* globalData) JSC_FAST_CALL - : ParserRefCounted(globalData) - { - } - - ArgumentsNode(JSGlobalData* globalData, ArgumentListNode* listNode) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_listNode(listNode) - { - } + ArgumentsNode(); + ArgumentsNode(ArgumentListNode*); - virtual ~ArgumentsNode(); - virtual void releaseNodes(NodeReleaser&); - - RefPtr m_listNode; + ArgumentListNode* m_listNode; }; class NewExprNode : public ExpressionNode, public ThrowableExpressionData { public: - NewExprNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr(expr) - { - } - - NewExprNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr(expr) - , m_args(args) - { - } - - virtual ~NewExprNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + NewExprNode(const JSTokenLocation&, ExpressionNode*); + NewExprNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*); private: - RefPtr m_expr; - RefPtr m_args; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; + ArgumentsNode* m_args; }; class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { public: - EvalFunctionCallNode(JSGlobalData* globalData, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_args(args) - { - } - - virtual ~EvalFunctionCallNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + EvalFunctionCallNode(const JSTokenLocation&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_args; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ArgumentsNode* m_args; }; class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallValueNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_expr(expr) - , m_args(args) - { - } - - virtual ~FunctionCallValueNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + FunctionCallValueNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_expr; - RefPtr m_args; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; + ArgumentsNode* m_args; }; class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallResolveNode(JSGlobalData* globalData, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_ident(ident) - , m_args(args) - { - } - - virtual ~FunctionCallResolveNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + FunctionCallResolveNode(const JSTokenLocation&, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - Identifier m_ident; - RefPtr m_args; - size_t m_index; // Used by LocalVarFunctionCallNode. - size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_ident; + ArgumentsNode* m_args; }; class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_args(args) - { - } - - virtual ~FunctionCallBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_base; - RefPtr m_subscript; - RefPtr m_args; + 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(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_args(args) - { - } - - virtual ~FunctionCallDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + FunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_base; - Identifier m_ident; - RefPtr m_args; - }; - - class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData { - public: - PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::numberType()) // could be reusable for pre? - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_ident(ident) - { - } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; protected: - Identifier m_ident; + ExpressionNode* m_base; + const Identifier& m_ident; + ArgumentsNode* m_args; }; - class PostfixResolveNode : public PrePostResolveNode { + class BytecodeIntrinsicNode : public ExpressionNode, public ThrowableExpressionData { public: - PostfixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset) - , m_operator(oper) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - private: - Operator m_operator; - }; + typedef RegisterID* (BytecodeIntrinsicNode::* EmitterType)(BytecodeGenerator&, RegisterID*); - class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData { - public: - PostfixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_operator(oper) - { - } + BytecodeIntrinsicNode(const JSTokenLocation&, EmitterType, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); - virtual ~PostfixBracketNode(); - virtual void releaseNodes(NodeReleaser&); + const Identifier& identifier() const { return m_ident; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; +#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: - RefPtr m_base; - RefPtr m_subscript; - Operator m_operator; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + EmitterType m_emitter; + const Identifier& m_ident; + ArgumentsNode* m_args; }; - class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData { + class CallFunctionCallDotNode : public FunctionCallDotNode { public: - PostfixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_operator(oper) - { - } - - virtual ~PostfixDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + CallFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_base; - Identifier m_ident; - Operator m_operator; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; - - class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData { + + class ApplyFunctionCallDotNode : public FunctionCallDotNode { public: - PostfixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_expr(expr) - , m_operator(oper) - { - } - - virtual ~PostfixErrorNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ApplyFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_expr; - Operator m_operator; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_ident(ident) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + DeleteResolveNode(const JSTokenLocation&, const Identifier&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - Identifier m_ident; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_ident; }; class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - { - } - - virtual ~DeleteBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + DeleteBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_base; - RefPtr m_subscript; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_base; + ExpressionNode* m_subscript; }; class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - { - } - - virtual ~DeleteDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + DeleteDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_base; - Identifier m_ident; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_base; + const Identifier& m_ident; }; class DeleteValueNode : public ExpressionNode { public: - DeleteValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr(expr) - { - } - - virtual ~DeleteValueNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + DeleteValueNode(const JSTokenLocation&, ExpressionNode*); private: - RefPtr m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; }; class VoidNode : public ExpressionNode { public: - VoidNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr(expr) - { - } - - virtual ~VoidNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + VoidNode(const JSTokenLocation&, ExpressionNode*); private: - RefPtr m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; }; class TypeOfResolveNode : public ExpressionNode { public: - TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::stringType()) - , m_ident(ident) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + TypeOfResolveNode(const JSTokenLocation&, const Identifier&); - const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } + const Identifier& identifier() const { return m_ident; } private: - Identifier m_ident; - }; - - class TypeOfValueNode : public ExpressionNode { - public: - TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::stringType()) - , m_expr(expr) - { - } - - virtual ~TypeOfValueNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - private: - RefPtr m_expr; + const Identifier& m_ident; }; - class PrefixResolveNode : public PrePostResolveNode { + class TypeOfValueNode : public ExpressionNode { public: - PrefixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset) - , m_operator(oper) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + TypeOfValueNode(const JSTokenLocation&, ExpressionNode*); private: - Operator m_operator; - }; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { - public: - PrefixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_operator(oper) - { - } - - virtual ~PrefixBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - private: - RefPtr m_base; - RefPtr m_subscript; - Operator m_operator; + ExpressionNode* m_expr; }; - class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { + class PrefixNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { public: - PrefixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_operator(oper) - { - } + PrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); - virtual ~PrefixDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + 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); - private: - RefPtr m_base; - Identifier m_ident; + ExpressionNode* m_expr; Operator m_operator; }; - class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData { + class PostfixNode : public PrefixNode { public: - PrefixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_expr(expr) - , m_operator(oper) - { - } - - virtual ~PrefixErrorNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + PostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr 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* globalData, ExpressionNode* expr) - : ExpressionNode(globalData) - , m_expr(expr) - { - } + UnaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode*, OpcodeID); - UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr) - : ExpressionNode(globalData, type) - , m_expr(expr) - { - } + protected: + ExpressionNode* expr() { return m_expr; } + const ExpressionNode* expr() const { return m_expr; } - virtual ~UnaryOpNode(); - virtual void releaseNodes(NodeReleaser&); + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0; + OpcodeID opcodeID() const { return m_opcodeID; } - protected: - RefPtr m_expr; + ExpressionNode* m_expr; + OpcodeID m_opcodeID; }; class UnaryPlusNode : public UnaryOpNode { public: - UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::numberType(), expr) - { - } - - virtual ExpressionNode* stripUnaryPlus() { return m_expr.get(); } + UnaryPlusNode(const JSTokenLocation&, ExpressionNode*); - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_to_jsnumber; } + private: + virtual ExpressionNode* stripUnaryPlus() override { return expr(); } }; class NegateNode : public UnaryOpNode { public: - NegateNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_negate; } + NegateNode(const JSTokenLocation&, ExpressionNode*); }; - class BitwiseNotNode : public UnaryOpNode { + class BitwiseNotNode : public ExpressionNode { public: - BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::forBitOp(), expr) - { - } + BitwiseNotNode(const JSTokenLocation&, ExpressionNode*); - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitnot; } - }; + 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* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::booleanType(), expr) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_not; } + LogicalNotNode(const JSTokenLocation&, ExpressionNode*); + private: + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; }; class BinaryOpNode : public ExpressionNode { public: - BinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : ExpressionNode(globalData) - , m_expr1(expr1) - , m_expr2(expr2) - , m_rightHasAssignments(rightHasAssignments) - { - } + BinaryOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + BinaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : ExpressionNode(globalData, type) - , m_expr1(expr1) - , m_expr2(expr2) - , m_rightHasAssignments(rightHasAssignments) - { - } + RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; - virtual ~BinaryOpNode(); - virtual void releaseNodes(NodeReleaser&); + ExpressionNode* lhs() { return m_expr1; }; + ExpressionNode* rhs() { return m_expr2; }; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0; + private: + void tryFoldToBranch(BytecodeGenerator&, TriState& branchCondition, ExpressionNode*& branchExpression); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; protected: - RefPtr m_expr1; - RefPtr m_expr2; - bool m_rightHasAssignments; - }; - - class ReverseBinaryOpNode : public BinaryOpNode { - public: - ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments) - { - } - - ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments) - { - } + OpcodeID opcodeID() const { return m_opcodeID; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + protected: + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + private: + OpcodeID m_opcodeID; + protected: + bool m_rightHasAssignments; }; class MultNode : public BinaryOpNode { public: - MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mul; } + MultNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class DivNode : public BinaryOpNode { public: - DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_div; } + DivNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class ModNode : public BinaryOpNode { public: - ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mod; } + ModNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class AddNode : public BinaryOpNode { public: - AddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, rightHasAssignments) - { - } + AddNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_add; } + virtual bool isAdd() const override { return true; } }; class SubNode : public BinaryOpNode { public: - SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } + SubNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_sub; } + virtual bool isSubtract() const override { return true; } }; class LeftShiftNode : public BinaryOpNode { public: - LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lshift; } + LeftShiftNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class RightShiftNode : public BinaryOpNode { public: - RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_rshift; } + RightShiftNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class UnsignedRightShiftNode : public BinaryOpNode { public: - UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_urshift; } + UnsignedRightShiftNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class LessNode : public BinaryOpNode { public: - LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; } + LessNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; - class GreaterNode : public ReverseBinaryOpNode { + class GreaterNode : public BinaryOpNode { public: - GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; } + GreaterNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class LessEqNode : public BinaryOpNode { public: - LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; } + LessEqNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; - class GreaterEqNode : public ReverseBinaryOpNode { + class GreaterEqNode : public BinaryOpNode { public: - GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; } + GreaterEqNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData { public: - ThrowableBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments) - { - } - ThrowableBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments) - { - } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + 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) override; }; class InstanceOfNode : public ThrowableBinaryOpNode { public: - InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ThrowableBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } + InstanceOfNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_instanceof; } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class InNode : public ThrowableBinaryOpNode { public: - InNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ThrowableBinaryOpNode(globalData, expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_in; } + InNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class EqualNode : public BinaryOpNode { public: - EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } + EqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_eq; } + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class NotEqualNode : public BinaryOpNode { public: - NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_neq; } + NotEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class StrictEqualNode : public BinaryOpNode { public: - StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } + StrictEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_stricteq; } + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class NotStrictEqualNode : public BinaryOpNode { public: - NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_nstricteq; } + NotStrictEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitAndNode : public BinaryOpNode { public: - BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitand; } + BitAndNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitOrNode : public BinaryOpNode { public: - BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitor; } + BitOrNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitXOrNode : public BinaryOpNode { public: - BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitxor; } + BitXOrNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; - /** - * m_expr1 && m_expr2, m_expr1 || m_expr2 - */ + // m_expr1 && m_expr2, m_expr1 || m_expr2 class LogicalOpNode : public ExpressionNode { public: - LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::booleanType()) - , m_expr1(expr1) - , m_expr2(expr2) - , m_operator(oper) - { - } - - virtual ~LogicalOpNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + LogicalOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); private: - RefPtr m_expr1; - RefPtr m_expr2; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; + + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; LogicalOperator m_operator; }; - /** - * The ternary operator, "m_logical ? m_expr1 : m_expr2" - */ + // The ternary operator, "m_logical ? m_expr1 : m_expr2" class ConditionalNode : public ExpressionNode { public: - ConditionalNode(JSGlobalData* globalData, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_logical(logical) - , m_expr1(expr1) - , m_expr2(expr2) - { - } - - virtual ~ConditionalNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ConditionalNode(const JSTokenLocation&, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); private: - RefPtr m_logical; - RefPtr m_expr1; - RefPtr m_expr2; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_logical; + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; }; class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - ReadModifyResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_ident(ident) - , m_right(right) - , m_operator(oper) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~ReadModifyResolveNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ReadModifyResolveNode(const JSTokenLocation&, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - Identifier m_ident; - RefPtr m_right; - size_t m_index; // Used by ReadModifyLocalVarNode. - Operator m_operator : 31; - bool m_rightHasAssignments : 1; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_ident; + ExpressionNode* m_right; + Operator m_operator; + bool m_rightHasAssignments; }; class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignResolveNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_ident(ident) - , m_right(right) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~AssignResolveNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + AssignResolveNode(const JSTokenLocation&, const Identifier&, ExpressionNode* right); private: - Identifier m_ident; - RefPtr m_right; - size_t m_index; // Used by ReadModifyLocalVarNode. - bool m_rightHasAssignments; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_ident; + ExpressionNode* m_right; }; class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_right(right) - , m_operator(oper) - , m_subscriptHasAssignments(subscriptHasAssignments) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~ReadModifyBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ReadModifyBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_base; - RefPtr m_subscript; - RefPtr m_right; - Operator m_operator : 30; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ExpressionNode* m_right; + unsigned m_operator : 30; bool m_subscriptHasAssignments : 1; bool m_rightHasAssignments : 1; }; class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_right(right) - , m_subscriptHasAssignments(subscriptHasAssignments) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~AssignBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + AssignBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_base; - RefPtr m_subscript; - RefPtr m_right; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ExpressionNode* m_right; bool m_subscriptHasAssignments : 1; bool m_rightHasAssignments : 1; }; class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_right(right) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~AssignDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + AssignDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_base; - Identifier m_ident; - RefPtr m_right; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_base; + const Identifier& m_ident; + ExpressionNode* m_right; bool m_rightHasAssignments; }; class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_right(right) - , m_operator(oper) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~ReadModifyDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ReadModifyDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_base; - Identifier m_ident; - RefPtr m_right; - Operator m_operator : 31; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_base; + const Identifier& m_ident; + ExpressionNode* m_right; + unsigned m_operator : 31; bool m_rightHasAssignments : 1; }; class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignErrorNode(JSGlobalData* globalData, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_left(left) - , m_operator(oper) - , m_right(right) - { - } - - virtual ~AssignErrorNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + AssignErrorNode(const JSTokenLocation&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - RefPtr m_left; - Operator m_operator; - RefPtr m_right; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; - - class CommaNode : public ExpressionNode { + + class CommaNode final : public ExpressionNode { public: - CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr1(expr1) - , m_expr2(expr2) - { - } - - virtual ~CommaNode(); - virtual void releaseNodes(NodeReleaser&); + CommaNode(const JSTokenLocation&, ExpressionNode*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + void setNext(CommaNode* next) { m_next = next; } + CommaNode* next() { return m_next; } private: - RefPtr m_expr1; - RefPtr m_expr2; + virtual bool isCommaNode() const override { return true; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; + CommaNode* m_next; }; - class VarDeclCommaNode : public CommaNode { - public: - VarDeclCommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL - : CommaNode(globalData, expr1, expr2) - { - } - }; - class ConstDeclNode : public ExpressionNode { public: - ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in) JSC_FAST_CALL; + ConstDeclNode(const JSTokenLocation&, const Identifier&, ExpressionNode*); - virtual ~ConstDeclNode(); - virtual void releaseNodes(NodeReleaser&); + bool hasInitializer() const { return m_init; } + const Identifier& ident() { return m_ident; } - Identifier m_ident; - RefPtr m_next; - RefPtr m_init; - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual RegisterID* emitCodeSingle(BytecodeGenerator&) JSC_FAST_CALL; - }; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + virtual RegisterID* emitCodeSingle(BytecodeGenerator&); + + const Identifier& m_ident; - class ConstStatementNode : public StatementNode { public: - ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next) JSC_FAST_CALL - : StatementNode(globalData) - , m_next(next) - { - } + ConstDeclNode* m_next; - virtual ~ConstStatementNode(); - virtual void releaseNodes(NodeReleaser&); + private: + ExpressionNode* m_init; + }; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + class ConstStatementNode : public StatementNode { + public: + ConstStatementNode(const JSTokenLocation&, ConstDeclNode* next); private: - RefPtr m_next; - }; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - typedef Vector > StatementVector; + ConstDeclNode* m_next; + }; - class SourceElements : public ParserRefCounted { + class SourceElements final : public ParserArenaFreeable { public: - SourceElements(JSGlobalData* globalData) : ParserRefCounted(globalData) {} + SourceElements(); - void append(PassRefPtr); - void releaseContentsIntoVector(StatementVector& destination) - { - ASSERT(destination.isEmpty()); - m_statements.swap(destination); - destination.shrinkToFit(); - } + void append(StatementNode*); + + StatementNode* singleStatement() const; + StatementNode* lastStatement() const; + + void emitBytecode(BytecodeGenerator&, RegisterID* destination); private: - StatementVector m_statements; + StatementNode* m_head; + StatementNode* m_tail; }; class BlockNode : public StatementNode { public: - BlockNode(JSGlobalData*, SourceElements* children) JSC_FAST_CALL; - - virtual ~BlockNode(); - virtual void releaseNodes(NodeReleaser&); + BlockNode(const JSTokenLocation&, SourceElements* = 0); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + StatementNode* singleStatement() const; + StatementNode* lastStatement() const; - StatementVector& children() { return m_children; } + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isBlock() const JSC_FAST_CALL { return true; } + virtual bool isBlock() const override { return true; } - private: - StatementVector m_children; + SourceElements* m_statements; }; class EmptyStatementNode : public StatementNode { public: - EmptyStatementNode(JSGlobalData* globalData) JSC_FAST_CALL // debug - : StatementNode(globalData) - { - } + EmptyStatementNode(const JSTokenLocation&); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isEmptyStatement() const JSC_FAST_CALL { return true; } + virtual bool isEmptyStatement() const override { return true; } }; class DebuggerStatementNode : public StatementNode { public: - DebuggerStatementNode(JSGlobalData* globalData) JSC_FAST_CALL - : StatementNode(globalData) - { - } + DebuggerStatementNode(const JSTokenLocation&); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ExprStatementNode : public StatementNode { public: - ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - { - } + ExprStatementNode(const JSTokenLocation&, ExpressionNode*); - virtual bool isExprStatement() const JSC_FAST_CALL { return true; } + ExpressionNode* expr() const { return m_expr; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual bool isExprStatement() const override { return true; } - ExpressionNode* expr() const { return m_expr.get(); } + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - private: - RefPtr m_expr; + ExpressionNode* m_expr; }; class VarStatementNode : public StatementNode { public: - VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - { - } - - virtual ~VarStatementNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - + VarStatementNode(const JSTokenLocation&, ExpressionNode*); private: - RefPtr m_expr; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; }; - class IfNode : public StatementNode { + class EmptyVarExpression : public ExpressionNode { public: - IfNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock) JSC_FAST_CALL - : StatementNode(globalData) - , m_condition(condition) - , m_ifBlock(ifBlock) - { - } + EmptyVarExpression(const JSTokenLocation&, const Identifier&); - virtual ~IfNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - protected: - RefPtr m_condition; - RefPtr m_ifBlock; + const Identifier& m_ident; }; - class IfElseNode : public IfNode { - public: - IfElseNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) JSC_FAST_CALL - : IfNode(globalData, condition, ifBlock) - , m_elseBlock(elseBlock) - { - } - - virtual ~IfElseNode(); - virtual void releaseNodes(NodeReleaser&); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + class IfElseNode : public StatementNode { + public: + IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); private: - RefPtr m_elseBlock; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + bool tryFoldBreakAndContinue(BytecodeGenerator&, StatementNode* ifBlock, + Label*& trueTarget, FallThroughMode&); + + ExpressionNode* m_condition; + StatementNode* m_ifBlock; + StatementNode* m_elseBlock; }; class DoWhileNode : public StatementNode { public: - DoWhileNode(JSGlobalData* globalData, StatementNode* statement, ExpressionNode* expr) JSC_FAST_CALL - : StatementNode(globalData) - , m_statement(statement) - , m_expr(expr) - { - } - - virtual ~DoWhileNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual bool isLoop() const JSC_FAST_CALL { return true; } + DoWhileNode(const JSTokenLocation&, StatementNode*, ExpressionNode*); private: - RefPtr m_statement; - RefPtr m_expr; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + StatementNode* m_statement; + ExpressionNode* m_expr; }; class WhileNode : public StatementNode { public: - WhileNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - , m_statement(statement) - { - } - - virtual ~WhileNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual bool isLoop() const JSC_FAST_CALL { return true; } + WhileNode(const JSTokenLocation&, ExpressionNode*, StatementNode*); private: - RefPtr m_expr; - RefPtr m_statement; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; + StatementNode* m_statement; }; class ForNode : public StatementNode { public: - ForNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr1(expr1) - , m_expr2(expr2) - , m_expr3(expr3) - , m_statement(statement) - , m_expr1WasVarDecl(expr1 && expr1WasVarDecl) - { - ASSERT(statement); - } - - virtual ~ForNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual bool isLoop() const JSC_FAST_CALL { return true; } + ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*); private: - RefPtr m_expr1; - RefPtr m_expr2; - RefPtr m_expr3; - RefPtr m_statement; - bool m_expr1WasVarDecl; - }; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - class ForInNode : public StatementNode, public ThrowableExpressionData { + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + ExpressionNode* m_expr3; + StatementNode* m_statement; + }; + + class DestructuringPatternNode; + + class EnumerationNode : public StatementNode, public ThrowableExpressionData { public: - ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*) JSC_FAST_CALL; - ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset) JSC_FAST_CALL; + EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); - virtual ~ForInNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + protected: + ExpressionNode* m_lexpr; + ExpressionNode* m_expr; + StatementNode* m_statement; + }; + + class ForInNode : public EnumerationNode { + public: + ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); - virtual bool isLoop() const JSC_FAST_CALL { return true; } + private: + RegisterID* tryGetBoundLocal(BytecodeGenerator&); + void emitLoopHeader(BytecodeGenerator&, RegisterID* propertyName); + void emitMultiLoopBytecode(BytecodeGenerator&, RegisterID* dst); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + }; + + class ForOfNode : public EnumerationNode { + public: + ForOfNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); + private: - Identifier m_ident; - RefPtr m_init; - RefPtr m_lexpr; - RefPtr m_expr; - RefPtr m_statement; - bool m_identIsVarDecl; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ContinueNode : public StatementNode, public ThrowableExpressionData { public: - ContinueNode(JSGlobalData* globalData) JSC_FAST_CALL - : StatementNode(globalData) - { - } - - ContinueNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : StatementNode(globalData) - , m_ident(ident) - { - } + ContinueNode(const JSTokenLocation&, const Identifier&); + Label* trivialTarget(BytecodeGenerator&); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - private: - Identifier m_ident; + 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(JSGlobalData* globalData) JSC_FAST_CALL - : StatementNode(globalData) - { - } - - BreakNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : StatementNode(globalData) - , m_ident(ident) - { - } + BreakNode(const JSTokenLocation&, const Identifier&); + Label* trivialTarget(BytecodeGenerator&); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - private: - Identifier m_ident; + virtual bool isBreak() const override { return true; } + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_ident; }; class ReturnNode : public StatementNode, public ThrowableExpressionData { public: - ReturnNode(JSGlobalData* globalData, ExpressionNode* value) JSC_FAST_CALL - : StatementNode(globalData) - , m_value(value) - { - } - - virtual ~ReturnNode(); - virtual void releaseNodes(NodeReleaser&); + ReturnNode(const JSTokenLocation&, ExpressionNode* value); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual bool isReturnNode() const JSC_FAST_CALL { return true; } + ExpressionNode* value() { return m_value; } private: - RefPtr m_value; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + virtual bool isReturnNode() const override { return true; } + + ExpressionNode* m_value; }; class WithNode : public StatementNode { public: - WithNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - , m_statement(statement) - , m_divot(divot) - , m_expressionLength(expressionLength) - { - } - - virtual ~WithNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + WithNode(const JSTokenLocation&, ExpressionNode*, StatementNode*, const JSTextPosition& divot, uint32_t expressionLength); private: - RefPtr m_expr; - RefPtr m_statement; - uint32_t m_divot; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; + StatementNode* m_statement; + JSTextPosition m_divot; uint32_t m_expressionLength; }; class LabelNode : public StatementNode, public ThrowableExpressionData { public: - LabelNode(JSGlobalData* globalData, const Identifier& name, StatementNode* statement) JSC_FAST_CALL - : StatementNode(globalData) - , m_name(name) - , m_statement(statement) - { - } - - virtual ~LabelNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + LabelNode(const JSTokenLocation&, const Identifier& name, StatementNode*); private: - Identifier m_name; - RefPtr m_statement; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_name; + StatementNode* m_statement; }; class ThrowNode : public StatementNode, public ThrowableExpressionData { public: - ThrowNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - { - } - - virtual ~ThrowNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ThrowNode(const JSTokenLocation&, ExpressionNode*); private: - RefPtr m_expr; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; }; class TryNode : public StatementNode { public: - TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock) JSC_FAST_CALL - : StatementNode(globalData) - , m_tryBlock(tryBlock) - , m_exceptionIdent(exceptionIdent) - , m_catchBlock(catchBlock) - , m_finallyBlock(finallyBlock) - , m_catchHasEval(catchHasEval) - { - } - - virtual ~TryNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL; + TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock); private: - RefPtr m_tryBlock; - Identifier m_exceptionIdent; - RefPtr m_catchBlock; - RefPtr m_finallyBlock; - bool m_catchHasEval; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + StatementNode* m_tryBlock; + const Identifier& m_thrownValueIdent; + StatementNode* m_catchBlock; + StatementNode* m_finallyBlock; }; - class ParameterNode : public ParserRefCounted { + class ParameterNode : public ParserArenaDeletable { public: - ParameterNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_ident(ident) - { - } - - ParameterNode(JSGlobalData* globalData, ParameterNode* l, const Identifier& ident) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_ident(ident) - { - l->m_next = this; - } + ParameterNode(PassRefPtr); + ParameterNode(ParameterNode*, PassRefPtr); - virtual ~ParameterNode(); - virtual void releaseNodes(NodeReleaser&); - - const Identifier& ident() const JSC_FAST_CALL { return m_ident; } - ParameterNode* nextParam() const JSC_FAST_CALL { return m_next.get(); } + DestructuringPatternNode* pattern() const { return m_pattern.get(); } + ParameterNode* nextParam() const { return m_next; } private: - Identifier m_ident; - RefPtr m_next; - }; - - struct ScopeNodeData { - typedef DeclarationStacks::VarStack VarStack; - typedef DeclarationStacks::FunctionStack FunctionStack; - - ScopeNodeData(SourceElements*, VarStack*, FunctionStack*, int numConstants); - - VarStack m_varStack; - FunctionStack m_functionStack; - int m_numConstants; - StatementVector m_children; - - void mark(); + RefPtr m_pattern; + ParameterNode* m_next; }; - class ScopeNode : public StatementNode { + class ScopeNode : public StatementNode, public ParserArenaRoot { public: typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNode(JSGlobalData*) JSC_FAST_CALL; - ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL; - virtual ~ScopeNode(); - virtual void releaseNodes(NodeReleaser&); + 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); - void adoptData(std::auto_ptr data) { m_data.adopt(data); } - ScopeNodeData* data() const { return m_data.get(); } - void destroyData() { m_data.clear(); } + using ParserArenaRoot::operator new; const SourceCode& source() const { return m_source; } - const UString& sourceURL() const JSC_FAST_CALL { 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 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; } - bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); } + 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(UniquedStringImpl* uid) { return m_capturedVariables.contains(uid); } + bool captures(const Identifier& ident) { return captures(ident.impl()); } - VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } - FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } - - 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; + return m_numConstants + 2; } - virtual void mark() { } + StatementNode* singleStatement() const; + + void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination); + + void setClosedVariables(Vector>&&) { } protected: - void setSource(const SourceCode& source) { m_source = source; } + 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 ProgramNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack&, FunctionStack&, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL - { - if (!m_code) - generateBytecode(scopeChain); - return *m_code; - } + unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } - private: - ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + static const bool scopeIsFunction = false; - void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + void setClosedVariables(Vector>&&); + const Vector>& closedVariables() const { return m_closedVariables; } - OwnPtr m_code; + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + Vector> m_closedVariables; + unsigned m_startColumn; + unsigned m_endColumn; }; class EvalNode : public ScopeNode { public: - static EvalNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; - - EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL - { - if (!m_code) - generateBytecode(scopeChain); - return *m_code; - } + EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack&, FunctionStack&, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL; + ALWAYS_INLINE unsigned startColumn() const { return 0; } + unsigned endColumn() const { return m_endColumn; } - virtual void mark(); + static const bool scopeIsFunction = false; private: - EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - OwnPtr m_code; + unsigned m_endColumn; }; - class FunctionBodyNode : public ScopeNode { - friend class JIT; + class FunctionParameters : public RefCounted { + WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(FunctionParameters); public: - static FunctionBodyNode* create(JSGlobalData*) JSC_FAST_CALL; - static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; - virtual ~FunctionBodyNode(); + static Ref create(ParameterNode*); + ~FunctionParameters(); - const Identifier* parameters() const JSC_FAST_CALL { return m_parameters; } - size_t parameterCount() const { return m_parameterCount; } - UString paramString() const JSC_FAST_CALL; - Identifier* copyParameters(); + unsigned size() const { return m_size; } + DestructuringPatternNode* at(unsigned index) { ASSERT(index < m_size); return patterns()[index]; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - CodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL - { - ASSERT(scopeChain); - if (!m_code) - generateBytecode(scopeChain); - return *m_code; - } + private: + FunctionParameters(ParameterNode*, unsigned size); - CodeBlock& generatedBytecode() JSC_FAST_CALL - { - ASSERT(m_code); - return *m_code; - } + DestructuringPatternNode** patterns() { return &m_storage; } - bool isGenerated() JSC_FAST_CALL - { - return m_code; - } + unsigned m_size; + DestructuringPatternNode* m_storage; + }; + + class FunctionBodyNode final : public StatementNode, public ParserArenaDeletable { + public: + 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); - virtual void mark(); + FunctionParameters* parameters() const { return m_parameters.get(); } - void finishParsing(const SourceCode&, ParameterNode*); - void finishParsing(Identifier* parameters, size_t parameterCount); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + void finishParsing(const SourceCode&, ParameterNode*, const Identifier&, FunctionMode); - UString toSourceString() const JSC_FAST_CALL { return source().toString(); } + 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; } - // These objects are ref/deref'd a lot in the scope chain, so this is a faster ref/deref. - // If the virtual machine changes so this doesn't happen as much we can change back. - void ref() - { - if (++m_refCount == 1) - ScopeNode::ref(); - } - void deref() - { - ASSERT(m_refCount); - if (!--m_refCount) - ScopeNode::deref(); - } + FunctionMode functionMode() { return m_functionMode; } - CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL; + 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; } - private: - FunctionBodyNode(JSGlobalData*) JSC_FAST_CALL; - FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + void setEndPosition(JSTextPosition); - void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; + 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); } - Identifier* m_parameters; - size_t m_parameterCount; - OwnPtr m_code; - unsigned m_refCount; + protected: + Identifier m_ident; + Identifier m_inferredName; + 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 FuncExprNode : public ExpressionNode { + class FunctionNode final : public ScopeNode { public: - FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_ident(ident) - , m_parameter(parameter) - , m_body(body) - { - m_body->finishParsing(source, m_parameter.get()); - } + 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 ~FuncExprNode(); - virtual void releaseNodes(NodeReleaser&); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + void finishParsing(PassRefPtr, const Identifier&, FunctionMode); + + const Identifier& ident() { return m_ident; } - virtual bool isFuncExprNode() const JSC_FAST_CALL { return true; } + FunctionMode functionMode() { return m_functionMode; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL; + unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } - FunctionBodyNode* body() { return m_body.get(); } + static const bool scopeIsFunction = true; private: Identifier m_ident; - RefPtr m_parameter; - RefPtr m_body; + FunctionMode m_functionMode; + RefPtr m_parameters; + unsigned m_startColumn; + unsigned m_endColumn; }; - class FuncDeclNode : public StatementNode { + class FuncExprNode : public ExpressionNode { public: - FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL - : StatementNode(globalData) - , m_ident(ident) - , m_parameter(parameter) - , m_body(body) - { - m_body->finishParsing(source, m_parameter.get()); - } + FuncExprNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); - virtual ~FuncDeclNode(); - virtual void releaseNodes(NodeReleaser&); + FunctionBodyNode* body() { return m_body; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL; + virtual bool isFuncExprNode() const override { return true; } - Identifier m_ident; + FunctionBodyNode* m_body; + }; - FunctionBodyNode* body() { return m_body.get(); } +#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: - RefPtr m_parameter; - RefPtr m_body; + 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; - class CaseClauseNode : public ParserRefCounted { public: - CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_expr(expr) + 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 }); } - CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr, SourceElements* children) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_expr(expr) + 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) { - if (children) - children->releaseContentsIntoVector(m_children); + 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; + }; - virtual ~CaseClauseNode(); - virtual void releaseNodes(NodeReleaser&); + class BindingNode : public DestructuringPatternNode { + public: + static Ref create(const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end); + const Identifier& boundProperty() const { return m_boundProperty; } - ExpressionNode* expr() const { return m_expr.get(); } - StatementVector& children() { return m_children; } + 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: - RefPtr m_expr; - StatementVector m_children; + 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 ClauseListNode : public ParserRefCounted { + class FuncDeclNode : public StatementNode { public: - ClauseListNode(JSGlobalData* globalData, CaseClauseNode* clause) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_clause(clause) - { - } + FuncDeclNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); - ClauseListNode(JSGlobalData* globalData, ClauseListNode* clauseList, CaseClauseNode* clause) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_clause(clause) - { - clauseList->m_next = this; - } + virtual bool isFuncDeclNode() const override { return true; } + FunctionBodyNode* body() { return m_body; } - virtual ~ClauseListNode(); - virtual void releaseNodes(NodeReleaser&); + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - CaseClauseNode* getClause() const JSC_FAST_CALL { return m_clause.get(); } - ClauseListNode* getNext() const JSC_FAST_CALL { return m_next.get(); } + FunctionBodyNode* m_body; + }; + +#if ENABLE(ES6_CLASS_SYNTAX) + class ClassDeclNode final : public StatementNode { + public: + ClassDeclNode(const JSTokenLocation&, ExpressionNode* classExpression); private: - RefPtr m_clause; - RefPtr m_next; + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_classDeclaration; }; +#endif - class CaseBlockNode : public ParserRefCounted { + class CaseClauseNode : public ParserArenaFreeable { public: - CaseBlockNode(JSGlobalData* globalData, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_list1(list1) - , m_defaultClause(defaultClause) - , m_list2(list2) - { - } + CaseClauseNode(ExpressionNode*, SourceElements* = 0); - virtual ~CaseBlockNode(); - virtual void releaseNodes(NodeReleaser&); + ExpressionNode* expr() const { return m_expr; } - RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL; + void emitBytecode(BytecodeGenerator&, RegisterID* destination); + void setStartOffset(int offset) { m_startOffset = offset; } private: - SwitchInfo::SwitchType tryOptimizedSwitch(Vector& literalVector, int32_t& min_num, int32_t& max_num); - RefPtr m_list1; - RefPtr m_defaultClause; - RefPtr m_list2; + ExpressionNode* m_expr; + SourceElements* m_statements; + int m_startOffset; }; - class SwitchNode : public StatementNode { + class ClauseListNode : public ParserArenaFreeable { public: - SwitchNode(JSGlobalData* globalData, ExpressionNode* expr, CaseBlockNode* block) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - , m_block(block) - { - } + ClauseListNode(CaseClauseNode*); + ClauseListNode(ClauseListNode*, CaseClauseNode*); + + CaseClauseNode* getClause() const { return m_clause; } + ClauseListNode* getNext() const { return m_next; } - virtual ~SwitchNode(); - virtual void releaseNodes(NodeReleaser&); + private: + CaseClauseNode* m_clause; + ClauseListNode* m_next; + }; + + class CaseBlockNode : public ParserArenaFreeable { + public: + CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + void emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination); private: - RefPtr m_expr; - RefPtr m_block; + 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; + }; + + class SwitchNode : public StatementNode { + public: + SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*); + + private: + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; + CaseBlockNode* m_block; }; struct ElementList { @@ -2421,4 +1979,4 @@ namespace JSC { } // namespace JSC -#endif // NODES_H_ +#endif // Nodes_h