finally blocks should not set the exception stack trace when re-throwing the exception.
[WebKit-https.git] / Source / JavaScriptCore / parser / Nodes.h
index d779a17..92f1a21 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013, 2015 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
@@ -76,7 +76,7 @@ namespace JSC {
     };
     inline FallThroughMode invert(FallThroughMode fallThroughMode) { return static_cast<FallThroughMode>(!fallThroughMode); }
 
-    typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet;
+    typedef HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> IdentifierSet;
 
     namespace DeclarationStacks {
         enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
@@ -94,7 +94,7 @@ namespace JSC {
     public:
         // ParserArenaFreeable objects are are freed when the arena is deleted.
         // Destructors are not called. Clients must not call delete on such objects.
-        void* operator new(size_t, VM*);
+        void* operator new(size_t, ParserArena&);
     };
 
     class ParserArenaDeletable {
@@ -103,24 +103,20 @@ namespace JSC {
 
         // ParserArenaDeletable objects are deleted when the arena is deleted.
         // Clients must not call delete directly on such objects.
-        void* operator new(size_t, VM*);
+        void* operator new(size_t, ParserArena&);
     };
 
-    template <typename T>
-    struct ParserArenaData : ParserArenaDeletable {
-        T data;
-    };
-
-    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 +126,17 @@ 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; }
 
     protected:
         JSTextPosition m_position;
+        int m_endOffset;
     };
 
     class ExpressionNode : public Node {
@@ -152,6 +152,7 @@ namespace JSC {
         virtual bool isPure(BytecodeGenerator&) const { return false; }        
         virtual bool isConstant() const { return false; }
         virtual bool isLocation() const { return false; }
+        virtual bool isAssignmentLocation() const { return isLocation(); }
         virtual bool isResolveNode() const { return false; }
         virtual bool isBracketAccessorNode() const { return false; }
         virtual bool isDotAccessorNode() const { return false; }
@@ -163,6 +164,7 @@ namespace JSC {
         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);
 
@@ -182,17 +184,21 @@ namespace JSC {
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0;
 
         void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset);
-        unsigned firstLine() const { return lineNo(); }
         unsigned lastLine() const { return m_lastLine; }
 
+        StatementNode* next() { return m_next; }
+        void setNext(StatementNode* next) { m_next = next; }
+
         virtual bool isEmptyStatement() const { return false; }
         virtual bool isReturnNode() const { return false; }
         virtual bool isExprStatement() const { return false; }
         virtual bool isBreak() const { return false; }
         virtual bool isContinue() const { return false; }
         virtual bool isBlock() const { return false; }
+        virtual bool isFuncDeclNode() const { return false; }
 
     protected:
+        StatementNode* m_next;
         int m_lastLine;
     };
 
@@ -231,16 +237,32 @@ namespace JSC {
     class NumberNode : public ConstantNode {
     public:
         NumberNode(const JSTokenLocation&, double value);
-        double value() { return m_value; }
-        void setValue(double value) { m_value = value; }
+        double value() const { return m_value; }
+        virtual bool isIntegerNode() const = 0;
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override final;
 
     private:
-        virtual bool isNumber() const override { return true; }
+        virtual bool isNumber() const override final { return true; }
         virtual JSValue jsValue(BytecodeGenerator&) const override { return jsNumber(m_value); }
 
         double m_value;
     };
 
+    class DoubleNode : public NumberNode {
+    public:
+        DoubleNode(const JSTokenLocation&, double value);
+
+    private:
+        virtual bool isIntegerNode() const override { return false; }
+    };
+
+    // An integer node represent a number represented as an integer (e.g. 42 instead of 42., 42.0, 42e0)
+    class IntegerNode : public DoubleNode {
+    public:
+        IntegerNode(const JSTokenLocation&, double value);
+        virtual bool isIntegerNode() const override final { return true; }
+    };
+
     class StringNode : public ConstantNode {
     public:
         StringNode(const JSTokenLocation&, const Identifier&);
@@ -252,7 +274,7 @@ namespace JSC {
 
         const Identifier& m_value;
     };
-    
+
     class ThrowableExpressionData {
     public:
         ThrowableExpressionData()
@@ -405,6 +427,76 @@ namespace JSC {
         uint16_t m_subexpressionLineStartOffset;
     };
 
+#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
+    class TemplateExpressionListNode : public ParserArenaFreeable {
+    public:
+        TemplateExpressionListNode(ExpressionNode*);
+        TemplateExpressionListNode(TemplateExpressionListNode*, ExpressionNode*);
+
+        ExpressionNode* value() { return m_node; }
+        TemplateExpressionListNode* next() { return m_next; }
+
+    private:
+        TemplateExpressionListNode* m_next { nullptr };
+        ExpressionNode* m_node { nullptr };
+    };
+
+    class TemplateStringNode : public ExpressionNode {
+    public:
+        TemplateStringNode(const JSTokenLocation&, const Identifier& cooked, const Identifier& raw);
+
+        const Identifier& cooked() { return m_cooked; }
+        const Identifier& raw() { return m_raw; }
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        const Identifier& m_cooked;
+        const Identifier& m_raw;
+    };
+
+    class TemplateStringListNode : public ParserArenaFreeable {
+    public:
+        TemplateStringListNode(TemplateStringNode*);
+        TemplateStringListNode(TemplateStringListNode*, TemplateStringNode*);
+
+        TemplateStringNode* value() { return m_node; }
+        TemplateStringListNode* next() { return m_next; }
+
+    private:
+        TemplateStringListNode* m_next { nullptr };
+        TemplateStringNode* m_node { nullptr };
+    };
+
+    class TemplateLiteralNode : public ExpressionNode {
+    public:
+        TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*);
+        TemplateLiteralNode(const JSTokenLocation&, TemplateStringListNode*, TemplateExpressionListNode*);
+
+        TemplateStringListNode* templateStrings() const { return m_templateStrings; }
+        TemplateExpressionListNode* templateExpressions() const { return m_templateExpressions; }
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        TemplateStringListNode* m_templateStrings;
+        TemplateExpressionListNode* m_templateExpressions;
+    };
+
+    class TaggedTemplateNode : public ExpressionNode, public ThrowableExpressionData {
+    public:
+        TaggedTemplateNode(const JSTokenLocation&, ExpressionNode*, TemplateLiteralNode*);
+
+        TemplateLiteralNode* templateLiteral() const { return m_templateLiteral; }
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        ExpressionNode* m_tag;
+        TemplateLiteralNode* m_templateLiteral;
+    };
+#endif
+
     class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
     public:
         RegExpNode(const JSTokenLocation&, const Identifier& pattern, const Identifier& flags);
@@ -418,9 +510,20 @@ namespace JSC {
 
     class ThisNode : public ExpressionNode {
     public:
-        ThisNode(const JSTokenLocation&);
+        ThisNode(const JSTokenLocation&, ThisTDZMode);
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        bool m_shouldAlwaysEmitTDZCheck;
+    };
+
+    class SuperNode final : public ExpressionNode {
+    public:
+        SuperNode(const JSTokenLocation&);
 
     private:
+        virtual bool isSuperNode() const override { return true; }
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     };
 
@@ -462,7 +565,7 @@ namespace JSC {
         ArrayNode(const JSTokenLocation&, ElementNode*);
         ArrayNode(const JSTokenLocation&, int elision, ElementNode*);
 
-        ArgumentListNode* toArgumentList(VM*, int, int) const;
+        ArgumentListNode* toArgumentList(ParserArena&, int, int) const;
 
         ElementNode* elements() const { ASSERT(isSimpleArray()); return m_element; }
     private:
@@ -477,23 +580,27 @@ namespace JSC {
 
     class PropertyNode : public ParserArenaFreeable {
     public:
-        enum Type { Constant = 1, Getter = 2, Setter = 4 };
+        enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16 };
+        enum PutType { Unknown, KnownDirect };
+
+        PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding);
+        PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType);
 
-        PropertyNode(VM*, const Identifier&, ExpressionNode*, Type);
-        PropertyNode(VM*, double, ExpressionNode*, Type);
-        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; }
+        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;
     };
 
     class PropertyListNode : public ExpressionNode {
@@ -501,9 +608,10 @@ namespace JSC {
         PropertyListNode(const JSTokenLocation&, PropertyNode*);
         PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*);
 
+    private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+        void emitPutConstantProperty(BytecodeGenerator&, RegisterID*, PropertyNode&);
 
-    private:
         PropertyNode* m_node;
         PropertyListNode* m_next;
     };
@@ -635,7 +743,7 @@ 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;
@@ -643,6 +751,7 @@ namespace JSC {
         ExpressionNode* m_base;
         ExpressionNode* m_subscript;
         ArgumentsNode* m_args;
+        bool m_subscriptHasAssignments;
     };
 
     class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData {
@@ -658,6 +767,26 @@ namespace JSC {
         ArgumentsNode* m_args;
     };
 
+    class BytecodeIntrinsicNode : public ExpressionNode, public ThrowableExpressionData {
+    public:
+        typedef RegisterID* (BytecodeIntrinsicNode::* EmitterType)(BytecodeGenerator&, RegisterID*);
+
+        BytecodeIntrinsicNode(const JSTokenLocation&, EmitterType, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+
+        const Identifier& identifier() const { return m_ident; }
+
+#define JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS(name) RegisterID* emit_intrinsic_##name(BytecodeGenerator&, RegisterID*);
+        JSC_COMMON_BYTECODE_INTRINSICS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS)
+#undef JSC_DECLARE_BYTECODE_INTRINSIC_FUNCTIONS
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        EmitterType m_emitter;
+        const Identifier& m_ident;
+        ArgumentsNode* m_args;
+    };
+
     class CallFunctionCallDotNode : public FunctionCallDotNode {
     public:
         CallFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
@@ -1039,7 +1168,7 @@ namespace JSC {
         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;
     };
@@ -1081,7 +1210,7 @@ namespace JSC {
         ExpressionNode* m_base;
         const Identifier& m_ident;
         ExpressionNode* m_right;
-        Operator m_operator : 31;
+        unsigned m_operator : 31;
         bool m_rightHasAssignments : 1;
     };
 
@@ -1093,21 +1222,19 @@ namespace JSC {
         virtual 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;
 
-        ExpressionVector m_expressions;
+        ExpressionNode* m_expr;
+        CommaNode* m_next;
     };
     
     class ConstDeclNode : public ExpressionNode {
@@ -1140,7 +1267,7 @@ namespace JSC {
         ConstDeclNode* m_next;
     };
 
-    class SourceElements : public ParserArenaDeletable {
+    class SourceElements final : public ParserArenaFreeable {
     public:
         SourceElements();
 
@@ -1152,7 +1279,8 @@ namespace JSC {
         void emitBytecode(BytecodeGenerator&, RegisterID* destination);
 
     private:
-        Vector<StatementNode*> m_statements;
+        StatementNode* m_head;
+        StatementNode* m_tail;
     };
 
     class BlockNode : public StatementNode {
@@ -1211,6 +1339,17 @@ namespace JSC {
         ExpressionNode* m_expr;
     };
 
+    class EmptyVarExpression : public ExpressionNode {
+    public:
+        EmptyVarExpression(const JSTokenLocation&, const Identifier&);
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        const Identifier& m_ident;
+    };
+
+
     class IfElseNode : public StatementNode {
     public:
         IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock);
@@ -1265,7 +1404,6 @@ namespace JSC {
     class EnumerationNode : public StatementNode, public ThrowableExpressionData {
     public:
         EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*);
-        EnumerationNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*);
         
     protected:
         ExpressionNode* m_lexpr;
@@ -1276,16 +1414,18 @@ namespace JSC {
     class ForInNode : public EnumerationNode {
     public:
         ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*);
-        ForInNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*);
 
     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*);
-        ForOfNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*);
         
     private:
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
@@ -1293,7 +1433,6 @@ namespace JSC {
 
     class ContinueNode : public StatementNode, public ThrowableExpressionData {
     public:
-        ContinueNode(VM*, const JSTokenLocation&);
         ContinueNode(const JSTokenLocation&, const Identifier&);
         Label* trivialTarget(BytecodeGenerator&);
         
@@ -1306,7 +1445,6 @@ namespace JSC {
 
     class BreakNode : public StatementNode, public ThrowableExpressionData {
     public:
-        BreakNode(VM*, const JSTokenLocation&);
         BreakNode(const JSTokenLocation&, const Identifier&);
         Label* trivialTarget(BytecodeGenerator&);
         
@@ -1373,7 +1511,7 @@ namespace JSC {
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
         StatementNode* m_tryBlock;
-        const Identifier& m_exceptionIdent;
+        const Identifier& m_thrownValueIdent;
         StatementNode* m_catchBlock;
         StatementNode* m_finallyBlock;
     };
@@ -1391,24 +1529,15 @@ namespace JSC {
         ParameterNode* m_next;
     };
 
-    class ScopeNode : public StatementNode, public ParserArenaRefCounted {
+    class ScopeNode : public StatementNode, public ParserArenaRoot {
     public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
-        ScopeNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, bool inStrictContext);
-        ScopeNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants);
+        ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, bool inStrictContext);
+        ScopeNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VarStack&, FunctionStack&, IdentifierSet&, CodeFeatures, int numConstants);
 
-        using ParserArenaRefCounted::operator new;
-
-        void destroyData()
-        {
-            m_arena.reset();
-            m_varStack.clear();
-            m_functionStack.clear();
-            m_statements = 0;
-            m_capturedVariables.clear();
-        }
+        using ParserArenaRoot::operator new;
 
         const SourceCode& source() const { return m_source; }
         const String& sourceURL() const { return m_source.provider()->url(); }
@@ -1424,6 +1553,7 @@ namespace JSC {
         bool usesEval() const { return m_features & EvalFeature; }
         bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); }
         bool modifiesParameter() const { return m_features & ModifiedParameterFeature; }
+        bool modifiesArguments() const { return m_features & (EvalFeature | ModifiedArgumentsFeature); }
         bool isStrictMode() const { return m_features & StrictModeFeature; }
         void setUsesArguments() { m_features |= ArgumentsFeature; }
         bool usesThis() const { return m_features & ThisFeature; }
@@ -1431,7 +1561,9 @@ namespace JSC {
         bool needsActivation() const { return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); }
         bool hasCapturedVariables() const { return !!m_capturedVariables.size(); }
         size_t capturedVariableCount() const { return m_capturedVariables.size(); }
-        bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); }
+        const IdentifierSet& capturedVariables() const { return m_capturedVariables; }
+        bool captures(UniquedStringImpl* uid) { return m_capturedVariables.contains(uid); }
+        bool captures(const Identifier& ident) { return captures(ident.impl()); }
 
         VarStack& varStack() { return m_varStack; }
         FunctionStack& functionStack() { return m_functionStack; }
@@ -1446,11 +1578,10 @@ namespace JSC {
         StatementNode* singleStatement() const;
 
         void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination);
+        
+        void setClosedVariables(Vector<RefPtr<UniquedStringImpl>>&&) { }
 
     protected:
-        void setSource(const SourceCode& source) { m_source = source; }
-        ParserArena m_arena;
-
         int m_startLineNumber;
         unsigned m_startStartOffset;
         unsigned m_startLineStartOffset;
@@ -1467,27 +1598,26 @@ namespace JSC {
 
     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*, VarStack&, FunctionStack&, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         unsigned startColumn() const { return m_startColumn; }
         unsigned endColumn() const { return m_endColumn; }
 
         static const bool scopeIsFunction = false;
 
-    private:
-        ProgramNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        void setClosedVariables(Vector<RefPtr<UniquedStringImpl>>&&);
+        const Vector<RefPtr<UniquedStringImpl>>& closedVariables() const { return m_closedVariables; }
 
+    private:
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
-
+        Vector<RefPtr<UniquedStringImpl>> m_closedVariables;
         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*, VarStack&, FunctionStack&, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         ALWAYS_INLINE unsigned startColumn() const { return 0; }
         unsigned endColumn() const { return m_endColumn; }
@@ -1495,8 +1625,6 @@ 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);
-
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
         unsigned m_endColumn;
@@ -1521,45 +1649,82 @@ namespace JSC {
         DeconstructionPatternNode* m_storage;
     };
 
-    class FunctionBodyNode : public ScopeNode {
+    class FunctionBodyNode final : public StatementNode, public ParserArenaDeletable {
     public:
-        static const bool isFunctionNode = true;
-        static FunctionBodyNode* create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, 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);
+        using ParserArenaDeletable::operator new;
+
+        FunctionBodyNode(
+            ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, 
+            unsigned startColumn, unsigned endColumn, int functionKeywordStart, 
+            int functionNameStart, int parametersStart, bool isInStrictContext, 
+            ConstructorKind);
 
         FunctionParameters* parameters() const { return m_parameters.get(); }
-        size_t parameterCount() const { return m_parameters->size(); }
 
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
-        void finishParsing(const SourceCode&, ParameterNode*, const Identifier&, FunctionNameIsInScopeToggle);
-        void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&, FunctionNameIsInScopeToggle);
+        void finishParsing(const SourceCode&, ParameterNode*, const Identifier&, FunctionMode);
         
+        void overrideName(const Identifier& ident) { m_ident = ident; }
         const Identifier& ident() { return m_ident; }
         void setInferredName(const Identifier& inferredName) { ASSERT(!inferredName.isNull()); m_inferredName = inferredName; }
         const Identifier& inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; }
 
-        bool functionNameIsInScope() { return m_functionNameIsInScopeToggle == FunctionNameIsInScope; }
-        FunctionNameIsInScopeToggle functionNameIsInScopeToggle() { return m_functionNameIsInScopeToggle; }
+        FunctionMode functionMode() { return m_functionMode; }
 
-        void 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; }
 
         void setEndPosition(JSTextPosition);
 
-        static const bool scopeIsFunction = true;
+        const SourceCode& source() const { return m_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; }
+        ConstructorKind constructorKind() { return static_cast<ConstructorKind>(m_constructorKind); }
 
+    protected:
         Identifier m_ident;
         Identifier m_inferredName;
-        FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
+        FunctionMode m_functionMode;
         RefPtr<FunctionParameters> m_parameters;
+        unsigned m_startColumn;
+        unsigned m_endColumn;
+        int m_functionKeywordStart;
         int m_functionNameStart;
+        int m_parametersStart;
+        SourceCode m_source;
+        int m_startStartOffset;
+        unsigned m_isInStrictContext : 1;
+        unsigned m_constructorKind : 2;
+    };
+
+    class FunctionNode final : public ScopeNode {
+    public:
+        FunctionNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack&, FunctionStack&, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+
+        FunctionParameters* parameters() const { return m_parameters.get(); }
+
+        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&, FunctionMode);
+        
+        const Identifier& ident() { return m_ident; }
+
+        FunctionMode functionMode() { return m_functionMode; }
+
+        unsigned startColumn() const { return m_startColumn; }
+        unsigned endColumn() const { return m_endColumn; }
+
+        static const bool scopeIsFunction = true;
+
+    private:
+        Identifier m_ident;
+        FunctionMode m_functionMode;
+        RefPtr<FunctionParameters> m_parameters;
         unsigned m_startColumn;
         unsigned m_endColumn;
     };
@@ -1578,6 +1743,25 @@ namespace JSC {
         FunctionBodyNode* m_body;
     };
 
+#if ENABLE(ES6_CLASS_SYNTAX)
+    class ClassExprNode final : public ExpressionNode {
+    public:
+        ClassExprNode(const JSTokenLocation&, const Identifier&, ExpressionNode* constructorExpresssion,
+            ExpressionNode* parentClass, PropertyListNode* instanceMethods, PropertyListNode* staticMethods);
+
+        const Identifier& name() { return m_name; }
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        const Identifier& m_name;
+        ExpressionNode* m_constructorExpression;
+        ExpressionNode* m_classHeritage;
+        PropertyListNode* m_instanceMethods;
+        PropertyListNode* m_staticMethods;
+    };
+#endif
+
     class DeconstructionPatternNode : public RefCounted<DeconstructionPatternNode> {
         WTF_MAKE_NONCOPYABLE(DeconstructionPatternNode);
         WTF_MAKE_FAST_ALLOCATED;
@@ -1593,19 +1777,19 @@ namespace JSC {
         virtual ~DeconstructionPatternNode() = 0;
         
     protected:
-        DeconstructionPatternNode(VM*);
+        DeconstructionPatternNode();
     };
 
     class ArrayPatternNode : public DeconstructionPatternNode {
     public:
-        static PassRefPtr<ArrayPatternNode> create(VM*);
+        static PassRefPtr<ArrayPatternNode> create();
         void appendIndex(const JSTokenLocation&, DeconstructionPatternNode* node)
         {
             m_targetPatterns.append(node);
         }
 
     private:
-        ArrayPatternNode(VM*);
+        ArrayPatternNode();
         virtual void collectBoundIdentifiers(Vector<Identifier>&) const override;
         virtual void bindValue(BytecodeGenerator&, RegisterID*) const override;
         virtual RegisterID* emitDirectBinding(BytecodeGenerator&, RegisterID* dst, ExpressionNode*) override;
@@ -1616,14 +1800,14 @@ namespace JSC {
     
     class ObjectPatternNode : public DeconstructionPatternNode {
     public:
-        static PassRefPtr<ObjectPatternNode> create(VM*);
+        static PassRefPtr<ObjectPatternNode> create();
         void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DeconstructionPatternNode* pattern)
         {
             m_targetPatterns.append(Entry(identifier, wasString, pattern));
         }
         
     private:
-        ObjectPatternNode(VM*);
+        ObjectPatternNode();
         virtual void collectBoundIdentifiers(Vector<Identifier>&) const override;
         virtual void bindValue(BytecodeGenerator&, RegisterID*) const override;
         virtual void toString(StringBuilder&) const override;
@@ -1643,14 +1827,14 @@ namespace JSC {
 
     class BindingNode : public DeconstructionPatternNode {
     public:
-        static PassRefPtr<BindingNode> create(VM*, const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end);
+        static PassRefPtr<BindingNode> create(const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end);
         const Identifier& boundProperty() const { return m_boundProperty; }
 
         const JSTextPosition& divotStart() const { return m_divotStart; }
         const JSTextPosition& divotEnd() const { return m_divotEnd; }
         
     private:
-        BindingNode(VM*, const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end);
+        BindingNode(const Identifier& boundProperty, const JSTextPosition& start, const JSTextPosition& end);
 
         virtual void collectBoundIdentifiers(Vector<Identifier>&) const override;
         virtual void bindValue(BytecodeGenerator&, RegisterID*) const override;
@@ -1671,7 +1855,7 @@ namespace JSC {
         using ParserArenaDeletable::operator new;
 
     private:
-        virtual bool isLocation() const override { return true; }
+        virtual bool isAssignmentLocation() const override { return true; }
         virtual bool isDeconstructionNode() const override { return true; }
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
@@ -1683,6 +1867,7 @@ namespace JSC {
     public:
         FuncDeclNode(const JSTokenLocation&, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0);
 
+        virtual bool isFuncDeclNode() const override { return true; }
         FunctionBodyNode* body() { return m_body; }
 
     private:
@@ -1691,6 +1876,18 @@ namespace JSC {
         FunctionBodyNode* m_body;
     };
 
+#if ENABLE(ES6_CLASS_SYNTAX)
+    class ClassDeclNode final : public StatementNode {
+    public:
+        ClassDeclNode(const JSTokenLocation&, ExpressionNode* classExpression);
+
+    private:
+        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        ExpressionNode* m_classDeclaration;
+    };
+#endif
+
     class CaseClauseNode : public ParserArenaFreeable {
     public:
         CaseClauseNode(ExpressionNode*, SourceElements* = 0);
@@ -1698,10 +1895,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 {