diff options
Diffstat (limited to 'Source/JavaScriptCore/parser/Nodes.h')
-rw-r--r-- | Source/JavaScriptCore/parser/Nodes.h | 1290 |
1 files changed, 927 insertions, 363 deletions
diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h index d779a178d..70606824d 100644 --- a/Source/JavaScriptCore/parser/Nodes.h +++ b/Source/JavaScriptCore/parser/Nodes.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2003-2009, 2013, 2015-2016 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel <eric@webkit.org> @@ -23,31 +23,39 @@ * */ -#ifndef Nodes_h -#define Nodes_h +#pragma once +#include "BuiltinNames.h" #include "Error.h" +#include "Interpreter.h" #include "JITCode.h" -#include "Opcode.h" #include "ParserArena.h" #include "ParserTokens.h" #include "ResultType.h" #include "SourceCode.h" #include "SymbolTable.h" +#include "VariableEnvironment.h" #include <wtf/MathExtras.h> +#include <wtf/SmallPtrSet.h> namespace JSC { + enum OpcodeID : unsigned; + class ArgumentListNode; class BytecodeGenerator; - class FunctionBodyNode; + class FunctionMetadataNode; + class FunctionParameters; class Label; + class ModuleAnalyzer; + class ModuleScopeData; class PropertyListNode; class ReadModifyResolveNode; class RegisterID; - class JSScope; class ScopeNode; + typedef SmallPtrSet<UniquedStringImpl*> UniquedStringImplPtrSet; + enum Operator { OpEqual, OpPlusEq, @@ -60,6 +68,7 @@ namespace JSC { OpXOrEq, OpOrEq, OpModEq, + OpPowEq, OpLShift, OpRShift, OpURShift @@ -76,12 +85,8 @@ namespace JSC { }; inline FallThroughMode invert(FallThroughMode fallThroughMode) { return static_cast<FallThroughMode>(!fallThroughMode); } - typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet; - namespace DeclarationStacks { - enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; - typedef Vector<std::pair<Identifier, unsigned>> VarStack; - typedef Vector<FunctionBodyNode*> FunctionStack; + typedef Vector<FunctionMetadataNode*> FunctionStack; } struct SwitchInfo { @@ -90,11 +95,17 @@ namespace JSC { SwitchType switchType; }; + enum class AssignmentContext { + DeclarationStatement, + ConstDeclarationStatement, + AssignmentExpression + }; + class ParserArenaFreeable { public: // ParserArenaFreeable objects are are freed when the arena is deleted. // Destructors are not called. Clients must not call delete on such objects. - void* operator new(size_t, VM*); + void* operator new(size_t, ParserArena&); }; class ParserArenaDeletable { @@ -103,24 +114,20 @@ namespace JSC { // ParserArenaDeletable objects are deleted when the arena is deleted. // Clients must not call delete directly on such objects. - void* operator new(size_t, VM*); - }; - - template <typename T> - struct ParserArenaData : ParserArenaDeletable { - T data; + void* operator new(size_t, ParserArena&); }; - class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> { - WTF_FASTMALLOC_OPERATORS; + class ParserArenaRoot { + WTF_MAKE_FAST_ALLOCATED; protected: - ParserArenaRefCounted(VM*); + ParserArenaRoot(ParserArena&); public: - virtual ~ParserArenaRefCounted() - { - ASSERT(deletionHasBegun()); - } + ParserArena& parserArena() { return m_arena; } + virtual ~ParserArenaRoot() { } + + protected: + ParserArena m_arena; }; class Node : public ParserArenaFreeable { @@ -130,13 +137,21 @@ namespace JSC { public: virtual ~Node() { } - int lineNo() const { return m_position.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; } + + bool needsDebugHook() const { return m_needsDebugHook; } + void setNeedsDebugHook() { m_needsDebugHook = true; } protected: JSTextPosition m_position; + int m_endOffset; + bool m_needsDebugHook { false }; }; class ExpressionNode : public Node { @@ -148,23 +163,34 @@ namespace JSC { virtual bool isNumber() const { return false; } virtual bool isString() const { return false; } + virtual bool isObjectLiteral() const { return false; } + virtual bool isArrayLiteral() 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 isAssignResolveNode() const { return false; } virtual bool isBracketAccessorNode() const { return false; } virtual bool isDotAccessorNode() const { return false; } - virtual bool isDeconstructionNode() const { return false; } + virtual bool isDestructuringNode() const { return false; } + virtual bool isBaseFuncExprNode() const { return false; } virtual bool isFuncExprNode() const { return false; } + virtual bool isArrowFuncExprNode() const { return false; } + virtual bool isClassExprNode() 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 bool isImportNode() const { return false; } + virtual bool isNewTarget() const { return false; } + virtual bool isBytecodeIntrinsicNode() const { return false; } - virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, FallThroughMode); + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label&, Label&, FallThroughMode); virtual ExpressionNode* stripUnaryPlus() { return this; } @@ -182,29 +208,57 @@ namespace JSC { virtual void emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset); - unsigned firstLine() const { return lineNo(); } unsigned lastLine() const { return m_lastLine; } + StatementNode* next() { return m_next; } + void setNext(StatementNode* next) { m_next = next; } + virtual bool isEmptyStatement() const { return false; } + virtual bool isDebuggerStatement() const { return false; } + virtual bool isFunctionNode() 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 isLabel() const { return false; } virtual bool isBlock() const { return false; } + virtual bool isFuncDeclNode() const { return false; } + virtual bool isModuleDeclarationNode() const { return false; } + virtual bool isForOfNode() const { return false; } protected: + StatementNode* m_next; int m_lastLine; }; + class VariableEnvironmentNode : public ParserArenaDeletable { + public: + typedef DeclarationStacks::FunctionStack FunctionStack; + + VariableEnvironmentNode() + { + } + + VariableEnvironmentNode(VariableEnvironment& lexicalDeclaredVariables); + VariableEnvironmentNode(VariableEnvironment& lexicalDeclaredVariables, FunctionStack&&); + + VariableEnvironment& lexicalVariables() { return m_lexicalVariables; } + FunctionStack& functionStack() { return m_functionStack; } + + protected: + VariableEnvironment m_lexicalVariables; + FunctionStack m_functionStack; + }; + class ConstantNode : public ExpressionNode { public: ConstantNode(const JSTokenLocation&, ResultType); - virtual bool isPure(BytecodeGenerator&) const override { return true; } - virtual bool isConstant() const override { return true; } + bool isPure(BytecodeGenerator&) const override { return true; } + 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; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecodeInConditionContext(BytecodeGenerator&, Label& trueTarget, Label& falseTarget, FallThroughMode) override; }; class NullNode : public ConstantNode { @@ -212,8 +266,8 @@ namespace JSC { NullNode(const JSTokenLocation&); private: - virtual bool isNull() const override { return true; } - virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNull(); } + bool isNull() const override { return true; } + JSValue jsValue(BytecodeGenerator&) const override { return jsNull(); } }; class BooleanNode : public ConstantNode { @@ -222,8 +276,8 @@ namespace JSC { bool value() { return m_value; } private: - virtual bool isBoolean() const override { return true; } - virtual JSValue jsValue(BytecodeGenerator&) const override { return jsBoolean(m_value); } + bool isBoolean() const override { return true; } + JSValue jsValue(BytecodeGenerator&) const override { return jsBoolean(m_value); } bool m_value; }; @@ -231,28 +285,44 @@ namespace JSC { class NumberNode : public ConstantNode { public: NumberNode(const JSTokenLocation&, double value); - double value() { return m_value; } - void setValue(double value) { m_value = value; } + double value() const { return m_value; } + virtual bool isIntegerNode() const = 0; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) final; private: - virtual bool isNumber() const override { return true; } - virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNumber(m_value); } + bool isNumber() const final { return true; } + JSValue jsValue(BytecodeGenerator&) const override { return jsNumber(m_value); } double m_value; }; + class DoubleNode : public NumberNode { + public: + DoubleNode(const JSTokenLocation&, double value); + + private: + bool isIntegerNode() const override { return false; } + }; + + // An integer node represent a number represented as an integer (e.g. 42 instead of 42., 42.0, 42e0) + class IntegerNode : public DoubleNode { + public: + IntegerNode(const JSTokenLocation&, double value); + bool isIntegerNode() const final { return true; } + }; + class StringNode : public ConstantNode { public: StringNode(const JSTokenLocation&, const Identifier&); const Identifier& value() { return m_value; } private: - virtual bool isString() const override { return true; } - virtual JSValue jsValue(BytecodeGenerator&) const override; + bool isString() const override { return true; } + JSValue jsValue(BytecodeGenerator&) const override; const Identifier& m_value; }; - + class ThrowableExpressionData { public: ThrowableExpressionData() @@ -405,12 +475,80 @@ namespace JSC { uint16_t m_subexpressionLineStartOffset; }; + class TemplateExpressionListNode : public ParserArenaFreeable { + public: + TemplateExpressionListNode(ExpressionNode*); + TemplateExpressionListNode(TemplateExpressionListNode*, ExpressionNode*); + + ExpressionNode* value() { return m_node; } + TemplateExpressionListNode* next() { return m_next; } + + private: + TemplateExpressionListNode* m_next { nullptr }; + ExpressionNode* m_node { nullptr }; + }; + + class TemplateStringNode : public ExpressionNode { + public: + TemplateStringNode(const JSTokenLocation&, const Identifier* cooked, const Identifier* raw); + + const Identifier* cooked() { return m_cooked; } + const Identifier* raw() { return m_raw; } + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier* m_cooked; + const Identifier* m_raw; + }; + + class TemplateStringListNode : public ParserArenaFreeable { + public: + TemplateStringListNode(TemplateStringNode*); + TemplateStringListNode(TemplateStringListNode*, TemplateStringNode*); + + TemplateStringNode* value() { return m_node; } + TemplateStringListNode* next() { return m_next; } + + private: + TemplateStringListNode* m_next { nullptr }; + TemplateStringNode* m_node { nullptr }; + }; + + class TemplateLiteralNode : public ExpressionNode { + public: + TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*); + TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*, TemplateExpressionListNode*); + + TemplateStringListNode* templateStrings() const { return m_templateStrings; } + TemplateExpressionListNode* templateExpressions() const { return m_templateExpressions; } + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + TemplateStringListNode* m_templateStrings; + TemplateExpressionListNode* m_templateExpressions; + }; + + class TaggedTemplateNode : public ExpressionNode, public ThrowableExpressionData { + public: + TaggedTemplateNode(const JSTokenLocation&, ExpressionNode*, TemplateLiteralNode*); + + TemplateLiteralNode* templateLiteral() const { return m_templateLiteral; } + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_tag; + TemplateLiteralNode* m_templateLiteral; + }; + class RegExpNode : public ExpressionNode, public ThrowableExpressionData { public: RegExpNode(const JSTokenLocation&, const Identifier& pattern, const Identifier& flags); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_pattern; const Identifier& m_flags; @@ -421,7 +559,36 @@ namespace JSC { ThisNode(const JSTokenLocation&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + }; + + class SuperNode final : public ExpressionNode { + public: + SuperNode(const JSTokenLocation&); + + private: + bool isSuperNode() const override { return true; } + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + }; + + class ImportNode : public ExpressionNode, public ThrowableExpressionData { + public: + ImportNode(const JSTokenLocation&, ExpressionNode*); + + private: + bool isImportNode() const override { return true; } + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_expr; + }; + + class NewTargetNode final : public ExpressionNode { + public: + NewTargetNode(const JSTokenLocation&); + + private: + bool isNewTarget() const final { return true; } + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ResolveNode : public ExpressionNode { @@ -431,11 +598,11 @@ namespace JSC { const Identifier& identifier() const { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + 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; } + bool isPure(BytecodeGenerator&) const override; + bool isLocation() const override { return true; } + bool isResolveNode() const override { return true; } const Identifier& m_ident; JSTextPosition m_start; @@ -462,13 +629,15 @@ namespace JSC { ArrayNode(const JSTokenLocation&, ElementNode*); ArrayNode(const JSTokenLocation&, int elision, ElementNode*); - ArgumentListNode* toArgumentList(VM*, int, int) const; + bool isArrayLiteral() const override { return true; } + + ArgumentListNode* toArgumentList(ParserArena&, int, int) const; ElementNode* elements() const { ASSERT(isSimpleArray()); return m_element; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isSimpleArray() const override; + bool isSimpleArray() const override; ElementNode* m_element; int m_elision; @@ -477,23 +646,29 @@ namespace JSC { class PropertyNode : public ParserArenaFreeable { public: - enum Type { Constant = 1, Getter = 2, Setter = 4 }; + enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16 }; + enum PutType { Unknown, KnownDirect }; + + PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty); + PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty); - PropertyNode(VM*, const Identifier&, ExpressionNode*, Type); - PropertyNode(VM*, double, ExpressionNode*, Type); - PropertyNode(VM*, ExpressionNode* propertyName, ExpressionNode*, Type); - ExpressionNode* expressionName() const { return m_expression; } const Identifier* name() const { return m_name; } - Type type() const { return m_type; } + Type type() const { return static_cast<Type>(m_type); } + bool needsSuperBinding() const { return m_needsSuperBinding; } + bool isClassProperty() const { return m_isClassProperty; } + PutType putType() const { return static_cast<PutType>(m_putType); } private: friend class PropertyListNode; const Identifier* m_name; ExpressionNode* m_expression; ExpressionNode* m_assign; - Type m_type; + unsigned m_type : 5; + unsigned m_needsSuperBinding : 1; + unsigned m_putType : 1; + unsigned m_isClassProperty: 1; }; class PropertyListNode : public ExpressionNode { @@ -501,9 +676,12 @@ namespace JSC { PropertyListNode(const JSTokenLocation&, PropertyNode*); PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + bool hasStaticallyNamedProperty(const Identifier& propName); private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitPutConstantProperty(BytecodeGenerator&, RegisterID*, PropertyNode&); + PropertyNode* m_node; PropertyListNode* m_next; }; @@ -512,9 +690,10 @@ namespace JSC { public: ObjectLiteralNode(const JSTokenLocation&); ObjectLiteralNode(const JSTokenLocation&, PropertyListNode*); + bool isObjectLiteral() const override { return true; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; PropertyListNode* m_list; }; @@ -529,10 +708,10 @@ namespace JSC { bool subscriptHasAssignments() const { return m_subscriptHasAssignments; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isLocation() const override { return true; } - virtual bool isBracketAccessorNode() const override { return true; } + bool isLocation() const override { return true; } + bool isBracketAccessorNode() const override { return true; } ExpressionNode* m_base; ExpressionNode* m_subscript; @@ -547,10 +726,10 @@ namespace JSC { const Identifier& identifier() const { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isLocation() const override { return true; } - virtual bool isDotAccessorNode() const override { return true; } + bool isLocation() const override { return true; } + bool isDotAccessorNode() const override { return true; } ExpressionNode* m_base; const Identifier& m_ident; @@ -563,9 +742,9 @@ namespace JSC { ExpressionNode* expression() const { return m_expression; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isSpreadExpression() const override { return true; } + bool isSpreadExpression() const override { return true; } ExpressionNode* m_expression; }; @@ -578,7 +757,7 @@ namespace JSC { ExpressionNode* m_expr; private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ArgumentsNode : public ParserArenaFreeable { @@ -595,7 +774,7 @@ namespace JSC { NewExprNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; ArgumentsNode* m_args; @@ -606,7 +785,7 @@ namespace JSC { EvalFunctionCallNode(const JSTokenLocation&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ArgumentsNode* m_args; }; @@ -616,7 +795,7 @@ namespace JSC { FunctionCallValueNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; ArgumentsNode* m_args; @@ -627,7 +806,7 @@ namespace JSC { FunctionCallResolveNode(const JSTokenLocation&, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; ArgumentsNode* m_args; @@ -635,14 +814,15 @@ namespace JSC { class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); + FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; ExpressionNode* m_subscript; ArgumentsNode* m_args; + bool m_subscriptHasAssignments; }; class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { @@ -650,7 +830,7 @@ namespace JSC { FunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; protected: ExpressionNode* m_base; @@ -658,12 +838,43 @@ namespace JSC { ArgumentsNode* m_args; }; + class BytecodeIntrinsicNode : public ExpressionNode, public ThrowableExpressionData { + public: + enum class Type { + Constant, + Function + }; + + typedef RegisterID* (BytecodeIntrinsicNode::* EmitterType)(BytecodeGenerator&, RegisterID*); + + BytecodeIntrinsicNode(Type, const JSTokenLocation&, EmitterType, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); + + bool isBytecodeIntrinsicNode() const override { return true; } + + Type type() const { return m_type; } + EmitterType emitter() const { return m_emitter; } + const Identifier& identifier() const { return m_ident; } + +#define JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS(name) RegisterID* emit_intrinsic_##name(BytecodeGenerator&, RegisterID*); + JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS) + JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS) +#undef JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + Type m_type; + EmitterType m_emitter; + const Identifier& m_ident; + ArgumentsNode* m_args; + }; + class CallFunctionCallDotNode : public FunctionCallDotNode { public: CallFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ApplyFunctionCallDotNode : public FunctionCallDotNode { @@ -671,7 +882,7 @@ namespace JSC { ApplyFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { @@ -679,7 +890,7 @@ namespace JSC { DeleteResolveNode(const JSTokenLocation&, const Identifier&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; }; @@ -689,7 +900,7 @@ namespace JSC { DeleteBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; ExpressionNode* m_subscript; @@ -700,7 +911,7 @@ namespace JSC { DeleteDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; const Identifier& m_ident; @@ -711,7 +922,7 @@ namespace JSC { DeleteValueNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; @@ -721,7 +932,7 @@ namespace JSC { VoidNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; @@ -733,7 +944,7 @@ namespace JSC { const Identifier& identifier() const { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; }; @@ -743,7 +954,7 @@ namespace JSC { TypeOfValueNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; @@ -753,7 +964,7 @@ namespace JSC { PrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); protected: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; virtual RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0); virtual RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0); virtual RegisterID* emitDot(BytecodeGenerator&, RegisterID* = 0); @@ -767,10 +978,10 @@ namespace JSC { PostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - 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; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitDot(BytecodeGenerator&, RegisterID* = 0) override; }; class UnaryOpNode : public ExpressionNode { @@ -780,11 +991,10 @@ namespace JSC { protected: ExpressionNode* expr() { return m_expr; } const ExpressionNode* expr() const { return m_expr; } + OpcodeID opcodeID() const { return m_opcodeID; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - - OpcodeID opcodeID() const { return m_opcodeID; } + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; OpcodeID m_opcodeID; @@ -795,7 +1005,9 @@ namespace JSC { UnaryPlusNode(const JSTokenLocation&, ExpressionNode*); private: - virtual ExpressionNode* stripUnaryPlus() override { return expr(); } + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* stripUnaryPlus() override { return expr(); } }; class NegateNode : public UnaryOpNode { @@ -812,7 +1024,7 @@ namespace JSC { const ExpressionNode* expr() const { return m_expr; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; @@ -821,7 +1033,7 @@ namespace JSC { public: LogicalNotNode(const JSTokenLocation&, ExpressionNode*); private: - virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; + void emitBytecodeInConditionContext(BytecodeGenerator&, Label& trueTarget, Label& falseTarget, FallThroughMode) override; }; class BinaryOpNode : public ExpressionNode { @@ -830,14 +1042,14 @@ namespace JSC { BinaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); - virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; + void emitBytecodeInConditionContext(BytecodeGenerator&, Label& trueTarget, Label& falseTarget, FallThroughMode) override; ExpressionNode* lhs() { return m_expr1; }; ExpressionNode* rhs() { return m_expr2; }; private: void tryFoldToBranch(BytecodeGenerator&, TriState& branchCondition, ExpressionNode*& branchExpression); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; protected: OpcodeID opcodeID() const { return m_opcodeID; } @@ -851,6 +1063,11 @@ namespace JSC { bool m_rightHasAssignments; }; + class PowNode : public BinaryOpNode { + public: + PowNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + class MultNode : public BinaryOpNode { public: MultNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); @@ -870,14 +1087,14 @@ namespace JSC { public: AddNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual bool isAdd() const override { return true; } + bool isAdd() const override { return true; } }; class SubNode : public BinaryOpNode { public: SubNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual bool isSubtract() const override { return true; } + bool isSubtract() const override { return true; } }; class LeftShiftNode : public BinaryOpNode { @@ -921,7 +1138,7 @@ namespace JSC { ThrowableBinaryOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class InstanceOfNode : public ThrowableBinaryOpNode { @@ -929,12 +1146,15 @@ namespace JSC { InstanceOfNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class InNode : public ThrowableBinaryOpNode { public: InNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class EqualNode : public BinaryOpNode { @@ -942,7 +1162,7 @@ namespace JSC { EqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class NotEqualNode : public BinaryOpNode { @@ -955,7 +1175,7 @@ namespace JSC { StrictEqualNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class NotStrictEqualNode : public BinaryOpNode { @@ -984,8 +1204,8 @@ namespace JSC { LogicalOpNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecodeInConditionContext(BytecodeGenerator&, Label& trueTarget, Label& falseTarget, FallThroughMode) override; ExpressionNode* m_expr1; ExpressionNode* m_expr2; @@ -998,7 +1218,7 @@ namespace JSC { ConditionalNode(const JSTokenLocation&, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_logical; ExpressionNode* m_expr1; @@ -1010,7 +1230,7 @@ namespace JSC { ReadModifyResolveNode(const JSTokenLocation&, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; ExpressionNode* m_right; @@ -1020,13 +1240,16 @@ namespace JSC { class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignResolveNode(const JSTokenLocation&, const Identifier&, ExpressionNode* right); + AssignResolveNode(const JSTokenLocation&, const Identifier&, ExpressionNode* right, AssignmentContext); + bool isAssignResolveNode() const override { return true; } + const Identifier& identifier() const { return m_ident; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; ExpressionNode* m_right; + AssignmentContext m_assignmentContext; }; class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { @@ -1034,12 +1257,12 @@ namespace JSC { ReadModifyBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; ExpressionNode* m_subscript; ExpressionNode* m_right; - Operator m_operator : 30; + unsigned m_operator : 30; bool m_subscriptHasAssignments : 1; bool m_rightHasAssignments : 1; }; @@ -1049,7 +1272,7 @@ namespace JSC { AssignBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; ExpressionNode* m_subscript; @@ -1063,7 +1286,7 @@ namespace JSC { AssignDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; const Identifier& m_ident; @@ -1076,12 +1299,12 @@ namespace JSC { ReadModifyDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_base; const Identifier& m_ident; ExpressionNode* m_right; - Operator m_operator : 31; + unsigned m_operator : 31; bool m_rightHasAssignments : 1; }; @@ -1090,57 +1313,25 @@ namespace JSC { AssignErrorNode(const JSTokenLocation&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; - typedef Vector<ExpressionNode*, 8> ExpressionVector; - - class CommaNode : public ExpressionNode, public ParserArenaDeletable { + class CommaNode final : public ExpressionNode { public: - CommaNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2); - - using ParserArenaDeletable::operator new; + CommaNode(const JSTokenLocation&, ExpressionNode*); - void append(ExpressionNode* expr) { ASSERT(expr); m_expressions.append(expr); } + void setNext(CommaNode* next) { m_next = next; } + CommaNode* next() { return m_next; } private: - virtual bool isCommaNode() const override { return true; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + bool isCommaNode() const override { return true; } + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - ExpressionVector m_expressions; + ExpressionNode* m_expr; + CommaNode* m_next; }; - class ConstDeclNode : public ExpressionNode { - public: - ConstDeclNode(const JSTokenLocation&, const Identifier&, ExpressionNode*); - - bool hasInitializer() const { return m_init; } - const Identifier& ident() { return m_ident; } - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual RegisterID* emitCodeSingle(BytecodeGenerator&); - - const Identifier& m_ident; - - public: - ConstDeclNode* m_next; - - private: - ExpressionNode* m_init; - }; - - class ConstStatementNode : public StatementNode { - public: - ConstStatementNode(const JSTokenLocation&, ConstDeclNode* next); - - private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - - ConstDeclNode* m_next; - }; - - class SourceElements : public ParserArenaDeletable { + class SourceElements final : public ParserArenaFreeable { public: SourceElements(); @@ -1150,22 +1341,26 @@ namespace JSC { StatementNode* lastStatement() const; void emitBytecode(BytecodeGenerator&, RegisterID* destination); + void analyzeModule(ModuleAnalyzer&); private: - Vector<StatementNode*> m_statements; + StatementNode* m_head; + StatementNode* m_tail; }; - class BlockNode : public StatementNode { + class BlockNode : public StatementNode, public VariableEnvironmentNode { public: - BlockNode(const JSTokenLocation&, SourceElements* = 0); + using ParserArenaDeletable::operator new; + + BlockNode(const JSTokenLocation&, SourceElements*, VariableEnvironment&, FunctionStack&&); StatementNode* singleStatement() const; StatementNode* lastStatement() const; private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isBlock() const override { return true; } + bool isBlock() const override { return true; } SourceElements* m_statements; }; @@ -1175,17 +1370,19 @@ namespace JSC { EmptyStatementNode(const JSTokenLocation&); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isEmptyStatement() const override { return true; } + bool isEmptyStatement() const override { return true; } }; class DebuggerStatementNode : public StatementNode { public: DebuggerStatementNode(const JSTokenLocation&); + + bool isDebuggerStatement() const override { return true; } private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ExprStatementNode : public StatementNode { @@ -1195,28 +1392,48 @@ namespace JSC { ExpressionNode* expr() const { return m_expr; } private: - virtual bool isExprStatement() const override { return true; } + bool isExprStatement() const override { return true; } - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; - class VarStatementNode : public StatementNode { + class DeclarationStatement : public StatementNode { public: - VarStatementNode(const JSTokenLocation&, ExpressionNode*); + DeclarationStatement(const JSTokenLocation&, ExpressionNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; + class EmptyVarExpression : public ExpressionNode { + public: + EmptyVarExpression(const JSTokenLocation&, const Identifier&); + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_ident; + }; + + class EmptyLetExpression : public ExpressionNode { + public: + EmptyLetExpression(const JSTokenLocation&, const Identifier&); + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + const Identifier& m_ident; + }; + class IfElseNode : public StatementNode { public: IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; bool tryFoldBreakAndContinue(BytecodeGenerator&, StatementNode* ifBlock, Label*& trueTarget, FallThroughMode&); @@ -1230,7 +1447,7 @@ namespace JSC { DoWhileNode(const JSTokenLocation&, StatementNode*, ExpressionNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; StatementNode* m_statement; ExpressionNode* m_expr; @@ -1241,18 +1458,20 @@ namespace JSC { WhileNode(const JSTokenLocation&, ExpressionNode*, StatementNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; StatementNode* m_statement; }; - class ForNode : public StatementNode { + class ForNode : public StatementNode, public VariableEnvironmentNode { public: - ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*); + using ParserArenaDeletable::operator new; + + ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*, VariableEnvironment&); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr1; ExpressionNode* m_expr2; @@ -1260,13 +1479,17 @@ namespace JSC { StatementNode* m_statement; }; - class DeconstructionPatternNode; + class DestructuringPatternNode; - class EnumerationNode : public StatementNode, public ThrowableExpressionData { + class EnumerationNode : public StatementNode, public ThrowableExpressionData, public VariableEnvironmentNode { public: - EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); - EnumerationNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*); - + using ParserArenaDeletable::operator new; + + EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&); + + ExpressionNode* lexpr() const { return m_lexpr; } + ExpressionNode* expr() const { return m_expr; } + protected: ExpressionNode* m_lexpr; ExpressionNode* m_expr; @@ -1275,44 +1498,44 @@ namespace JSC { class ForInNode : public EnumerationNode { public: - ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); - ForInNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*); + ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* tryGetBoundLocal(BytecodeGenerator&); + void emitLoopHeader(BytecodeGenerator&, RegisterID* propertyName); + + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ForOfNode : public EnumerationNode { public: - ForOfNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); - ForOfNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*); - + ForOfNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*, VariableEnvironment&); + bool isForOfNode() const override { return true; } + private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; }; class ContinueNode : public StatementNode, public ThrowableExpressionData { public: - ContinueNode(VM*, const JSTokenLocation&); ContinueNode(const JSTokenLocation&, const Identifier&); Label* trivialTarget(BytecodeGenerator&); private: - virtual bool isContinue() const override { return true; } - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + bool isContinue() const override { return true; } + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; }; class BreakNode : public StatementNode, public ThrowableExpressionData { public: - BreakNode(VM*, const JSTokenLocation&); BreakNode(const JSTokenLocation&, const Identifier&); Label* trivialTarget(BytecodeGenerator&); private: - virtual bool isBreak() const override { return true; } - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + bool isBreak() const override { return true; } + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_ident; }; @@ -1324,9 +1547,9 @@ namespace JSC { ExpressionNode* value() { return m_value; } private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isReturnNode() const override { return true; } + bool isReturnNode() const override { return true; } ExpressionNode* m_value; }; @@ -1336,7 +1559,7 @@ namespace JSC { WithNode(const JSTokenLocation&, ExpressionNode*, StatementNode*, const JSTextPosition& divot, uint32_t expressionLength); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; StatementNode* m_statement; @@ -1348,8 +1571,10 @@ namespace JSC { public: LabelNode(const JSTokenLocation&, const Identifier& name, StatementNode*); + bool isLabel() const override { return true; } + private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; const Identifier& m_name; StatementNode* m_statement; @@ -1360,55 +1585,33 @@ namespace JSC { ThrowNode(const JSTokenLocation&, ExpressionNode*); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; }; - class TryNode : public StatementNode { + class TryNode : public StatementNode, public VariableEnvironmentNode { public: - TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock); + using ParserArenaDeletable::operator new; + + TryNode(const JSTokenLocation&, StatementNode* tryBlock, DestructuringPatternNode* catchPattern, StatementNode* catchBlock, VariableEnvironment& catchEnvironment, StatementNode* finallyBlock); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; StatementNode* m_tryBlock; - const Identifier& m_exceptionIdent; + DestructuringPatternNode* m_catchPattern; StatementNode* m_catchBlock; StatementNode* m_finallyBlock; }; - class ParameterNode : public ParserArenaDeletable { + class ScopeNode : public StatementNode, public ParserArenaRoot, public VariableEnvironmentNode { public: - ParameterNode(PassRefPtr<DeconstructionPatternNode>); - ParameterNode(ParameterNode*, PassRefPtr<DeconstructionPatternNode>); - DeconstructionPatternNode* pattern() const { return m_pattern.get(); } - ParameterNode* nextParam() const { return m_next; } + ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, bool inStrictContext); + ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants); - private: - RefPtr<DeconstructionPatternNode> m_pattern; - ParameterNode* m_next; - }; - - class ScopeNode : public StatementNode, public ParserArenaRefCounted { - public: - typedef DeclarationStacks::VarStack VarStack; - typedef DeclarationStacks::FunctionStack FunctionStack; - - ScopeNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, bool inStrictContext); - ScopeNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); - - using ParserArenaRefCounted::operator new; - - void destroyData() - { - m_arena.reset(); - m_varStack.clear(); - m_functionStack.clear(); - m_statements = 0; - m_capturedVariables.clear(); - } + using ParserArenaRoot::operator new; const SourceCode& source() const { return m_source; } const String& sourceURL() const { return m_source.provider()->url(); } @@ -1420,21 +1623,31 @@ namespace JSC { void setFeatures(CodeFeatures features) { m_features = features; } CodeFeatures features() { return m_features; } + InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures() { return m_innerArrowFunctionCodeFeatures; } + bool doAnyInnerArrowFunctionsUseAnyFeature() { return m_innerArrowFunctionCodeFeatures != NoInnerArrowFunctionFeatures; } + bool doAnyInnerArrowFunctionsUseArguments() { return m_innerArrowFunctionCodeFeatures & ArgumentsInnerArrowFunctionFeature; } + bool doAnyInnerArrowFunctionsUseSuperCall() { return m_innerArrowFunctionCodeFeatures & SuperCallInnerArrowFunctionFeature; } + bool doAnyInnerArrowFunctionsUseSuperProperty() { return m_innerArrowFunctionCodeFeatures & SuperPropertyInnerArrowFunctionFeature; } + bool doAnyInnerArrowFunctionsUseEval() { return m_innerArrowFunctionCodeFeatures & EvalInnerArrowFunctionFeature; } + bool doAnyInnerArrowFunctionsUseThis() { return m_innerArrowFunctionCodeFeatures & ThisInnerArrowFunctionFeature; } + bool doAnyInnerArrowFunctionsUseNewTarget() { return m_innerArrowFunctionCodeFeatures & NewTargetInnerArrowFunctionFeature; } bool usesEval() const { return m_features & EvalFeature; } bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); } - bool modifiesParameter() const { return m_features & ModifiedParameterFeature; } + bool usesArrowFunction() const { return m_features & ArrowFunctionFeature; } bool isStrictMode() const { return m_features & StrictModeFeature; } void setUsesArguments() { m_features |= ArgumentsFeature; } bool usesThis() const { return m_features & ThisFeature; } - 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(); } - bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); } + bool usesSuperCall() const { return m_features & SuperCallFeature; } + bool usesSuperProperty() const { return m_features & SuperPropertyFeature; } + bool usesNewTarget() const { return m_features & NewTargetFeature; } + bool needsActivation() const { return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature)); } + bool hasCapturedVariables() const { return m_varDeclarations.hasCapturedVariables(); } + bool captures(UniquedStringImpl* uid) { return m_varDeclarations.captures(uid); } + bool captures(const Identifier& ident) { return captures(ident.impl()); } + bool hasSloppyModeHoistedFunction(UniquedStringImpl* uid) const { return m_sloppyModeHoistedFunctions.contains(uid); } - VarStack& varStack() { return m_varStack; } - FunctionStack& functionStack() { return m_functionStack; } + VariableEnvironment& varDeclarations() { return m_varDeclarations; } int neededConstants() { @@ -1446,29 +1659,27 @@ namespace JSC { StatementNode* singleStatement() const; void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination); + + void analyzeModule(ModuleAnalyzer&); protected: - void setSource(const SourceCode& source) { m_source = source; } - ParserArena m_arena; - int m_startLineNumber; unsigned m_startStartOffset; unsigned m_startLineStartOffset; private: CodeFeatures m_features; + InnerArrowFunctionCodeFeatures m_innerArrowFunctionCodeFeatures; SourceCode m_source; - VarStack m_varStack; - FunctionStack m_functionStack; + VariableEnvironment m_varDeclarations; + UniquedStringImplPtrSet m_sloppyModeHoistedFunctions; int m_numConstants; SourceElements* m_statements; - IdentifierSet m_capturedVariables; }; class ProgramNode : public ScopeNode { public: - static const bool isFunctionNode = false; - static PassRefPtr<ProgramNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + ProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&); unsigned startColumn() const { return m_startColumn; } unsigned endColumn() const { return m_endColumn; } @@ -1476,18 +1687,14 @@ namespace JSC { static const bool scopeIsFunction = false; private: - ProgramNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; unsigned m_startColumn; unsigned m_endColumn; }; class EvalNode : public ScopeNode { public: - static const bool isFunctionNode = false; - static PassRefPtr<EvalNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + EvalNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&); ALWAYS_INLINE unsigned startColumn() const { return 0; } unsigned endColumn() const { return m_endColumn; } @@ -1495,200 +1702,565 @@ namespace JSC { static const bool scopeIsFunction = false; private: - EvalNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + unsigned m_endColumn; + }; + + class ModuleProgramNode : public ScopeNode { + public: + ModuleProgramNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&); - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } + + static const bool scopeIsFunction = false; + ModuleScopeData& moduleScopeData() + { + return m_moduleScopeData; + } + + private: + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + unsigned m_startColumn; unsigned m_endColumn; + Ref<ModuleScopeData> m_moduleScopeData; }; - class FunctionParameters : public RefCounted<FunctionParameters> { - WTF_MAKE_FAST_ALLOCATED; - WTF_MAKE_NONCOPYABLE(FunctionParameters); + class ModuleNameNode : public Node { + public: + ModuleNameNode(const JSTokenLocation&, const Identifier& moduleName); + + const Identifier& moduleName() { return m_moduleName; } + + private: + const Identifier& m_moduleName; + }; + + class ImportSpecifierNode : public Node { + public: + ImportSpecifierNode(const JSTokenLocation&, const Identifier& importedName, const Identifier& localName); + + const Identifier& importedName() { return m_importedName; } + const Identifier& localName() { return m_localName; } + + private: + const Identifier& m_importedName; + const Identifier& m_localName; + }; + + class ImportSpecifierListNode : public ParserArenaDeletable { + public: + typedef Vector<ImportSpecifierNode*, 3> Specifiers; + + const Specifiers& specifiers() const { return m_specifiers; } + void append(ImportSpecifierNode* specifier) + { + m_specifiers.append(specifier); + } + + private: + Specifiers m_specifiers; + }; + + class ModuleDeclarationNode : public StatementNode { + public: + virtual void analyzeModule(ModuleAnalyzer&) = 0; + bool isModuleDeclarationNode() const override { return true; } + + protected: + ModuleDeclarationNode(const JSTokenLocation&); + }; + + class ImportDeclarationNode : public ModuleDeclarationNode { + public: + ImportDeclarationNode(const JSTokenLocation&, ImportSpecifierListNode*, ModuleNameNode*); + + ImportSpecifierListNode* specifierList() const { return m_specifierList; } + ModuleNameNode* moduleName() const { return m_moduleName; } + + private: + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void analyzeModule(ModuleAnalyzer&) override; + + ImportSpecifierListNode* m_specifierList; + ModuleNameNode* m_moduleName; + }; + + class ExportAllDeclarationNode : public ModuleDeclarationNode { + public: + ExportAllDeclarationNode(const JSTokenLocation&, ModuleNameNode*); + + ModuleNameNode* moduleName() const { return m_moduleName; } + + private: + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void analyzeModule(ModuleAnalyzer&) override; + + ModuleNameNode* m_moduleName; + }; + + class ExportDefaultDeclarationNode : public ModuleDeclarationNode { + public: + ExportDefaultDeclarationNode(const JSTokenLocation&, StatementNode*, const Identifier& localName); + + const StatementNode& declaration() const { return *m_declaration; } + const Identifier& localName() const { return m_localName; } + + private: + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void analyzeModule(ModuleAnalyzer&) override; + StatementNode* m_declaration; + const Identifier& m_localName; + }; + + class ExportLocalDeclarationNode : public ModuleDeclarationNode { + public: + ExportLocalDeclarationNode(const JSTokenLocation&, StatementNode*); + + const StatementNode& declaration() const { return *m_declaration; } + + private: + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void analyzeModule(ModuleAnalyzer&) override; + StatementNode* m_declaration; + }; + + class ExportSpecifierNode : public Node { public: - static PassRefPtr<FunctionParameters> create(ParameterNode*); - ~FunctionParameters(); + ExportSpecifierNode(const JSTokenLocation&, const Identifier& localName, const Identifier& exportedName); - unsigned size() const { return m_size; } - DeconstructionPatternNode* at(unsigned index) { ASSERT(index < m_size); return patterns()[index]; } + const Identifier& exportedName() { return m_exportedName; } + const Identifier& localName() { return m_localName; } private: - FunctionParameters(ParameterNode*, unsigned size); + const Identifier& m_localName; + const Identifier& m_exportedName; + }; - DeconstructionPatternNode** patterns() { return &m_storage; } + class ExportSpecifierListNode : public ParserArenaDeletable { + public: + typedef Vector<ExportSpecifierNode*, 3> Specifiers; - unsigned m_size; - DeconstructionPatternNode* m_storage; + const Specifiers& specifiers() const { return m_specifiers; } + void append(ExportSpecifierNode* specifier) + { + m_specifiers.append(specifier); + } + + private: + Specifiers m_specifiers; }; - class FunctionBodyNode : public ScopeNode { + class ExportNamedDeclarationNode : public ModuleDeclarationNode { public: - static const bool isFunctionNode = true; - static FunctionBodyNode* create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, bool isStrictMode); - static PassRefPtr<FunctionBodyNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + ExportNamedDeclarationNode(const JSTokenLocation&, ExportSpecifierListNode*, ModuleNameNode*); + + ExportSpecifierListNode* specifierList() const { return m_specifierList; } + ModuleNameNode* moduleName() const { return m_moduleName; } + + private: + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void analyzeModule(ModuleAnalyzer&) override; + ExportSpecifierListNode* m_specifierList; + ModuleNameNode* m_moduleName { nullptr }; + }; - FunctionParameters* parameters() const { return m_parameters.get(); } - size_t parameterCount() const { return m_parameters->size(); } + class FunctionMetadataNode final : public Node, public ParserArenaDeletable { + public: + using ParserArenaDeletable::operator new; - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + FunctionMetadataNode( + ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, + unsigned startColumn, unsigned endColumn, int functionKeywordStart, + int functionNameStart, int parametersStart, bool isInStrictContext, + ConstructorKind, SuperBinding, unsigned parameterCount, + SourceParseMode, bool isArrowFunctionBodyExpression); - void finishParsing(const SourceCode&, ParameterNode*, const Identifier&, FunctionNameIsInScopeToggle); - void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&, FunctionNameIsInScopeToggle); + void finishParsing(const SourceCode&, const Identifier&, FunctionMode); + void overrideName(const Identifier& ident) { m_ident = ident; } const Identifier& ident() { return m_ident; } + void setEcmaName(const Identifier& ecmaName) { m_ecmaName = ecmaName; } + const Identifier& ecmaName() { return m_ident.isEmpty() ? m_ecmaName : m_ident; } void setInferredName(const Identifier& inferredName) { ASSERT(!inferredName.isNull()); m_inferredName = inferredName; } const Identifier& inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; } - bool functionNameIsInScope() { return m_functionNameIsInScopeToggle == FunctionNameIsInScope; } - FunctionNameIsInScopeToggle functionNameIsInScopeToggle() { return m_functionNameIsInScopeToggle; } + FunctionMode functionMode() { return m_functionMode; } - void setFunctionNameStart(int functionNameStart) { m_functionNameStart = functionNameStart; } 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; } + unsigned parameterCount() const { return m_parameterCount; } + SourceParseMode parseMode() const { return m_parseMode; } void setEndPosition(JSTextPosition); - static const bool scopeIsFunction = true; + const SourceCode& source() const { return m_source; } + const SourceCode& classSource() const { return m_classSource; } + void setClassSource(const SourceCode& source) { m_classSource = source; } - private: - FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, bool inStrictContext); - FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + int startStartOffset() const { return m_startStartOffset; } + bool isInStrictContext() const { return m_isInStrictContext; } + SuperBinding superBinding() { return static_cast<SuperBinding>(m_superBinding); } + ConstructorKind constructorKind() { return static_cast<ConstructorKind>(m_constructorKind); } + bool isArrowFunctionBodyExpression() const { return m_isArrowFunctionBodyExpression; } + void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset) + { + m_lastLine = lastLine; + m_position = JSTextPosition(firstLine, startOffset, lineStartOffset); + ASSERT(m_position.offset >= m_position.lineStartOffset); + } + unsigned lastLine() const { return m_lastLine; } + + protected: Identifier m_ident; + Identifier m_ecmaName; Identifier m_inferredName; - FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle; - RefPtr<FunctionParameters> m_parameters; + FunctionMode m_functionMode; + unsigned m_startColumn; + unsigned m_endColumn; + int m_functionKeywordStart; int m_functionNameStart; + int m_parametersStart; + SourceCode m_source; + SourceCode m_classSource; + int m_startStartOffset; + unsigned m_parameterCount; + int m_lastLine; + SourceParseMode m_parseMode; + unsigned m_isInStrictContext : 1; + unsigned m_superBinding : 1; + unsigned m_constructorKind : 2; + unsigned m_isArrowFunctionBodyExpression : 1; + }; + + class FunctionNode final : public ScopeNode { + public: + FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&, FunctionStack&&, VariableEnvironment&, UniquedStringImplPtrSet&&, FunctionParameters*, const SourceCode&, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants, RefPtr<ModuleScopeData>&&); + + FunctionParameters* parameters() const { return m_parameters; } + + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + bool isFunctionNode() const override { return true; } + + void finishParsing(const Identifier&, FunctionMode); + + const Identifier& ident() { return m_ident; } + + FunctionMode functionMode() const { return m_functionMode; } + + unsigned startColumn() const { return m_startColumn; } + unsigned endColumn() const { return m_endColumn; } + + static const bool scopeIsFunction = true; + + private: + Identifier m_ident; + FunctionMode m_functionMode; + FunctionParameters* m_parameters; unsigned m_startColumn; unsigned m_endColumn; }; - class FuncExprNode : public ExpressionNode { + class BaseFuncExprNode : public ExpressionNode { + public: + FunctionMetadataNode* metadata() { return m_metadata; } + + bool isBaseFuncExprNode() const override { return true; } + + protected: + BaseFuncExprNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&, FunctionMode); + + FunctionMetadataNode* m_metadata; + }; + + + class FuncExprNode : public BaseFuncExprNode { public: - FuncExprNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + FuncExprNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&); - FunctionBodyNode* body() { return m_body; } + protected: + FuncExprNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&, FunctionMode); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - virtual bool isFuncExprNode() const override { return true; } + bool isFuncExprNode() const override { return true; } + }; - FunctionBodyNode* m_body; + class ArrowFuncExprNode : public BaseFuncExprNode { + public: + ArrowFuncExprNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&); + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + bool isArrowFuncExprNode() const override { return true; } }; - class DeconstructionPatternNode : public RefCounted<DeconstructionPatternNode> { - WTF_MAKE_NONCOPYABLE(DeconstructionPatternNode); - WTF_MAKE_FAST_ALLOCATED; + class MethodDefinitionNode : public FuncExprNode { + public: + MethodDefinitionNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&); + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + }; + class YieldExprNode final : public ExpressionNode, public ThrowableExpressionData { public: + YieldExprNode(const JSTokenLocation&, ExpressionNode* argument, bool delegate); + + ExpressionNode* argument() const { return m_argument; } + bool delegate() const { return m_delegate; } + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_argument; + bool m_delegate; + }; + + class AwaitExprNode final : public ExpressionNode, public ThrowableExpressionData { + public: + AwaitExprNode(const JSTokenLocation&, ExpressionNode* argument); + + ExpressionNode* argument() const { return m_argument; } + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_argument; + }; + + class ClassExprNode final : public ExpressionNode, public VariableEnvironmentNode { + public: + using ParserArenaDeletable::operator new; + + ClassExprNode(const JSTokenLocation&, const Identifier&, const SourceCode& classSource, + VariableEnvironment& classEnvironment, ExpressionNode* constructorExpresssion, + ExpressionNode* parentClass, PropertyListNode* instanceMethods, PropertyListNode* staticMethods); + + const Identifier& name() { return m_name; } + const Identifier& ecmaName() { return m_ecmaName ? *m_ecmaName : m_name; } + void setEcmaName(const Identifier& name) { m_ecmaName = m_name.isNull() ? &name : &m_name; } + + bool hasStaticProperty(const Identifier& propName) { return m_staticMethods ? m_staticMethods->hasStaticallyNamedProperty(propName) : false; } + + private: + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + bool isClassExprNode() const override { return true; } + + SourceCode m_classSource; + const Identifier& m_name; + const Identifier* m_ecmaName; + ExpressionNode* m_constructorExpression; + ExpressionNode* m_classHeritage; + PropertyListNode* m_instanceMethods; + PropertyListNode* m_staticMethods; + }; + + class DestructuringPatternNode : public ParserArenaFreeable { + public: + virtual ~DestructuringPatternNode() { } virtual void collectBoundIdentifiers(Vector<Identifier>&) const = 0; virtual void bindValue(BytecodeGenerator&, RegisterID* source) const = 0; virtual void toString(StringBuilder&) const = 0; virtual bool isBindingNode() const { return false; } + virtual bool isRestParameter() const { return false; } virtual RegisterID* emitDirectBinding(BytecodeGenerator&, RegisterID*, ExpressionNode*) { return 0; } - virtual ~DeconstructionPatternNode() = 0; - protected: - DeconstructionPatternNode(VM*); + DestructuringPatternNode(); }; - class ArrayPatternNode : public DeconstructionPatternNode { + class ArrayPatternNode : public DestructuringPatternNode, public ThrowableExpressionData, public ParserArenaDeletable { public: - static PassRefPtr<ArrayPatternNode> create(VM*); - void appendIndex(const JSTokenLocation&, DeconstructionPatternNode* node) + using ParserArenaDeletable::operator new; + + ArrayPatternNode(); + enum class BindingType { + Elision, + Element, + RestElement + }; + + void appendIndex(BindingType bindingType, const JSTokenLocation&, DestructuringPatternNode* node, ExpressionNode* defaultValue) { - m_targetPatterns.append(node); + m_targetPatterns.append({ bindingType, node, defaultValue }); } private: - ArrayPatternNode(VM*); - virtual void collectBoundIdentifiers(Vector<Identifier>&) const override; - virtual void bindValue(BytecodeGenerator&, RegisterID*) const override; - virtual RegisterID* emitDirectBinding(BytecodeGenerator&, RegisterID* dst, ExpressionNode*) override; - virtual void toString(StringBuilder&) const override; + struct Entry { + BindingType bindingType; + DestructuringPatternNode* pattern; + ExpressionNode* defaultValue; + }; + void collectBoundIdentifiers(Vector<Identifier>&) const override; + void bindValue(BytecodeGenerator&, RegisterID*) const override; + RegisterID* emitDirectBinding(BytecodeGenerator&, RegisterID* dst, ExpressionNode*) override; + void toString(StringBuilder&) const override; - Vector<RefPtr<DeconstructionPatternNode>> m_targetPatterns; + Vector<Entry> m_targetPatterns; }; - class ObjectPatternNode : public DeconstructionPatternNode { + class ObjectPatternNode : public DestructuringPatternNode, public ParserArenaDeletable { public: - static PassRefPtr<ObjectPatternNode> create(VM*); - void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DeconstructionPatternNode* pattern) + using ParserArenaDeletable::operator new; + + ObjectPatternNode(); + void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue) { - m_targetPatterns.append(Entry(identifier, wasString, pattern)); + m_targetPatterns.append(Entry{ identifier, nullptr, wasString, pattern, defaultValue }); } - + + void appendEntry(const JSTokenLocation&, ExpressionNode* propertyExpression, DestructuringPatternNode* pattern, ExpressionNode* defaultValue) + { + m_targetPatterns.append(Entry{ Identifier(), propertyExpression, false, pattern, defaultValue }); + } + private: - ObjectPatternNode(VM*); - virtual void collectBoundIdentifiers(Vector<Identifier>&) const override; - virtual void bindValue(BytecodeGenerator&, RegisterID*) const override; - virtual void toString(StringBuilder&) const override; + void collectBoundIdentifiers(Vector<Identifier>&) const override; + void bindValue(BytecodeGenerator&, RegisterID*) const override; + void toString(StringBuilder&) const override; struct Entry { - Entry(const Identifier& propertyName, bool wasString, DeconstructionPatternNode* pattern) - : propertyName(propertyName) - , wasString(wasString) - , pattern(pattern) - { - } - Identifier propertyName; + const Identifier& propertyName; + ExpressionNode* propertyExpression; bool wasString; - RefPtr<DeconstructionPatternNode> pattern; + DestructuringPatternNode* pattern; + ExpressionNode* defaultValue; }; Vector<Entry> m_targetPatterns; }; - class BindingNode : public DeconstructionPatternNode { + class BindingNode : public DestructuringPatternNode { public: - static PassRefPtr<BindingNode> create(VM*, const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end); + BindingNode(const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end, AssignmentContext); const Identifier& boundProperty() const { return m_boundProperty; } const JSTextPosition& divotStart() const { return m_divotStart; } const JSTextPosition& divotEnd() const { return m_divotEnd; } private: - BindingNode(VM*, const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end); - - virtual void collectBoundIdentifiers(Vector<Identifier>&) const override; - virtual void bindValue(BytecodeGenerator&, RegisterID*) const override; - virtual void toString(StringBuilder&) const override; + void collectBoundIdentifiers(Vector<Identifier>&) const override; + void bindValue(BytecodeGenerator&, RegisterID*) const override; + void toString(StringBuilder&) const override; - virtual bool isBindingNode() const override { return true; } + bool isBindingNode() const override { return true; } JSTextPosition m_divotStart; JSTextPosition m_divotEnd; - Identifier m_boundProperty; + const Identifier& m_boundProperty; + AssignmentContext m_bindingContext; }; - class DeconstructingAssignmentNode : public ExpressionNode, public ParserArenaDeletable { + class RestParameterNode : public DestructuringPatternNode { public: - DeconstructingAssignmentNode(const JSTokenLocation&, PassRefPtr<DeconstructionPatternNode>, ExpressionNode*); - DeconstructionPatternNode* bindings() { return m_bindings.get(); } - - using ParserArenaDeletable::operator new; + RestParameterNode(DestructuringPatternNode*, unsigned numParametersToSkip); + + bool isRestParameter() const override { return true; } + + void emit(BytecodeGenerator&); + + private: + void collectBoundIdentifiers(Vector<Identifier>&) const override; + void bindValue(BytecodeGenerator&, RegisterID*) const override; + void toString(StringBuilder&) const override; + + DestructuringPatternNode* m_pattern; + unsigned m_numParametersToSkip; + }; + + class AssignmentElementNode : public DestructuringPatternNode { + public: + AssignmentElementNode(ExpressionNode* assignmentTarget, const JSTextPosition& start, const JSTextPosition& end); + const ExpressionNode* assignmentTarget() { return m_assignmentTarget; } + + const JSTextPosition& divotStart() const { return m_divotStart; } + const JSTextPosition& divotEnd() const { return m_divotEnd; } private: - virtual bool isLocation() const override { return true; } - virtual bool isDeconstructionNode() const override { return true; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void collectBoundIdentifiers(Vector<Identifier>&) const override; + void bindValue(BytecodeGenerator&, RegisterID*) const override; + void toString(StringBuilder&) const override; - RefPtr<DeconstructionPatternNode> m_bindings; + JSTextPosition m_divotStart; + JSTextPosition m_divotEnd; + ExpressionNode* m_assignmentTarget; + }; + + class DestructuringAssignmentNode : public ExpressionNode { + public: + DestructuringAssignmentNode(const JSTokenLocation&, DestructuringPatternNode*, ExpressionNode*); + DestructuringPatternNode* bindings() { return m_bindings; } + + private: + bool isAssignmentLocation() const override { return true; } + bool isDestructuringNode() const override { return true; } + RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + DestructuringPatternNode* m_bindings; ExpressionNode* m_initializer; }; + class FunctionParameters : public ParserArenaDeletable { + public: + FunctionParameters(); + ALWAYS_INLINE unsigned size() const { return m_patterns.size(); } + ALWAYS_INLINE std::pair<DestructuringPatternNode*, ExpressionNode*> at(unsigned index) { return m_patterns[index]; } + ALWAYS_INLINE void append(DestructuringPatternNode* pattern, ExpressionNode* defaultValue) + { + ASSERT(pattern); + + // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation + // This implements IsSimpleParameterList in the Ecma 2015 spec. + // If IsSimpleParameterList is false, we will create a strict-mode like arguments object. + // IsSimpleParameterList is false if the argument list contains any default parameter values, + // a rest parameter, or any destructuring patterns. + // If we do have default parameters, destructuring parameters, or a rest parameter, our parameters will be allocated in a different scope. + + bool hasDefaultParameterValue = defaultValue; + bool isSimpleParameter = !hasDefaultParameterValue && pattern->isBindingNode(); + m_isSimpleParameterList &= isSimpleParameter; + + m_patterns.append(std::make_pair(pattern, defaultValue)); + } + ALWAYS_INLINE bool isSimpleParameterList() const { return m_isSimpleParameterList; } + + private: + + Vector<std::pair<DestructuringPatternNode*, ExpressionNode*>, 3> m_patterns; + bool m_isSimpleParameterList { true }; + }; + class FuncDeclNode : public StatementNode { public: - FuncDeclNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + FuncDeclNode(const JSTokenLocation&, const Identifier&, FunctionMetadataNode*, const SourceCode&); - FunctionBodyNode* body() { return m_body; } + bool isFuncDeclNode() const override { return true; } + FunctionMetadataNode* metadata() { return m_metadata; } private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; - FunctionBodyNode* m_body; + FunctionMetadataNode* m_metadata; + }; + + class ClassDeclNode final : public StatementNode { + public: + ClassDeclNode(const JSTokenLocation&, ExpressionNode* classExpression); + + private: + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + + ExpressionNode* m_classDeclaration; }; class CaseClauseNode : public ParserArenaFreeable { @@ -1698,10 +2270,12 @@ namespace JSC { ExpressionNode* expr() const { return m_expr; } void emitBytecode(BytecodeGenerator&, RegisterID* destination); + void setStartOffset(int offset) { m_startOffset = offset; } private: ExpressionNode* m_expr; SourceElements* m_statements; + int m_startOffset; }; class ClauseListNode : public ParserArenaFreeable { @@ -1731,12 +2305,14 @@ namespace JSC { ClauseListNode* m_list2; }; - class SwitchNode : public StatementNode { + class SwitchNode : public StatementNode, public VariableEnvironmentNode { public: - SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*); + using ParserArenaDeletable::operator new; + + SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*, VariableEnvironment&, FunctionStack&&); private: - virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; + void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; ExpressionNode* m_expr; CaseBlockNode* m_block; @@ -1757,21 +2333,9 @@ namespace JSC { ArgumentListNode* tail; }; - struct ConstDeclList { - ConstDeclNode* head; - ConstDeclNode* tail; - }; - - struct ParameterList { - ParameterNode* head; - ParameterNode* tail; - }; - struct ClauseList { ClauseListNode* head; ClauseListNode* tail; }; } // namespace JSC - -#endif // Nodes_h |