| /* |
| * 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 "Opcode.h" |
| #include "ResultType.h" |
| #include "SourceCode.h" |
| #include "SymbolTable.h" |
| #include <wtf/MathExtras.h> |
| #include <wtf/OwnPtr.h> |
| #include <wtf/Vector.h> |
| |
| #if PLATFORM(X86) && COMPILER(GCC) |
| #define JSC_FAST_CALL __attribute__((regparm(3))) |
| #else |
| #define JSC_FAST_CALL |
| #endif |
| |
| namespace JSC { |
| |
| class CodeBlock; |
| class BytecodeGenerator; |
| class FuncDeclNode; |
| class EvalCodeBlock; |
| class JSFunction; |
| class NodeReleaser; |
| class ProgramCodeBlock; |
| class PropertyListNode; |
| class RegisterID; |
| class ScopeChainNode; |
| |
| typedef unsigned CodeFeatures; |
| |
| const CodeFeatures NoFeatures = 0; |
| const CodeFeatures EvalFeature = 1 << 0; |
| const CodeFeatures ClosureFeature = 1 << 1; |
| const CodeFeatures AssignFeature = 1 << 2; |
| const CodeFeatures ArgumentsFeature = 1 << 3; |
| const CodeFeatures WithFeature = 1 << 4; |
| const CodeFeatures CatchFeature = 1 << 5; |
| const CodeFeatures ThisFeature = 1 << 6; |
| const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature; |
| |
| enum Operator { |
| OpEqual, |
| OpPlusEq, |
| OpMinusEq, |
| OpMultEq, |
| OpDivEq, |
| OpPlusPlus, |
| OpMinusMinus, |
| OpAndEq, |
| OpXOrEq, |
| OpOrEq, |
| OpModEq, |
| OpLShift, |
| OpRShift, |
| OpURShift |
| }; |
| |
| enum LogicalOperator { |
| OpLogicalAnd, |
| OpLogicalOr |
| }; |
| |
| namespace DeclarationStacks { |
| enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; |
| typedef Vector<std::pair<Identifier, unsigned> > VarStack; |
| typedef Vector<RefPtr<FuncDeclNode> > FunctionStack; |
| } |
| |
| struct SwitchInfo { |
| enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString }; |
| uint32_t bytecodeOffset; |
| SwitchType switchType; |
| }; |
| |
| class ParserRefCounted : Noncopyable { |
| protected: |
| ParserRefCounted(JSGlobalData*) JSC_FAST_CALL; |
| |
| public: |
| virtual ~ParserRefCounted(); |
| |
| // Nonrecursive destruction. |
| virtual void releaseNodes(NodeReleaser&); |
| |
| void ref() JSC_FAST_CALL; |
| void deref() JSC_FAST_CALL; |
| bool hasOneRef() JSC_FAST_CALL; |
| |
| static void deleteNewObjects(JSGlobalData*) JSC_FAST_CALL; |
| |
| private: |
| JSGlobalData* m_globalData; |
| }; |
| |
| class Node : public ParserRefCounted { |
| public: |
| Node(JSGlobalData*) JSC_FAST_CALL; |
| |
| /* |
| Return value: The register holding the production's value. |
| dst: An optional parameter specifying the most efficient |
| destination at which to store the production's value. |
| The callee must honor dst. |
| |
| dst provides for a crude form of copy propagation. For example, |
| |
| x = 1 |
| |
| becomes |
| |
| load r[x], 1 |
| |
| instead of |
| |
| load r0, 1 |
| mov r[x], r0 |
| |
| because the assignment node, "x =", passes r[x] as dst to the number |
| node, "1". |
| */ |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL = 0; |
| |
| int lineNo() const { return m_line; } |
| |
| protected: |
| int m_line; |
| }; |
| |
| class ExpressionNode : public Node { |
| public: |
| ExpressionNode(JSGlobalData* globalData, ResultType resultDesc = ResultType::unknownType()) JSC_FAST_CALL |
| : Node(globalData) |
| , m_resultDesc(resultDesc) |
| { |
| } |
| |
| virtual bool isNumber() const JSC_FAST_CALL { return false; } |
| virtual bool isString() const JSC_FAST_CALL { return false; } |
| virtual bool isNull() const JSC_FAST_CALL { return false; } |
| virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return false; } |
| virtual bool isLocation() const JSC_FAST_CALL { return false; } |
| virtual bool isResolveNode() const JSC_FAST_CALL { return false; } |
| virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return false; } |
| virtual bool isDotAccessorNode() const JSC_FAST_CALL { return false; } |
| virtual bool isFuncExprNode() const JSC_FAST_CALL { return false; } |
| |
| virtual ExpressionNode* stripUnaryPlus() { return this; } |
| |
| ResultType resultDescriptor() const JSC_FAST_CALL { return m_resultDesc; } |
| |
| // This needs to be in public in order to compile using GCC 3.x |
| typedef enum { EvalOperator, FunctionCall } CallerType; |
| |
| private: |
| ResultType m_resultDesc; |
| }; |
| |
| class StatementNode : public Node { |
| public: |
| StatementNode(JSGlobalData*) JSC_FAST_CALL; |
| void setLoc(int line0, int line1) JSC_FAST_CALL; |
| int firstLine() const JSC_FAST_CALL { return lineNo(); } |
| int lastLine() const JSC_FAST_CALL { return m_lastLine; } |
| |
| virtual bool isEmptyStatement() const JSC_FAST_CALL { return false; } |
| virtual bool isReturnNode() const JSC_FAST_CALL { return false; } |
| virtual bool isExprStatement() const JSC_FAST_CALL { return false; } |
| |
| virtual bool isBlock() const JSC_FAST_CALL { return false; } |
| virtual bool isLoop() const JSC_FAST_CALL { return false; } |
| |
| private: |
| int m_lastLine; |
| }; |
| |
| class NullNode : public ExpressionNode { |
| public: |
| NullNode(JSGlobalData* globalData) JSC_FAST_CALL |
| : ExpressionNode(globalData, ResultType::nullType()) |
| { |
| } |
| |
| virtual bool isNull() const JSC_FAST_CALL { return true; } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| }; |
| |
| class BooleanNode : public ExpressionNode { |
| public: |
| BooleanNode(JSGlobalData* globalData, bool value) JSC_FAST_CALL |
| : ExpressionNode(globalData, ResultType::booleanType()) |
| , m_value(value) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } |
| |
| private: |
| bool m_value; |
| }; |
| |
| class NumberNode : public ExpressionNode { |
| public: |
| NumberNode(JSGlobalData* globalData, double v) JSC_FAST_CALL |
| : ExpressionNode(globalData, ResultType::numberType()) |
| , m_double(v) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isNumber() const JSC_FAST_CALL { return true; } |
| virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } |
| double value() const JSC_FAST_CALL { return m_double; } |
| void setValue(double d) JSC_FAST_CALL { m_double = d; } |
| |
| private: |
| double m_double; |
| }; |
| |
| class StringNode : public ExpressionNode { |
| public: |
| StringNode(JSGlobalData* globalData, const Identifier& v) JSC_FAST_CALL |
| : ExpressionNode(globalData, ResultType::stringType()) |
| , m_value(v) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isString() const JSC_FAST_CALL { return true; } |
| const Identifier& value() { return m_value; } |
| virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } |
| |
| private: |
| 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* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg); |
| RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* msg, const Identifier&); |
| |
| private: |
| uint32_t m_divot; |
| uint16_t m_startOffset; |
| uint16_t m_endOffset; |
| }; |
| |
| class ThrowableSubExpressionData : public ThrowableExpressionData { |
| public: |
| ThrowableSubExpressionData() |
| : ThrowableExpressionData() |
| , 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() |
| : ThrowableExpressionData() |
| , 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* globalData, const UString& pattern, const UString& flags) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_pattern(pattern) |
| , m_flags(flags) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| UString m_pattern; |
| UString m_flags; |
| }; |
| |
| class ThisNode : public ExpressionNode { |
| public: |
| ThisNode(JSGlobalData* globalData) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| }; |
| |
| class ResolveNode : public ExpressionNode { |
| public: |
| ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_ident(ident) |
| , m_startOffset(startOffset) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL; |
| virtual bool isLocation() const JSC_FAST_CALL { return true; } |
| virtual bool isResolveNode() const JSC_FAST_CALL { return true; } |
| const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } |
| |
| private: |
| Identifier m_ident; |
| int32_t m_startOffset; |
| }; |
| |
| class ElementNode : public ParserRefCounted { |
| public: |
| ElementNode(JSGlobalData* globalData, int elision, ExpressionNode* node) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_elision(elision) |
| , m_node(node) |
| { |
| } |
| |
| ElementNode(JSGlobalData* globalData, ElementNode* l, int elision, ExpressionNode* node) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_elision(elision) |
| , m_node(node) |
| { |
| l->m_next = this; |
| } |
| |
| virtual ~ElementNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| int elision() const { return m_elision; } |
| ExpressionNode* value() { return m_node.get(); } |
| |
| ElementNode* next() { return m_next.get(); } |
| |
| private: |
| RefPtr<ElementNode> m_next; |
| int m_elision; |
| RefPtr<ExpressionNode> m_node; |
| }; |
| |
| class ArrayNode : public ExpressionNode { |
| public: |
| ArrayNode(JSGlobalData* globalData, int elision) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_elision(elision) |
| , m_optional(true) |
| { |
| } |
| |
| ArrayNode(JSGlobalData* globalData, ElementNode* element) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_element(element) |
| , m_elision(0) |
| , m_optional(false) |
| { |
| } |
| |
| ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_element(element) |
| , m_elision(elision) |
| , m_optional(true) |
| { |
| } |
| |
| virtual ~ArrayNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ElementNode> m_element; |
| int m_elision; |
| bool m_optional; |
| }; |
| |
| class PropertyNode : public ParserRefCounted { |
| public: |
| enum Type { Constant, Getter, Setter }; |
| |
| PropertyNode(JSGlobalData* globalData, const Identifier& name, ExpressionNode* assign, Type type) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_name(name) |
| , m_assign(assign) |
| , m_type(type) |
| { |
| } |
| |
| virtual ~PropertyNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| const Identifier& name() const { return m_name; } |
| |
| private: |
| friend class PropertyListNode; |
| Identifier m_name; |
| RefPtr<ExpressionNode> m_assign; |
| Type m_type; |
| }; |
| |
| class PropertyListNode : public Node { |
| public: |
| PropertyListNode(JSGlobalData* globalData, PropertyNode* node) JSC_FAST_CALL |
| : Node(globalData) |
| , m_node(node) |
| { |
| } |
| |
| PropertyListNode(JSGlobalData* globalData, PropertyNode* node, PropertyListNode* list) JSC_FAST_CALL |
| : Node(globalData) |
| , m_node(node) |
| { |
| list->m_next = this; |
| } |
| |
| virtual ~PropertyListNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<PropertyNode> m_node; |
| RefPtr<PropertyListNode> m_next; |
| }; |
| |
| class ObjectLiteralNode : public ExpressionNode { |
| public: |
| ObjectLiteralNode(JSGlobalData* globalData) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| { |
| } |
| |
| ObjectLiteralNode(JSGlobalData* globalData, PropertyListNode* list) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_list(list) |
| { |
| } |
| |
| virtual ~ObjectLiteralNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<PropertyListNode> m_list; |
| }; |
| |
| class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| BracketAccessorNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_base(base) |
| , m_subscript(subscript) |
| , m_subscriptHasAssignments(subscriptHasAssignments) |
| { |
| } |
| |
| virtual ~BracketAccessorNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isLocation() const JSC_FAST_CALL { return true; } |
| virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return true; } |
| ExpressionNode* base() JSC_FAST_CALL { return m_base.get(); } |
| ExpressionNode* subscript() JSC_FAST_CALL { return m_subscript.get(); } |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| RefPtr<ExpressionNode> m_subscript; |
| bool m_subscriptHasAssignments; |
| }; |
| |
| class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| DotAccessorNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_base(base) |
| , m_ident(ident) |
| { |
| } |
| |
| virtual ~DotAccessorNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isLocation() const JSC_FAST_CALL { return true; } |
| virtual bool isDotAccessorNode() const JSC_FAST_CALL { return true; } |
| ExpressionNode* base() const JSC_FAST_CALL { return m_base.get(); } |
| const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| Identifier m_ident; |
| }; |
| |
| class ArgumentListNode : public Node { |
| public: |
| ArgumentListNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : Node(globalData) |
| , m_expr(expr) |
| { |
| } |
| |
| ArgumentListNode(JSGlobalData* globalData, ArgumentListNode* listNode, ExpressionNode* expr) JSC_FAST_CALL |
| : Node(globalData) |
| , m_expr(expr) |
| { |
| listNode->m_next = this; |
| } |
| |
| virtual ~ArgumentListNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| RefPtr<ArgumentListNode> m_next; |
| RefPtr<ExpressionNode> m_expr; |
| }; |
| |
| class ArgumentsNode : public ParserRefCounted { |
| public: |
| ArgumentsNode(JSGlobalData* globalData) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| { |
| } |
| |
| ArgumentsNode(JSGlobalData* globalData, ArgumentListNode* listNode) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_listNode(listNode) |
| { |
| } |
| |
| virtual ~ArgumentsNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| RefPtr<ArgumentListNode> m_listNode; |
| }; |
| |
| class NewExprNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| NewExprNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_expr(expr) |
| { |
| } |
| |
| NewExprNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_expr(expr) |
| , m_args(args) |
| { |
| } |
| |
| virtual ~NewExprNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| RefPtr<ArgumentsNode> m_args; |
| }; |
| |
| class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| EvalFunctionCallNode(JSGlobalData* globalData, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_args(args) |
| { |
| } |
| |
| virtual ~EvalFunctionCallNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ArgumentsNode> m_args; |
| }; |
| |
| class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| FunctionCallValueNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_expr(expr) |
| , m_args(args) |
| { |
| } |
| |
| virtual ~FunctionCallValueNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| RefPtr<ArgumentsNode> m_args; |
| }; |
| |
| class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| FunctionCallResolveNode(JSGlobalData* globalData, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_ident(ident) |
| , m_args(args) |
| { |
| } |
| |
| virtual ~FunctionCallResolveNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| Identifier m_ident; |
| RefPtr<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* globalData, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableSubExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_subscript(subscript) |
| , m_args(args) |
| { |
| } |
| |
| virtual ~FunctionCallBracketNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| RefPtr<ExpressionNode> m_subscript; |
| RefPtr<ArgumentsNode> m_args; |
| }; |
| |
| class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { |
| public: |
| FunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableSubExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_ident(ident) |
| , m_args(args) |
| { |
| } |
| |
| virtual ~FunctionCallDotNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| Identifier m_ident; |
| RefPtr<ArgumentsNode> m_args; |
| }; |
| |
| class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData, ResultType::numberType()) // could be reusable for pre? |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_ident(ident) |
| { |
| } |
| |
| protected: |
| Identifier m_ident; |
| }; |
| |
| class PostfixResolveNode : public PrePostResolveNode { |
| public: |
| PostfixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset) |
| , m_operator(oper) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| Operator m_operator; |
| }; |
| |
| class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData { |
| public: |
| PostfixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableSubExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_subscript(subscript) |
| , m_operator(oper) |
| { |
| } |
| |
| virtual ~PostfixBracketNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| RefPtr<ExpressionNode> m_subscript; |
| Operator m_operator; |
| }; |
| |
| class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData { |
| public: |
| PostfixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableSubExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_ident(ident) |
| , m_operator(oper) |
| { |
| } |
| |
| virtual ~PostfixDotNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| Identifier m_ident; |
| Operator m_operator; |
| }; |
| |
| class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData { |
| public: |
| PostfixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableSubExpressionData(divot, startOffset, endOffset) |
| , m_expr(expr) |
| , m_operator(oper) |
| { |
| } |
| |
| virtual ~PostfixErrorNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| Operator m_operator; |
| }; |
| |
| class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| DeleteResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_ident(ident) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| Identifier m_ident; |
| }; |
| |
| class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| DeleteBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_subscript(subscript) |
| { |
| } |
| |
| virtual ~DeleteBracketNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| RefPtr<ExpressionNode> m_subscript; |
| }; |
| |
| class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| DeleteDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_ident(ident) |
| { |
| } |
| |
| virtual ~DeleteDotNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| Identifier m_ident; |
| }; |
| |
| class DeleteValueNode : public ExpressionNode { |
| public: |
| DeleteValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_expr(expr) |
| { |
| } |
| |
| virtual ~DeleteValueNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| }; |
| |
| class VoidNode : public ExpressionNode { |
| public: |
| VoidNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_expr(expr) |
| { |
| } |
| |
| virtual ~VoidNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| }; |
| |
| class TypeOfResolveNode : public ExpressionNode { |
| public: |
| TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL |
| : ExpressionNode(globalData, ResultType::stringType()) |
| , m_ident(ident) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } |
| |
| private: |
| Identifier m_ident; |
| }; |
| |
| class TypeOfValueNode : public ExpressionNode { |
| public: |
| TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : ExpressionNode(globalData, ResultType::stringType()) |
| , m_expr(expr) |
| { |
| } |
| |
| virtual ~TypeOfValueNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| }; |
| |
| class PrefixResolveNode : public PrePostResolveNode { |
| public: |
| PrefixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset) |
| , m_operator(oper) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| Operator m_operator; |
| }; |
| |
| class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { |
| public: |
| PrefixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_subscript(subscript) |
| , m_operator(oper) |
| { |
| } |
| |
| virtual ~PrefixBracketNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| RefPtr<ExpressionNode> m_subscript; |
| Operator m_operator; |
| }; |
| |
| class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { |
| public: |
| PrefixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_ident(ident) |
| , m_operator(oper) |
| { |
| } |
| |
| virtual ~PrefixDotNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| Identifier m_ident; |
| Operator m_operator; |
| }; |
| |
| class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| PrefixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_expr(expr) |
| , m_operator(oper) |
| { |
| } |
| |
| virtual ~PrefixErrorNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| Operator m_operator; |
| }; |
| |
| class UnaryOpNode : public ExpressionNode { |
| public: |
| UnaryOpNode(JSGlobalData* globalData, ExpressionNode* expr) |
| : ExpressionNode(globalData) |
| , m_expr(expr) |
| { |
| } |
| |
| UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr) |
| : ExpressionNode(globalData, type) |
| , m_expr(expr) |
| { |
| } |
| |
| virtual ~UnaryOpNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0; |
| |
| protected: |
| RefPtr<ExpressionNode> m_expr; |
| }; |
| |
| class UnaryPlusNode : public UnaryOpNode { |
| public: |
| UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : UnaryOpNode(globalData, ResultType::numberType(), expr) |
| { |
| } |
| |
| virtual ExpressionNode* stripUnaryPlus() { return m_expr.get(); } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_to_jsnumber; } |
| }; |
| |
| class NegateNode : public UnaryOpNode { |
| public: |
| NegateNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : UnaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_negate; } |
| }; |
| |
| class BitwiseNotNode : public UnaryOpNode { |
| public: |
| BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : UnaryOpNode(globalData, ResultType::forBitOp(), expr) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitnot; } |
| }; |
| |
| class LogicalNotNode : public UnaryOpNode { |
| public: |
| LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : UnaryOpNode(globalData, ResultType::booleanType(), expr) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_not; } |
| }; |
| |
| class BinaryOpNode : public ExpressionNode { |
| public: |
| BinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
| : ExpressionNode(globalData) |
| , m_expr1(expr1) |
| , m_expr2(expr2) |
| , m_rightHasAssignments(rightHasAssignments) |
| { |
| } |
| |
| BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
| : ExpressionNode(globalData, type) |
| , m_expr1(expr1) |
| , m_expr2(expr2) |
| , m_rightHasAssignments(rightHasAssignments) |
| { |
| } |
| |
| virtual ~BinaryOpNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0; |
| |
| protected: |
| RefPtr<ExpressionNode> m_expr1; |
| RefPtr<ExpressionNode> m_expr2; |
| bool m_rightHasAssignments; |
| }; |
| |
| class ReverseBinaryOpNode : public BinaryOpNode { |
| public: |
| ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
| : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) |
| : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| }; |
| |
| class MultNode : public BinaryOpNode { |
| public: |
| MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mul; } |
| }; |
| |
| class DivNode : public BinaryOpNode { |
| public: |
| DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_div; } |
| }; |
| |
| class ModNode : public BinaryOpNode { |
| public: |
| ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mod; } |
| }; |
| |
| class AddNode : public BinaryOpNode { |
| public: |
| AddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_add; } |
| }; |
| |
| class SubNode : public BinaryOpNode { |
| public: |
| SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_sub; } |
| }; |
| |
| class LeftShiftNode : public BinaryOpNode { |
| public: |
| LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lshift; } |
| }; |
| |
| class RightShiftNode : public BinaryOpNode { |
| public: |
| RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_rshift; } |
| }; |
| |
| class UnsignedRightShiftNode : public BinaryOpNode { |
| public: |
| UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_urshift; } |
| }; |
| |
| class LessNode : public BinaryOpNode { |
| public: |
| LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; } |
| }; |
| |
| class GreaterNode : public ReverseBinaryOpNode { |
| public: |
| GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; } |
| }; |
| |
| class LessEqNode : public BinaryOpNode { |
| public: |
| LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; } |
| }; |
| |
| class GreaterEqNode : public ReverseBinaryOpNode { |
| public: |
| GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; } |
| }; |
| |
| class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData { |
| public: |
| ThrowableBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments) |
| { |
| } |
| ThrowableBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments) |
| { |
| } |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| }; |
| |
| class InstanceOfNode : public ThrowableBinaryOpNode { |
| public: |
| InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : ThrowableBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_instanceof; } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| }; |
| |
| class InNode : public ThrowableBinaryOpNode { |
| public: |
| InNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : ThrowableBinaryOpNode(globalData, expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_in; } |
| }; |
| |
| class EqualNode : public BinaryOpNode { |
| public: |
| EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_eq; } |
| }; |
| |
| class NotEqualNode : public BinaryOpNode { |
| public: |
| NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_neq; } |
| }; |
| |
| class StrictEqualNode : public BinaryOpNode { |
| public: |
| StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_stricteq; } |
| }; |
| |
| class NotStrictEqualNode : public BinaryOpNode { |
| public: |
| NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_nstricteq; } |
| }; |
| |
| class BitAndNode : public BinaryOpNode { |
| public: |
| BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitand; } |
| }; |
| |
| class BitOrNode : public BinaryOpNode { |
| public: |
| BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitor; } |
| }; |
| |
| class BitXOrNode : public BinaryOpNode { |
| public: |
| BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL |
| : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) |
| { |
| } |
| |
| virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitxor; } |
| }; |
| |
| /** |
| * m_expr1 && m_expr2, m_expr1 || m_expr2 |
| */ |
| class LogicalOpNode : public ExpressionNode { |
| public: |
| LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) JSC_FAST_CALL |
| : ExpressionNode(globalData, ResultType::booleanType()) |
| , m_expr1(expr1) |
| , m_expr2(expr2) |
| , m_operator(oper) |
| { |
| } |
| |
| virtual ~LogicalOpNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr1; |
| RefPtr<ExpressionNode> m_expr2; |
| LogicalOperator m_operator; |
| }; |
| |
| /** |
| * The ternary operator, "m_logical ? m_expr1 : m_expr2" |
| */ |
| class ConditionalNode : public ExpressionNode { |
| public: |
| ConditionalNode(JSGlobalData* globalData, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_logical(logical) |
| , m_expr1(expr1) |
| , m_expr2(expr2) |
| { |
| } |
| |
| virtual ~ConditionalNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_logical; |
| RefPtr<ExpressionNode> m_expr1; |
| RefPtr<ExpressionNode> m_expr2; |
| }; |
| |
| class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| ReadModifyResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_ident(ident) |
| , m_right(right) |
| , m_operator(oper) |
| , m_rightHasAssignments(rightHasAssignments) |
| { |
| } |
| |
| virtual ~ReadModifyResolveNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| Identifier m_ident; |
| RefPtr<ExpressionNode> m_right; |
| size_t m_index; // Used by ReadModifyLocalVarNode. |
| Operator m_operator : 31; |
| bool m_rightHasAssignments : 1; |
| }; |
| |
| class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| AssignResolveNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_ident(ident) |
| , m_right(right) |
| , m_rightHasAssignments(rightHasAssignments) |
| { |
| } |
| |
| virtual ~AssignResolveNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| Identifier m_ident; |
| RefPtr<ExpressionNode> m_right; |
| size_t m_index; // Used by ReadModifyLocalVarNode. |
| bool m_rightHasAssignments; |
| }; |
| |
| class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { |
| public: |
| ReadModifyBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableSubExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_subscript(subscript) |
| , m_right(right) |
| , m_operator(oper) |
| , m_subscriptHasAssignments(subscriptHasAssignments) |
| , m_rightHasAssignments(rightHasAssignments) |
| { |
| } |
| |
| virtual ~ReadModifyBracketNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| RefPtr<ExpressionNode> m_subscript; |
| RefPtr<ExpressionNode> m_right; |
| Operator m_operator : 30; |
| bool m_subscriptHasAssignments : 1; |
| bool m_rightHasAssignments : 1; |
| }; |
| |
| class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| AssignBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_subscript(subscript) |
| , m_right(right) |
| , m_subscriptHasAssignments(subscriptHasAssignments) |
| , m_rightHasAssignments(rightHasAssignments) |
| { |
| } |
| |
| virtual ~AssignBracketNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| RefPtr<ExpressionNode> m_subscript; |
| RefPtr<ExpressionNode> m_right; |
| bool m_subscriptHasAssignments : 1; |
| bool m_rightHasAssignments : 1; |
| }; |
| |
| class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| AssignDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_ident(ident) |
| , m_right(right) |
| , m_rightHasAssignments(rightHasAssignments) |
| { |
| } |
| |
| virtual ~AssignDotNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| Identifier m_ident; |
| RefPtr<ExpressionNode> m_right; |
| bool m_rightHasAssignments; |
| }; |
| |
| class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { |
| public: |
| ReadModifyDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableSubExpressionData(divot, startOffset, endOffset) |
| , m_base(base) |
| , m_ident(ident) |
| , m_right(right) |
| , m_operator(oper) |
| , m_rightHasAssignments(rightHasAssignments) |
| { |
| } |
| |
| virtual ~ReadModifyDotNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_base; |
| Identifier m_ident; |
| RefPtr<ExpressionNode> m_right; |
| Operator m_operator : 31; |
| bool m_rightHasAssignments : 1; |
| }; |
| |
| class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData { |
| public: |
| AssignErrorNode(JSGlobalData* globalData, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , ThrowableExpressionData(divot, startOffset, endOffset) |
| , m_left(left) |
| , m_operator(oper) |
| , m_right(right) |
| { |
| } |
| |
| virtual ~AssignErrorNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_left; |
| Operator m_operator; |
| RefPtr<ExpressionNode> m_right; |
| }; |
| |
| class CommaNode : public ExpressionNode { |
| public: |
| CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_expr1(expr1) |
| , m_expr2(expr2) |
| { |
| } |
| |
| virtual ~CommaNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr1; |
| RefPtr<ExpressionNode> m_expr2; |
| }; |
| |
| class VarDeclCommaNode : public CommaNode { |
| public: |
| VarDeclCommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL |
| : CommaNode(globalData, expr1, expr2) |
| { |
| } |
| }; |
| |
| class ConstDeclNode : public ExpressionNode { |
| public: |
| ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in) JSC_FAST_CALL; |
| |
| virtual ~ConstDeclNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| Identifier m_ident; |
| RefPtr<ConstDeclNode> m_next; |
| RefPtr<ExpressionNode> m_init; |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| virtual RegisterID* emitCodeSingle(BytecodeGenerator&) JSC_FAST_CALL; |
| }; |
| |
| class ConstStatementNode : public StatementNode { |
| public: |
| ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_next(next) |
| { |
| } |
| |
| virtual ~ConstStatementNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ConstDeclNode> m_next; |
| }; |
| |
| typedef Vector<RefPtr<StatementNode> > StatementVector; |
| |
| class SourceElements : public ParserRefCounted { |
| public: |
| SourceElements(JSGlobalData* globalData) : ParserRefCounted(globalData) {} |
| |
| void append(PassRefPtr<StatementNode>); |
| void releaseContentsIntoVector(StatementVector& destination) |
| { |
| ASSERT(destination.isEmpty()); |
| m_statements.swap(destination); |
| destination.shrinkToFit(); |
| } |
| |
| private: |
| StatementVector m_statements; |
| }; |
| |
| class BlockNode : public StatementNode { |
| public: |
| BlockNode(JSGlobalData*, SourceElements* children) JSC_FAST_CALL; |
| |
| virtual ~BlockNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| StatementVector& children() { return m_children; } |
| |
| virtual bool isBlock() const JSC_FAST_CALL { return true; } |
| |
| private: |
| StatementVector m_children; |
| }; |
| |
| class EmptyStatementNode : public StatementNode { |
| public: |
| EmptyStatementNode(JSGlobalData* globalData) JSC_FAST_CALL // debug |
| : StatementNode(globalData) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isEmptyStatement() const JSC_FAST_CALL { return true; } |
| }; |
| |
| class DebuggerStatementNode : public StatementNode { |
| public: |
| DebuggerStatementNode(JSGlobalData* globalData) JSC_FAST_CALL |
| : StatementNode(globalData) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| }; |
| |
| class ExprStatementNode : public StatementNode { |
| public: |
| ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_expr(expr) |
| { |
| } |
| |
| virtual bool isExprStatement() const JSC_FAST_CALL { return true; } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| ExpressionNode* expr() const { return m_expr.get(); } |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| }; |
| |
| class VarStatementNode : public StatementNode { |
| public: |
| VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_expr(expr) |
| { |
| } |
| |
| virtual ~VarStatementNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| }; |
| |
| class IfNode : public StatementNode { |
| public: |
| IfNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_condition(condition) |
| , m_ifBlock(ifBlock) |
| { |
| } |
| |
| virtual ~IfNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| protected: |
| RefPtr<ExpressionNode> m_condition; |
| RefPtr<StatementNode> m_ifBlock; |
| }; |
| |
| class IfElseNode : public IfNode { |
| public: |
| IfElseNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) JSC_FAST_CALL |
| : IfNode(globalData, condition, ifBlock) |
| , m_elseBlock(elseBlock) |
| { |
| } |
| |
| virtual ~IfElseNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<StatementNode> m_elseBlock; |
| }; |
| |
| class DoWhileNode : public StatementNode { |
| public: |
| DoWhileNode(JSGlobalData* globalData, StatementNode* statement, ExpressionNode* expr) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_statement(statement) |
| , m_expr(expr) |
| { |
| } |
| |
| virtual ~DoWhileNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isLoop() const JSC_FAST_CALL { return true; } |
| |
| private: |
| RefPtr<StatementNode> m_statement; |
| RefPtr<ExpressionNode> m_expr; |
| }; |
| |
| class WhileNode : public StatementNode { |
| public: |
| WhileNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_expr(expr) |
| , m_statement(statement) |
| { |
| } |
| |
| virtual ~WhileNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isLoop() const JSC_FAST_CALL { return true; } |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| RefPtr<StatementNode> m_statement; |
| }; |
| |
| class ForNode : public StatementNode { |
| public: |
| ForNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_expr1(expr1) |
| , m_expr2(expr2) |
| , m_expr3(expr3) |
| , m_statement(statement) |
| , m_expr1WasVarDecl(expr1 && expr1WasVarDecl) |
| { |
| ASSERT(statement); |
| } |
| |
| virtual ~ForNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isLoop() const JSC_FAST_CALL { return true; } |
| |
| private: |
| RefPtr<ExpressionNode> m_expr1; |
| RefPtr<ExpressionNode> m_expr2; |
| RefPtr<ExpressionNode> m_expr3; |
| RefPtr<StatementNode> m_statement; |
| bool m_expr1WasVarDecl; |
| }; |
| |
| class ForInNode : public StatementNode, public ThrowableExpressionData { |
| public: |
| ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*) JSC_FAST_CALL; |
| ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset) JSC_FAST_CALL; |
| |
| virtual ~ForInNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| virtual bool isLoop() const JSC_FAST_CALL { return true; } |
| |
| private: |
| Identifier m_ident; |
| RefPtr<ExpressionNode> m_init; |
| RefPtr<ExpressionNode> m_lexpr; |
| RefPtr<ExpressionNode> m_expr; |
| RefPtr<StatementNode> m_statement; |
| bool m_identIsVarDecl; |
| }; |
| |
| class ContinueNode : public StatementNode, public ThrowableExpressionData { |
| public: |
| ContinueNode(JSGlobalData* globalData) JSC_FAST_CALL |
| : StatementNode(globalData) |
| { |
| } |
| |
| ContinueNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_ident(ident) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| Identifier m_ident; |
| }; |
| |
| class BreakNode : public StatementNode, public ThrowableExpressionData { |
| public: |
| BreakNode(JSGlobalData* globalData) JSC_FAST_CALL |
| : StatementNode(globalData) |
| { |
| } |
| |
| BreakNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_ident(ident) |
| { |
| } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| Identifier m_ident; |
| }; |
| |
| class ReturnNode : public StatementNode, public ThrowableExpressionData { |
| public: |
| ReturnNode(JSGlobalData* globalData, ExpressionNode* value) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_value(value) |
| { |
| } |
| |
| virtual ~ReturnNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| virtual bool isReturnNode() const JSC_FAST_CALL { return true; } |
| |
| private: |
| RefPtr<ExpressionNode> m_value; |
| }; |
| |
| class WithNode : public StatementNode { |
| public: |
| WithNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_expr(expr) |
| , m_statement(statement) |
| , m_divot(divot) |
| , m_expressionLength(expressionLength) |
| { |
| } |
| |
| virtual ~WithNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| RefPtr<StatementNode> m_statement; |
| uint32_t m_divot; |
| uint32_t m_expressionLength; |
| }; |
| |
| class LabelNode : public StatementNode, public ThrowableExpressionData { |
| public: |
| LabelNode(JSGlobalData* globalData, const Identifier& name, StatementNode* statement) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_name(name) |
| , m_statement(statement) |
| { |
| } |
| |
| virtual ~LabelNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| Identifier m_name; |
| RefPtr<StatementNode> m_statement; |
| }; |
| |
| class ThrowNode : public StatementNode, public ThrowableExpressionData { |
| public: |
| ThrowNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_expr(expr) |
| { |
| } |
| |
| virtual ~ThrowNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| }; |
| |
| class TryNode : public StatementNode { |
| public: |
| TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_tryBlock(tryBlock) |
| , m_exceptionIdent(exceptionIdent) |
| , m_catchBlock(catchBlock) |
| , m_finallyBlock(finallyBlock) |
| , m_catchHasEval(catchHasEval) |
| { |
| } |
| |
| virtual ~TryNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<StatementNode> m_tryBlock; |
| Identifier m_exceptionIdent; |
| RefPtr<StatementNode> m_catchBlock; |
| RefPtr<StatementNode> m_finallyBlock; |
| bool m_catchHasEval; |
| }; |
| |
| class ParameterNode : public ParserRefCounted { |
| public: |
| ParameterNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_ident(ident) |
| { |
| } |
| |
| ParameterNode(JSGlobalData* globalData, ParameterNode* l, const Identifier& ident) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_ident(ident) |
| { |
| l->m_next = this; |
| } |
| |
| virtual ~ParameterNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| const Identifier& ident() const JSC_FAST_CALL { return m_ident; } |
| ParameterNode* nextParam() const JSC_FAST_CALL { return m_next.get(); } |
| |
| private: |
| Identifier m_ident; |
| RefPtr<ParameterNode> m_next; |
| }; |
| |
| struct ScopeNodeData { |
| typedef DeclarationStacks::VarStack VarStack; |
| typedef DeclarationStacks::FunctionStack FunctionStack; |
| |
| ScopeNodeData(SourceElements*, VarStack*, FunctionStack*, int numConstants); |
| |
| VarStack m_varStack; |
| FunctionStack m_functionStack; |
| int m_numConstants; |
| StatementVector m_children; |
| |
| void mark(); |
| }; |
| |
| class ScopeNode : public StatementNode { |
| public: |
| typedef DeclarationStacks::VarStack VarStack; |
| typedef DeclarationStacks::FunctionStack FunctionStack; |
| |
| ScopeNode(JSGlobalData*) JSC_FAST_CALL; |
| ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL; |
| virtual ~ScopeNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| void adoptData(std::auto_ptr<ScopeNodeData> data) { m_data.adopt(data); } |
| ScopeNodeData* data() const { return m_data.get(); } |
| void destroyData() { m_data.clear(); } |
| |
| const SourceCode& source() const { return m_source; } |
| const UString& sourceURL() const JSC_FAST_CALL { return m_source.provider()->url(); } |
| intptr_t sourceID() const { return m_source.provider()->asID(); } |
| |
| 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; } |
| void setUsesArguments() { m_features |= ArgumentsFeature; } |
| bool usesThis() const { return m_features & ThisFeature; } |
| bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); } |
| |
| VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } |
| FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } |
| |
| StatementVector& children() { ASSERT(m_data); return m_data->m_children; } |
| |
| 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; |
| } |
| |
| virtual void mark() { } |
| |
| 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 ProgramNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; |
| |
| ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL |
| { |
| if (!m_code) |
| generateBytecode(scopeChain); |
| return *m_code; |
| } |
| |
| private: |
| ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; |
| |
| void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| OwnPtr<ProgramCodeBlock> m_code; |
| }; |
| |
| class EvalNode : public ScopeNode { |
| public: |
| static EvalNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; |
| |
| EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL |
| { |
| if (!m_code) |
| generateBytecode(scopeChain); |
| return *m_code; |
| } |
| |
| EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL; |
| |
| virtual void mark(); |
| |
| private: |
| EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; |
| |
| void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| OwnPtr<EvalCodeBlock> m_code; |
| }; |
| |
| class FunctionBodyNode : public ScopeNode { |
| friend class JIT; |
| public: |
| static FunctionBodyNode* create(JSGlobalData*) JSC_FAST_CALL; |
| static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; |
| virtual ~FunctionBodyNode(); |
| |
| const Identifier* parameters() const JSC_FAST_CALL { return m_parameters; } |
| size_t parameterCount() const { return m_parameterCount; } |
| UString paramString() const JSC_FAST_CALL; |
| Identifier* copyParameters(); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| CodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL |
| { |
| ASSERT(scopeChain); |
| if (!m_code) |
| generateBytecode(scopeChain); |
| return *m_code; |
| } |
| |
| CodeBlock& generatedBytecode() JSC_FAST_CALL |
| { |
| ASSERT(m_code); |
| return *m_code; |
| } |
| |
| bool isGenerated() JSC_FAST_CALL |
| { |
| return m_code; |
| } |
| |
| virtual void mark(); |
| |
| void finishParsing(const SourceCode&, ParameterNode*); |
| void finishParsing(Identifier* parameters, size_t parameterCount); |
| |
| UString toSourceString() const JSC_FAST_CALL { return source().toString(); } |
| |
| // These objects are ref/deref'd a lot in the scope chain, so this is a faster ref/deref. |
| // If the virtual machine changes so this doesn't happen as much we can change back. |
| void ref() |
| { |
| if (++m_refCount == 1) |
| ScopeNode::ref(); |
| } |
| void deref() |
| { |
| ASSERT(m_refCount); |
| if (!--m_refCount) |
| ScopeNode::deref(); |
| } |
| |
| CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL; |
| |
| private: |
| FunctionBodyNode(JSGlobalData*) JSC_FAST_CALL; |
| FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; |
| |
| void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; |
| |
| Identifier* m_parameters; |
| size_t m_parameterCount; |
| OwnPtr<CodeBlock> m_code; |
| unsigned m_refCount; |
| }; |
| |
| class FuncExprNode : public ExpressionNode { |
| public: |
| FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL |
| : ExpressionNode(globalData) |
| , m_ident(ident) |
| , m_parameter(parameter) |
| , m_body(body) |
| { |
| m_body->finishParsing(source, m_parameter.get()); |
| } |
| |
| virtual ~FuncExprNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual bool isFuncExprNode() const JSC_FAST_CALL { return true; } |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL; |
| |
| FunctionBodyNode* body() { return m_body.get(); } |
| |
| private: |
| Identifier m_ident; |
| RefPtr<ParameterNode> m_parameter; |
| RefPtr<FunctionBodyNode> m_body; |
| }; |
| |
| class FuncDeclNode : public StatementNode { |
| public: |
| FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_ident(ident) |
| , m_parameter(parameter) |
| , m_body(body) |
| { |
| m_body->finishParsing(source, m_parameter.get()); |
| } |
| |
| virtual ~FuncDeclNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL; |
| |
| Identifier m_ident; |
| |
| FunctionBodyNode* body() { return m_body.get(); } |
| |
| private: |
| RefPtr<ParameterNode> m_parameter; |
| RefPtr<FunctionBodyNode> m_body; |
| }; |
| |
| class CaseClauseNode : public ParserRefCounted { |
| public: |
| CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_expr(expr) |
| { |
| } |
| |
| CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr, SourceElements* children) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_expr(expr) |
| { |
| if (children) |
| children->releaseContentsIntoVector(m_children); |
| } |
| |
| virtual ~CaseClauseNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| ExpressionNode* expr() const { return m_expr.get(); } |
| StatementVector& children() { return m_children; } |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| StatementVector m_children; |
| }; |
| |
| class ClauseListNode : public ParserRefCounted { |
| public: |
| ClauseListNode(JSGlobalData* globalData, CaseClauseNode* clause) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_clause(clause) |
| { |
| } |
| |
| ClauseListNode(JSGlobalData* globalData, ClauseListNode* clauseList, CaseClauseNode* clause) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_clause(clause) |
| { |
| clauseList->m_next = this; |
| } |
| |
| virtual ~ClauseListNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| CaseClauseNode* getClause() const JSC_FAST_CALL { return m_clause.get(); } |
| ClauseListNode* getNext() const JSC_FAST_CALL { return m_next.get(); } |
| |
| private: |
| RefPtr<CaseClauseNode> m_clause; |
| RefPtr<ClauseListNode> m_next; |
| }; |
| |
| class CaseBlockNode : public ParserRefCounted { |
| public: |
| CaseBlockNode(JSGlobalData* globalData, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) JSC_FAST_CALL |
| : ParserRefCounted(globalData) |
| , m_list1(list1) |
| , m_defaultClause(defaultClause) |
| , m_list2(list2) |
| { |
| } |
| |
| virtual ~CaseBlockNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL; |
| |
| private: |
| SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num); |
| RefPtr<ClauseListNode> m_list1; |
| RefPtr<CaseClauseNode> m_defaultClause; |
| RefPtr<ClauseListNode> m_list2; |
| }; |
| |
| class SwitchNode : public StatementNode { |
| public: |
| SwitchNode(JSGlobalData* globalData, ExpressionNode* expr, CaseBlockNode* block) JSC_FAST_CALL |
| : StatementNode(globalData) |
| , m_expr(expr) |
| , m_block(block) |
| { |
| } |
| |
| virtual ~SwitchNode(); |
| virtual void releaseNodes(NodeReleaser&); |
| |
| virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; |
| |
| private: |
| RefPtr<ExpressionNode> m_expr; |
| RefPtr<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_ |