summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptCore/parser/Nodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/parser/Nodes.h')
-rw-r--r--Source/JavaScriptCore/parser/Nodes.h1617
1 files changed, 1617 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h
new file mode 100644
index 0000000..b8e9cdf
--- /dev/null
+++ b/Source/JavaScriptCore/parser/Nodes.h
@@ -0,0 +1,1617 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Nodes_h
+#define Nodes_h
+
+#include "Error.h"
+#include "JITCode.h"
+#include "Opcode.h"
+#include "ParserArena.h"
+#include "ResultType.h"
+#include "SourceCode.h"
+#include "SymbolTable.h"
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+ class ArgumentListNode;
+ class BytecodeGenerator;
+ class FunctionBodyNode;
+ class Label;
+ class PropertyListNode;
+ class ReadModifyResolveNode;
+ class RegisterID;
+ class ScopeChainNode;
+ class ScopeNode;
+
+ typedef unsigned CodeFeatures;
+
+ const CodeFeatures NoFeatures = 0;
+ const CodeFeatures EvalFeature = 1 << 0;
+ const CodeFeatures ClosureFeature = 1 << 1;
+ const CodeFeatures AssignFeature = 1 << 2;
+ const CodeFeatures ArgumentsFeature = 1 << 3;
+ const CodeFeatures WithFeature = 1 << 4;
+ const CodeFeatures CatchFeature = 1 << 5;
+ const CodeFeatures ThisFeature = 1 << 6;
+ const CodeFeatures StrictModeFeature = 1 << 7;
+ const CodeFeatures ShadowsArgumentsFeature = 1 << 8;
+
+
+ const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature;
+
+ enum Operator {
+ OpEqual,
+ OpPlusEq,
+ OpMinusEq,
+ OpMultEq,
+ OpDivEq,
+ OpPlusPlus,
+ OpMinusMinus,
+ OpAndEq,
+ OpXOrEq,
+ OpOrEq,
+ OpModEq,
+ OpLShift,
+ OpRShift,
+ OpURShift
+ };
+
+ enum LogicalOperator {
+ OpLogicalAnd,
+ OpLogicalOr
+ };
+
+ typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet;
+
+ namespace DeclarationStacks {
+ enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
+ typedef Vector<std::pair<const Identifier*, unsigned> > VarStack;
+ typedef Vector<FunctionBodyNode*> FunctionStack;
+ }
+
+ struct SwitchInfo {
+ enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString };
+ uint32_t bytecodeOffset;
+ SwitchType switchType;
+ };
+
+ 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, JSGlobalData*);
+ };
+
+ class ParserArenaDeletable {
+ public:
+ virtual ~ParserArenaDeletable() { }
+
+ // ParserArenaDeletable objects are deleted when the arena is deleted.
+ // Clients must not call delete directly on such objects.
+ void* operator new(size_t, JSGlobalData*);
+ };
+
+ class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> {
+ protected:
+ ParserArenaRefCounted(JSGlobalData*);
+
+ public:
+ virtual ~ParserArenaRefCounted()
+ {
+ ASSERT(deletionHasBegun());
+ }
+ };
+
+ class Node : public ParserArenaFreeable {
+ protected:
+ Node(JSGlobalData*);
+
+ public:
+ virtual ~Node() { }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0;
+
+ int lineNo() const { return m_line; }
+
+ protected:
+ int m_line;
+ };
+
+ class ExpressionNode : public Node {
+ protected:
+ ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType());
+
+ public:
+ virtual bool isNumber() const { return false; }
+ virtual bool isString() const { return false; }
+ virtual bool isNull() const { return false; }
+ virtual bool isPure(BytecodeGenerator&) const { return false; }
+ virtual bool isLocation() const { return false; }
+ virtual bool isResolveNode() const { return false; }
+ virtual bool isBracketAccessorNode() const { return false; }
+ virtual bool isDotAccessorNode() const { return false; }
+ virtual bool isFuncExprNode() const { return false; }
+ virtual bool isCommaNode() const { return false; }
+ virtual bool isSimpleArray() const { return false; }
+ virtual bool isAdd() const { return false; }
+ virtual bool isSubtract() const { return false; }
+ virtual bool hasConditionContextCodegen() const { return false; }
+
+ virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); }
+
+ virtual ExpressionNode* stripUnaryPlus() { return this; }
+
+ ResultType resultDescriptor() const { return m_resultType; }
+
+ private:
+ ResultType m_resultType;
+ };
+
+ class StatementNode : public Node {
+ protected:
+ StatementNode(JSGlobalData*);
+
+ public:
+ void setLoc(int firstLine, int lastLine);
+ int firstLine() const { return lineNo(); }
+ int lastLine() const { return m_lastLine; }
+
+ virtual bool isEmptyStatement() const { return false; }
+ virtual bool isReturnNode() const { return false; }
+ virtual bool isExprStatement() const { return false; }
+
+ virtual bool isBlock() const { return false; }
+
+ private:
+ int m_lastLine;
+ };
+
+ class NullNode : public ExpressionNode {
+ public:
+ NullNode(JSGlobalData*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isNull() const { return true; }
+ };
+
+ class BooleanNode : public ExpressionNode {
+ public:
+ BooleanNode(JSGlobalData*, bool value);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isPure(BytecodeGenerator&) const { return true; }
+
+ bool m_value;
+ };
+
+ class NumberNode : public ExpressionNode {
+ public:
+ NumberNode(JSGlobalData*, double value);
+
+ double value() const { return m_value; }
+ void setValue(double value) { m_value = value; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isNumber() const { return true; }
+ virtual bool isPure(BytecodeGenerator&) const { return true; }
+
+ double m_value;
+ };
+
+ class StringNode : public ExpressionNode {
+ public:
+ StringNode(JSGlobalData*, const Identifier&);
+
+ const Identifier& value() { return m_value; }
+
+ private:
+ virtual bool isPure(BytecodeGenerator&) const { return true; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isString() const { return true; }
+
+ const Identifier& m_value;
+ };
+
+ class ThrowableExpressionData {
+ public:
+ ThrowableExpressionData()
+ : m_divot(static_cast<uint32_t>(-1))
+ , m_startOffset(static_cast<uint16_t>(-1))
+ , m_endOffset(static_cast<uint16_t>(-1))
+ {
+ }
+
+ ThrowableExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset)
+ : m_divot(divot)
+ , m_startOffset(startOffset)
+ , m_endOffset(endOffset)
+ {
+ }
+
+ void setExceptionSourceCode(unsigned divot, unsigned startOffset, unsigned endOffset)
+ {
+ m_divot = divot;
+ m_startOffset = startOffset;
+ m_endOffset = endOffset;
+ }
+
+ uint32_t divot() const { return m_divot; }
+ uint16_t startOffset() const { return m_startOffset; }
+ uint16_t endOffset() const { return m_endOffset; }
+
+ protected:
+ RegisterID* emitThrowReferenceError(BytecodeGenerator&, const UString& message);
+ RegisterID* emitThrowSyntaxError(BytecodeGenerator&, const UString& message);
+
+ private:
+ uint32_t m_divot;
+ uint16_t m_startOffset;
+ uint16_t m_endOffset;
+ };
+
+ class ThrowableSubExpressionData : public ThrowableExpressionData {
+ public:
+ ThrowableSubExpressionData()
+ : m_subexpressionDivotOffset(0)
+ , m_subexpressionEndOffset(0)
+ {
+ }
+
+ ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_subexpressionDivotOffset(0)
+ , m_subexpressionEndOffset(0)
+ {
+ }
+
+ void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset)
+ {
+ ASSERT(subexpressionDivot <= divot());
+ if ((divot() - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot
+ return;
+ m_subexpressionDivotOffset = divot() - subexpressionDivot;
+ m_subexpressionEndOffset = subexpressionOffset;
+ }
+
+ protected:
+ uint16_t m_subexpressionDivotOffset;
+ uint16_t m_subexpressionEndOffset;
+ };
+
+ class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData {
+ public:
+ ThrowablePrefixedSubExpressionData()
+ : m_subexpressionDivotOffset(0)
+ , m_subexpressionStartOffset(0)
+ {
+ }
+
+ ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset)
+ : ThrowableExpressionData(divot, startOffset, endOffset)
+ , m_subexpressionDivotOffset(0)
+ , m_subexpressionStartOffset(0)
+ {
+ }
+
+ void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset)
+ {
+ ASSERT(subexpressionDivot >= divot());
+ if ((subexpressionDivot - divot()) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot
+ return;
+ m_subexpressionDivotOffset = subexpressionDivot - divot();
+ m_subexpressionStartOffset = subexpressionOffset;
+ }
+
+ protected:
+ uint16_t m_subexpressionDivotOffset;
+ uint16_t m_subexpressionStartOffset;
+ };
+
+ class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ RegExpNode(JSGlobalData*, const Identifier& pattern, const Identifier& flags);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_pattern;
+ const Identifier& m_flags;
+ };
+
+ class ThisNode : public ExpressionNode {
+ public:
+ ThisNode(JSGlobalData*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class ResolveNode : public ExpressionNode {
+ public:
+ ResolveNode(JSGlobalData*, const Identifier&, int startOffset);
+
+ const Identifier& identifier() const { return m_ident; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isPure(BytecodeGenerator&) const ;
+ virtual bool isLocation() const { return true; }
+ virtual bool isResolveNode() const { return true; }
+
+ const Identifier& m_ident;
+ int32_t m_startOffset;
+ };
+
+ class ElementNode : public ParserArenaFreeable {
+ public:
+ ElementNode(JSGlobalData*, int elision, ExpressionNode*);
+ ElementNode(JSGlobalData*, ElementNode*, int elision, ExpressionNode*);
+
+ int elision() const { return m_elision; }
+ ExpressionNode* value() { return m_node; }
+ ElementNode* next() { return m_next; }
+
+ private:
+ ElementNode* m_next;
+ int m_elision;
+ ExpressionNode* m_node;
+ };
+
+ class ArrayNode : public ExpressionNode {
+ public:
+ ArrayNode(JSGlobalData*, int elision);
+ ArrayNode(JSGlobalData*, ElementNode*);
+ ArrayNode(JSGlobalData*, int elision, ElementNode*);
+
+ ArgumentListNode* toArgumentList(JSGlobalData*) const;
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isSimpleArray() const ;
+
+ ElementNode* m_element;
+ int m_elision;
+ bool m_optional;
+ };
+
+ class PropertyNode : public ParserArenaFreeable {
+ public:
+ enum Type { Constant = 1, Getter = 2, Setter = 4 };
+
+ PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type);
+ PropertyNode(JSGlobalData*, double name, ExpressionNode* value, Type);
+
+ const Identifier& name() const { return m_name; }
+ Type type() const { return m_type; }
+
+ private:
+ friend class PropertyListNode;
+ const Identifier& m_name;
+ ExpressionNode* m_assign;
+ Type m_type;
+ };
+
+ class PropertyListNode : public Node {
+ public:
+ PropertyListNode(JSGlobalData*, PropertyNode*);
+ PropertyListNode(JSGlobalData*, PropertyNode*, PropertyListNode*);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ private:
+ PropertyNode* m_node;
+ PropertyListNode* m_next;
+ };
+
+ class ObjectLiteralNode : public ExpressionNode {
+ public:
+ ObjectLiteralNode(JSGlobalData*);
+ ObjectLiteralNode(JSGlobalData*, PropertyListNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ PropertyListNode* m_list;
+ };
+
+ class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ BracketAccessorNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments);
+
+ ExpressionNode* base() const { return m_base; }
+ ExpressionNode* subscript() const { return m_subscript; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isLocation() const { return true; }
+ virtual bool isBracketAccessorNode() const { return true; }
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ bool m_subscriptHasAssignments;
+ };
+
+ class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DotAccessorNode(JSGlobalData*, ExpressionNode* base, const Identifier&);
+
+ ExpressionNode* base() const { return m_base; }
+ const Identifier& identifier() const { return m_ident; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isLocation() const { return true; }
+ virtual bool isDotAccessorNode() const { return true; }
+
+ ExpressionNode* m_base;
+ const Identifier& m_ident;
+ };
+
+ class ArgumentListNode : public Node {
+ public:
+ ArgumentListNode(JSGlobalData*, ExpressionNode*);
+ ArgumentListNode(JSGlobalData*, ArgumentListNode*, ExpressionNode*);
+
+ ArgumentListNode* m_next;
+ ExpressionNode* m_expr;
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class ArgumentsNode : public ParserArenaFreeable {
+ public:
+ ArgumentsNode(JSGlobalData*);
+ ArgumentsNode(JSGlobalData*, ArgumentListNode*);
+
+ ArgumentListNode* m_listNode;
+ };
+
+ class NewExprNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ NewExprNode(JSGlobalData*, ExpressionNode*);
+ NewExprNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ ArgumentsNode* m_args;
+ };
+
+ class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ EvalFunctionCallNode(JSGlobalData*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ArgumentsNode* m_args;
+ };
+
+ class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ FunctionCallValueNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ ArgumentsNode* m_args;
+ };
+
+ class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ FunctionCallResolveNode(JSGlobalData*, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_ident;
+ ArgumentsNode* m_args;
+ size_t m_index; // Used by LocalVarFunctionCallNode.
+ size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode
+ };
+
+ class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ FunctionCallBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ ArgumentsNode* m_args;
+ };
+
+ class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ FunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ protected:
+ ExpressionNode* m_base;
+ const Identifier& m_ident;
+ ArgumentsNode* m_args;
+ };
+
+ class CallFunctionCallDotNode : public FunctionCallDotNode {
+ public:
+ CallFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class ApplyFunctionCallDotNode : public FunctionCallDotNode {
+ public:
+ ApplyFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ PrePostResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ protected:
+ const Identifier& m_ident;
+ };
+
+ class PostfixResolveNode : public PrePostResolveNode {
+ public:
+ PostfixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ Operator m_operator;
+ };
+
+ class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ PostfixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ Operator m_operator;
+ };
+
+ class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ PostfixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ const Identifier& m_ident;
+ Operator m_operator;
+ };
+
+ class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ PostfixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ Operator m_operator;
+ };
+
+ class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DeleteResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_ident;
+ };
+
+ class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DeleteBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ };
+
+ class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ DeleteDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ const Identifier& m_ident;
+ };
+
+ class DeleteValueNode : public ExpressionNode {
+ public:
+ DeleteValueNode(JSGlobalData*, ExpressionNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ };
+
+ class VoidNode : public ExpressionNode {
+ public:
+ VoidNode(JSGlobalData*, ExpressionNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ };
+
+ class TypeOfResolveNode : public ExpressionNode {
+ public:
+ TypeOfResolveNode(JSGlobalData*, const Identifier&);
+
+ const Identifier& identifier() const { return m_ident; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_ident;
+ };
+
+ class TypeOfValueNode : public ExpressionNode {
+ public:
+ TypeOfValueNode(JSGlobalData*, ExpressionNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ };
+
+ class PrefixResolveNode : public PrePostResolveNode {
+ public:
+ PrefixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ Operator m_operator;
+ };
+
+ class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
+ public:
+ PrefixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ Operator m_operator;
+ };
+
+ class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
+ public:
+ PrefixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ const Identifier& m_ident;
+ Operator m_operator;
+ };
+
+ class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ PrefixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ Operator m_operator;
+ };
+
+ class UnaryOpNode : public ExpressionNode {
+ public:
+ UnaryOpNode(JSGlobalData*, ResultType, ExpressionNode*, OpcodeID);
+
+ protected:
+ ExpressionNode* expr() { return m_expr; }
+ const ExpressionNode* expr() const { return m_expr; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ OpcodeID opcodeID() const { return m_opcodeID; }
+
+ ExpressionNode* m_expr;
+ OpcodeID m_opcodeID;
+ };
+
+ class UnaryPlusNode : public UnaryOpNode {
+ public:
+ UnaryPlusNode(JSGlobalData*, ExpressionNode*);
+
+ private:
+ virtual ExpressionNode* stripUnaryPlus() { return expr(); }
+ };
+
+ class NegateNode : public UnaryOpNode {
+ public:
+ NegateNode(JSGlobalData*, ExpressionNode*);
+ };
+
+ class BitwiseNotNode : public UnaryOpNode {
+ public:
+ BitwiseNotNode(JSGlobalData*, ExpressionNode*);
+ };
+
+ class LogicalNotNode : public UnaryOpNode {
+ public:
+ LogicalNotNode(JSGlobalData*, ExpressionNode*);
+ private:
+ void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
+ virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); }
+ };
+
+ class BinaryOpNode : public ExpressionNode {
+ public:
+ BinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+ BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+
+ RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
+
+ ExpressionNode* lhs() { return m_expr1; };
+ ExpressionNode* rhs() { return m_expr2; };
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ protected:
+ OpcodeID opcodeID() const { return m_opcodeID; }
+
+ protected:
+ ExpressionNode* m_expr1;
+ ExpressionNode* m_expr2;
+ private:
+ OpcodeID m_opcodeID;
+ protected:
+ bool m_rightHasAssignments;
+ };
+
+ class ReverseBinaryOpNode : public BinaryOpNode {
+ public:
+ ReverseBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+ ReverseBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class MultNode : public BinaryOpNode {
+ public:
+ MultNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class DivNode : public BinaryOpNode {
+ public:
+ DivNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class ModNode : public BinaryOpNode {
+ public:
+ ModNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class AddNode : public BinaryOpNode {
+ public:
+ AddNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+
+ virtual bool isAdd() const { return true; }
+ };
+
+ class SubNode : public BinaryOpNode {
+ public:
+ SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+
+ virtual bool isSubtract() const { return true; }
+ };
+
+ class LeftShiftNode : public BinaryOpNode {
+ public:
+ LeftShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class RightShiftNode : public BinaryOpNode {
+ public:
+ RightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class UnsignedRightShiftNode : public BinaryOpNode {
+ public:
+ UnsignedRightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class LessNode : public BinaryOpNode {
+ public:
+ LessNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class GreaterNode : public ReverseBinaryOpNode {
+ public:
+ GreaterNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class LessEqNode : public BinaryOpNode {
+ public:
+ LessEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class GreaterEqNode : public ReverseBinaryOpNode {
+ public:
+ GreaterEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData {
+ public:
+ ThrowableBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+ ThrowableBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class InstanceOfNode : public ThrowableBinaryOpNode {
+ public:
+ InstanceOfNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class InNode : public ThrowableBinaryOpNode {
+ public:
+ InNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class EqualNode : public BinaryOpNode {
+ public:
+ EqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class NotEqualNode : public BinaryOpNode {
+ public:
+ NotEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class StrictEqualNode : public BinaryOpNode {
+ public:
+ StrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class NotStrictEqualNode : public BinaryOpNode {
+ public:
+ NotStrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class BitAndNode : public BinaryOpNode {
+ public:
+ BitAndNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class BitOrNode : public BinaryOpNode {
+ public:
+ BitOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ class BitXOrNode : public BinaryOpNode {
+ public:
+ BitXOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+ };
+
+ // m_expr1 && m_expr2, m_expr1 || m_expr2
+ class LogicalOpNode : public ExpressionNode {
+ public:
+ LogicalOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
+ virtual bool hasConditionContextCodegen() const { return true; }
+
+ ExpressionNode* m_expr1;
+ ExpressionNode* m_expr2;
+ LogicalOperator m_operator;
+ };
+
+ // The ternary operator, "m_logical ? m_expr1 : m_expr2"
+ class ConditionalNode : public ExpressionNode {
+ public:
+ ConditionalNode(JSGlobalData*, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_logical;
+ ExpressionNode* m_expr1;
+ ExpressionNode* m_expr2;
+ };
+
+ class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ ReadModifyResolveNode(JSGlobalData*, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_ident;
+ ExpressionNode* m_right;
+ size_t m_index; // Used by ReadModifyLocalVarNode.
+ Operator m_operator;
+ bool m_rightHasAssignments;
+ };
+
+ class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignResolveNode(JSGlobalData*, const Identifier&, ExpressionNode* right, bool rightHasAssignments);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_ident;
+ ExpressionNode* m_right;
+ size_t m_index; // Used by ReadModifyLocalVarNode.
+ bool m_rightHasAssignments;
+ };
+
+ class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ ReadModifyBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ ExpressionNode* m_right;
+ Operator m_operator : 30;
+ bool m_subscriptHasAssignments : 1;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ ExpressionNode* m_subscript;
+ ExpressionNode* m_right;
+ bool m_subscriptHasAssignments : 1;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignDotNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ const Identifier& m_ident;
+ ExpressionNode* m_right;
+ bool m_rightHasAssignments;
+ };
+
+ class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData {
+ public:
+ ReadModifyDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_base;
+ const Identifier& m_ident;
+ ExpressionNode* m_right;
+ Operator m_operator : 31;
+ bool m_rightHasAssignments : 1;
+ };
+
+ class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData {
+ public:
+ AssignErrorNode(JSGlobalData*, ExpressionNode* left, Operator, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_left;
+ Operator m_operator;
+ ExpressionNode* m_right;
+ };
+
+ typedef Vector<ExpressionNode*, 8> ExpressionVector;
+
+ class CommaNode : public ExpressionNode, public ParserArenaDeletable {
+ public:
+ CommaNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2);
+
+ using ParserArenaDeletable::operator new;
+
+ void append(ExpressionNode* expr) { m_expressions.append(expr); }
+
+ private:
+ virtual bool isCommaNode() const { return true; }
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionVector m_expressions;
+ };
+
+ class ConstDeclNode : public ExpressionNode {
+ public:
+ ConstDeclNode(JSGlobalData*, const Identifier&, ExpressionNode*);
+
+ bool hasInitializer() const { return m_init; }
+ const Identifier& ident() { return m_ident; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ virtual RegisterID* emitCodeSingle(BytecodeGenerator&);
+
+ const Identifier& m_ident;
+
+ public:
+ ConstDeclNode* m_next;
+
+ private:
+ ExpressionNode* m_init;
+ };
+
+ class ConstStatementNode : public StatementNode {
+ public:
+ ConstStatementNode(JSGlobalData*, ConstDeclNode* next);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ConstDeclNode* m_next;
+ };
+
+ class SourceElements : public ParserArenaDeletable {
+ public:
+ SourceElements(JSGlobalData*);
+
+ void append(StatementNode*);
+
+ StatementNode* singleStatement() const;
+ StatementNode* lastStatement() const;
+
+ void emitBytecode(BytecodeGenerator&, RegisterID* destination);
+
+ private:
+ Vector<StatementNode*> m_statements;
+ };
+
+ class BlockNode : public StatementNode {
+ public:
+ BlockNode(JSGlobalData*, SourceElements* = 0);
+
+ StatementNode* singleStatement() const;
+ StatementNode* lastStatement() const;
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isBlock() const { return true; }
+
+ SourceElements* m_statements;
+ };
+
+ class EmptyStatementNode : public StatementNode {
+ public:
+ EmptyStatementNode(JSGlobalData*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isEmptyStatement() const { return true; }
+ };
+
+ class DebuggerStatementNode : public StatementNode {
+ public:
+ DebuggerStatementNode(JSGlobalData*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class ExprStatementNode : public StatementNode {
+ public:
+ ExprStatementNode(JSGlobalData*, ExpressionNode*);
+
+ ExpressionNode* expr() const { return m_expr; }
+
+ private:
+ virtual bool isExprStatement() const { return true; }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ };
+
+ class VarStatementNode : public StatementNode {
+ public:
+ VarStatementNode(JSGlobalData*, ExpressionNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ };
+
+ class IfNode : public StatementNode {
+ public:
+ IfNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock);
+
+ protected:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_condition;
+ StatementNode* m_ifBlock;
+ };
+
+ class IfElseNode : public IfNode {
+ public:
+ IfElseNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ StatementNode* m_elseBlock;
+ };
+
+ class DoWhileNode : public StatementNode {
+ public:
+ DoWhileNode(JSGlobalData*, StatementNode* statement, ExpressionNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ StatementNode* m_statement;
+ ExpressionNode* m_expr;
+ };
+
+ class WhileNode : public StatementNode {
+ public:
+ WhileNode(JSGlobalData*, ExpressionNode*, StatementNode* statement);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ StatementNode* m_statement;
+ };
+
+ class ForNode : public StatementNode {
+ public:
+ ForNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr1;
+ ExpressionNode* m_expr2;
+ ExpressionNode* m_expr3;
+ StatementNode* m_statement;
+ bool m_expr1WasVarDecl;
+ };
+
+ class ForInNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*);
+ ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_ident;
+ ExpressionNode* m_init;
+ ExpressionNode* m_lexpr;
+ ExpressionNode* m_expr;
+ StatementNode* m_statement;
+ bool m_identIsVarDecl;
+ };
+
+ class ContinueNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ContinueNode(JSGlobalData*);
+ ContinueNode(JSGlobalData*, const Identifier&);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_ident;
+ };
+
+ class BreakNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ BreakNode(JSGlobalData*);
+ BreakNode(JSGlobalData*, const Identifier&);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_ident;
+ };
+
+ class ReturnNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ReturnNode(JSGlobalData*, ExpressionNode* value);
+
+ ExpressionNode* value() { return m_value; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isReturnNode() const { return true; }
+
+ ExpressionNode* m_value;
+ };
+
+ class WithNode : public StatementNode {
+ public:
+ WithNode(JSGlobalData*, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ StatementNode* m_statement;
+ uint32_t m_divot;
+ uint32_t m_expressionLength;
+ };
+
+ class LabelNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ LabelNode(JSGlobalData*, const Identifier& name, StatementNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ const Identifier& m_name;
+ StatementNode* m_statement;
+ };
+
+ class ThrowNode : public StatementNode, public ThrowableExpressionData {
+ public:
+ ThrowNode(JSGlobalData*, ExpressionNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ };
+
+ class TryNode : public StatementNode {
+ public:
+ TryNode(JSGlobalData*, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ StatementNode* m_tryBlock;
+ const Identifier& m_exceptionIdent;
+ StatementNode* m_catchBlock;
+ StatementNode* m_finallyBlock;
+ bool m_catchHasEval;
+ };
+
+ class ParameterNode : public ParserArenaFreeable {
+ public:
+ ParameterNode(JSGlobalData*, const Identifier&);
+ ParameterNode(JSGlobalData*, ParameterNode*, const Identifier&);
+
+ const Identifier& ident() const { return m_ident; }
+ ParameterNode* nextParam() const { return m_next; }
+
+ private:
+ const Identifier& m_ident;
+ ParameterNode* m_next;
+ };
+
+ struct ScopeNodeData : FastAllocBase {
+ typedef DeclarationStacks::VarStack VarStack;
+ typedef DeclarationStacks::FunctionStack FunctionStack;
+
+ ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, int numConstants);
+
+ ParserArena m_arena;
+ VarStack m_varStack;
+ FunctionStack m_functionStack;
+ int m_numConstants;
+ SourceElements* m_statements;
+ IdentifierSet m_capturedVariables;
+ };
+
+ class ScopeNode : public StatementNode, public ParserArenaRefCounted {
+ public:
+ typedef DeclarationStacks::VarStack VarStack;
+ typedef DeclarationStacks::FunctionStack FunctionStack;
+
+ ScopeNode(JSGlobalData*, bool inStrictContext);
+ ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants);
+
+ using ParserArenaRefCounted::operator new;
+
+ ScopeNodeData* data() const { return m_data.get(); }
+ void destroyData() { m_data.clear(); }
+
+ const SourceCode& source() const { return m_source; }
+ const UString& sourceURL() const { return m_source.provider()->url(); }
+ intptr_t sourceID() const { return m_source.provider()->asID(); }
+
+ void setFeatures(CodeFeatures features) { m_features = features; }
+ CodeFeatures features() { return m_features; }
+
+ bool usesEval() const { return m_features & EvalFeature; }
+ bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); }
+ bool isStrictMode() const { return m_features & StrictModeFeature; }
+ void setUsesArguments() { m_features |= ArgumentsFeature; }
+ bool usesThis() const { return m_features & ThisFeature; }
+ bool needsActivationForMoreThanVariables() const { ASSERT(m_data); return m_features & (EvalFeature | WithFeature | CatchFeature); }
+ bool needsActivation() const { ASSERT(m_data); return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); }
+ bool hasCapturedVariables() const { return !!m_data->m_capturedVariables.size(); }
+ size_t capturedVariableCount() const { return m_data->m_capturedVariables.size(); }
+ bool captures(const Identifier& ident) { return m_data->m_capturedVariables.contains(ident.impl()); }
+
+ VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; }
+ FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; }
+
+ int neededConstants()
+ {
+ ASSERT(m_data);
+ // We may need 2 more constants than the count given by the parser,
+ // because of the various uses of jsUndefined() and jsNull().
+ return m_data->m_numConstants + 2;
+ }
+
+ StatementNode* singleStatement() const;
+
+ void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination);
+
+ protected:
+ void setSource(const SourceCode& source) { m_source = source; }
+
+ private:
+ OwnPtr<ScopeNodeData> m_data;
+ CodeFeatures m_features;
+ SourceCode m_source;
+ };
+
+ class ProgramNode : public ScopeNode {
+ public:
+ static const bool isFunctionNode = false;
+ static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+
+ static const bool scopeIsFunction = false;
+
+ private:
+ ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class EvalNode : public ScopeNode {
+ public:
+ static const bool isFunctionNode = false;
+ static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+
+ static const bool scopeIsFunction = false;
+
+ private:
+ EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ };
+
+ class FunctionParameters : public Vector<Identifier>, public RefCounted<FunctionParameters> {
+ public:
+ static PassRefPtr<FunctionParameters> create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); }
+
+ private:
+ FunctionParameters(ParameterNode*);
+ };
+
+ class FunctionBodyNode : public ScopeNode {
+ public:
+ static const bool isFunctionNode = true;
+ static FunctionBodyNode* create(JSGlobalData*, bool isStrictMode);
+ static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+
+ FunctionParameters* parameters() const { return m_parameters.get(); }
+ size_t parameterCount() const { return m_parameters->size(); }
+
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ void finishParsing(const SourceCode&, ParameterNode*, const Identifier&);
+ void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&);
+
+ const Identifier& ident() { return m_ident; }
+
+ static const bool scopeIsFunction = true;
+
+ private:
+ FunctionBodyNode(JSGlobalData*, bool inStrictContext);
+ FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+
+ Identifier m_ident;
+ RefPtr<FunctionParameters> m_parameters;
+ };
+
+ class FuncExprNode : public ExpressionNode {
+ public:
+ FuncExprNode(JSGlobalData*, const Identifier&, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0);
+
+ FunctionBodyNode* body() { return m_body; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ virtual bool isFuncExprNode() const { return true; }
+
+ FunctionBodyNode* m_body;
+ };
+
+ class FuncDeclNode : public StatementNode {
+ public:
+ FuncDeclNode(JSGlobalData*, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0);
+
+ FunctionBodyNode* body() { return m_body; }
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ FunctionBodyNode* m_body;
+ };
+
+ class CaseClauseNode : public ParserArenaFreeable {
+ public:
+ CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements* = 0);
+
+ ExpressionNode* expr() const { return m_expr; }
+
+ void emitBytecode(BytecodeGenerator&, RegisterID* destination);
+
+ private:
+ ExpressionNode* m_expr;
+ SourceElements* m_statements;
+ };
+
+ class ClauseListNode : public ParserArenaFreeable {
+ public:
+ ClauseListNode(JSGlobalData*, CaseClauseNode*);
+ ClauseListNode(JSGlobalData*, ClauseListNode*, CaseClauseNode*);
+
+ CaseClauseNode* getClause() const { return m_clause; }
+ ClauseListNode* getNext() const { return m_next; }
+
+ private:
+ CaseClauseNode* m_clause;
+ ClauseListNode* m_next;
+ };
+
+ class CaseBlockNode : public ParserArenaFreeable {
+ public:
+ CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2);
+
+ RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination);
+
+ private:
+ SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num);
+ ClauseListNode* m_list1;
+ CaseClauseNode* m_defaultClause;
+ ClauseListNode* m_list2;
+ };
+
+ class SwitchNode : public StatementNode {
+ public:
+ SwitchNode(JSGlobalData*, ExpressionNode*, CaseBlockNode*);
+
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+
+ ExpressionNode* m_expr;
+ CaseBlockNode* m_block;
+ };
+
+ struct ElementList {
+ ElementNode* head;
+ ElementNode* tail;
+ };
+
+ struct PropertyList {
+ PropertyListNode* head;
+ PropertyListNode* tail;
+ };
+
+ struct ArgumentList {
+ ArgumentListNode* head;
+ 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