blob: a70d3506da55f9c54885a918141397a8540a19f5 [file] [log] [blame]
/*
* 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 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 "JSString.h"
#include "JSType.h"
#include "Opcode.h"
#include "RegisterID.h"
#include "ResultType.h"
#include "SourceCode.h"
#include "SymbolTable.h"
#include "regexp.h"
#include <wtf/ListRefPtr.h>
#include <wtf/MathExtras.h>
#include <wtf/OwnPtr.h>
#include <wtf/UnusedParam.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 CodeGenerator;
class FuncDeclNode;
class Node;
class EvalCodeBlock;
class JSFunction;
class ProgramCodeBlock;
class PropertyListNode;
class SourceStream;
typedef unsigned int 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
};
enum Precedence {
PrecPrimary,
PrecMember,
PrecCall,
PrecLeftHandSide,
PrecPostfix,
PrecUnary,
PrecMultiplicative,
PrecAdditive,
PrecShift,
PrecRelational,
PrecEquality,
PrecBitwiseAnd,
PrecBitwiseXor,
PrecBitwiseOr,
PrecLogicalAnd,
PrecLogicalOr,
PrecConditional,
PrecAssignment,
PrecExpression
};
namespace DeclarationStacks {
typedef Vector<Node*, 16> NodeStack;
enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
typedef Vector<std::pair<Identifier, unsigned>, 16> VarStack;
typedef Vector<RefPtr<FuncDeclNode>, 16> FunctionStack;
}
struct SwitchInfo {
enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString };
uint32_t opcodeOffset;
SwitchType switchType;
};
class ParserRefCounted : Noncopyable {
protected:
ParserRefCounted(JSGlobalData*) JSC_FAST_CALL;
JSGlobalData* m_globalData;
public:
void ref() JSC_FAST_CALL;
void deref() JSC_FAST_CALL;
bool hasOneRef() JSC_FAST_CALL;
static void deleteNewObjects(JSGlobalData*) JSC_FAST_CALL;
virtual ~ParserRefCounted();
};
class Node : public ParserRefCounted {
public:
typedef DeclarationStacks::NodeStack NodeStack;
typedef DeclarationStacks::VarStack VarStack;
typedef DeclarationStacks::FunctionStack FunctionStack;
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* emitCode(CodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL
{
ASSERT_WITH_MESSAGE(0, "Don't know how to generate code for:\n%s\n", toString().ascii());
UNUSED_PARAM(dst);
return 0;
} // FIXME: Make this pure virtual.
UString toString() const JSC_FAST_CALL;
int lineNo() const { return m_line; }
virtual bool isReturnNode() const JSC_FAST_CALL { return false; }
// Serialization.
virtual void streamTo(SourceStream&) const JSC_FAST_CALL = 0;
virtual Precedence precedence() const = 0;
virtual bool needsParensIfLeftmost() const { return false; }
protected:
int m_line;
};
class ExpressionNode : public Node {
public:
ExpressionNode(JSGlobalData* globalData, ResultType resultDesc = ResultType::unknown()) 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(CodeGenerator&) 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 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 Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
virtual bool isEmptyStatement() 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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
};
class BooleanNode : public ExpressionNode {
public:
BooleanNode(JSGlobalData* globalData, bool value) JSC_FAST_CALL
: ExpressionNode(globalData, ResultType::boolean())
, m_value(value)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return true; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
protected:
bool m_value;
};
class NumberNode : public ExpressionNode {
public:
NumberNode(JSGlobalData* globalData, double v) JSC_FAST_CALL
: ExpressionNode(globalData, ResultType::constNumber())
, m_double(v)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return signbit(m_double) ? PrecUnary : PrecPrimary; }
virtual bool isNumber() const JSC_FAST_CALL { return true; }
virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return true; }
double value() const JSC_FAST_CALL { return m_double; }
virtual void setValue(double d) JSC_FAST_CALL { m_double = d; }
protected:
double m_double;
};
class ImmediateNumberNode : public NumberNode {
public:
ImmediateNumberNode(JSGlobalData* globalData, JSValue* v, double d) JSC_FAST_CALL
: NumberNode(globalData, d)
, m_value(v)
{
ASSERT(v == JSImmediate::from(d));
}
virtual void setValue(double d) JSC_FAST_CALL { m_double = d; m_value = JSImmediate::from(d); ASSERT(m_value); }
private:
JSValue* m_value; // This is never a JSCell, only JSImmediate, thus no ProtectedPtr
};
class StringNode : public ExpressionNode {
public:
StringNode(JSGlobalData* globalData, const Identifier& v) JSC_FAST_CALL
: ExpressionNode(globalData, ResultType::string())
, m_value(v)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual bool isString() const JSC_FAST_CALL { return true; }
const Identifier& value() { return m_value; }
virtual bool isPure(CodeGenerator&) const JSC_FAST_CALL { return true; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
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(CodeGenerator&, ErrorType, const char* msg);
RegisterID* emitThrowError(CodeGenerator&, ErrorType, const char* msg, const Identifier&);
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 <= m_divot);
if ((m_divot - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot
return;
m_subexpressionDivotOffset = m_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 >= m_divot);
if ((subexpressionDivot - m_divot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot
return;
m_subexpressionDivotOffset = subexpressionDivot - m_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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
private:
UString m_pattern;
UString m_flags;
};
class ThisNode : public ExpressionNode {
public:
ThisNode(JSGlobalData* globalData) JSC_FAST_CALL
: ExpressionNode(globalData)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
};
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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
virtual bool isPure(CodeGenerator&) 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; }
protected:
Identifier m_ident;
int32_t m_startOffset;
};
class ElementNode : public Node {
public:
ElementNode(JSGlobalData* globalData, int elision, ExpressionNode* node) JSC_FAST_CALL
: Node(globalData)
, m_elision(elision)
, m_node(node)
{
}
ElementNode(JSGlobalData* globalData, ElementNode* l, int elision, ExpressionNode* node) JSC_FAST_CALL
: Node(globalData)
, m_elision(elision)
, m_node(node)
{
l->m_next = this;
}
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
int elision() const { return m_elision; }
ExpressionNode* value() { return m_node.get(); }
ElementNode* next() { return m_next.get(); }
PassRefPtr<ElementNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
private:
ListRefPtr<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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
private:
RefPtr<ElementNode> m_element;
int m_elision;
bool m_optional;
};
class PropertyNode : public Node {
public:
enum Type { Constant, Getter, Setter };
PropertyNode(JSGlobalData* globalData, const Identifier& name, ExpressionNode* assign, Type type) JSC_FAST_CALL
: Node(globalData)
, m_name(name)
, m_assign(assign)
, m_type(type)
{
}
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
PassRefPtr<PropertyListNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
private:
friend class ObjectLiteralNode;
RefPtr<PropertyNode> m_node;
ListRefPtr<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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
virtual bool needsParensIfLeftmost() const { return true; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecMember; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecMember; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
PassRefPtr<ArgumentListNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
ListRefPtr<ArgumentListNode> m_next;
RefPtr<ExpressionNode> m_expr;
};
class ArgumentsNode : public Node {
public:
ArgumentsNode(JSGlobalData* globalData) JSC_FAST_CALL
: Node(globalData)
{
}
ArgumentsNode(JSGlobalData* globalData, ArgumentListNode* listNode) JSC_FAST_CALL
: Node(globalData)
, m_listNode(listNode)
{
}
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecLeftHandSide; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
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::constNumber()) // 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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
private:
RefPtr<ExpressionNode> m_expr;
};
class VoidNode : public ExpressionNode {
public:
VoidNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
: ExpressionNode(globalData)
, m_expr(expr)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
private:
RefPtr<ExpressionNode> m_expr;
};
class TypeOfResolveNode : public ExpressionNode {
public:
TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
: ExpressionNode(globalData, ResultType::string())
, m_ident(ident)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
const Identifier& identifier() const JSC_FAST_CALL { return m_ident; }
protected:
Identifier m_ident;
size_t m_index; // Used by LocalTypeOfNode.
};
class TypeOfValueNode : public ExpressionNode {
public:
TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
: ExpressionNode(globalData, ResultType::string())
, m_expr(expr)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual OpcodeID opcode() 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::constNumber(), expr)
{
}
virtual ExpressionNode* stripUnaryPlus() { return m_expr.get(); }
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_to_jsnumber; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
};
class NegateNode : public UnaryOpNode {
public:
NegateNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
: UnaryOpNode(globalData, ResultType::reusableNumber(), expr)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_negate; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
};
class BitwiseNotNode : public UnaryOpNode {
public:
BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
: UnaryOpNode(globalData, ResultType::reusableNumber(), expr)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitnot; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
};
class LogicalNotNode : public UnaryOpNode {
public:
LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
: UnaryOpNode(globalData, ResultType::boolean(), expr)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_not; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
};
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual OpcodeID opcode() const JSC_FAST_CALL = 0;
protected:
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
bool m_rightHasAssignments;
};
class ReverseBinaryOpNode : public ExpressionNode {
public:
ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
: ExpressionNode(globalData)
, m_expr1(expr1)
, m_expr2(expr2)
, m_rightHasAssignments(rightHasAssignments)
{
}
ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
: ExpressionNode(globalData, type)
, m_expr1(expr1)
, m_expr2(expr2)
, m_rightHasAssignments(rightHasAssignments)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual OpcodeID opcode() const JSC_FAST_CALL = 0;
protected:
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
bool m_rightHasAssignments;
};
class MultNode : public BinaryOpNode {
public:
MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_mul; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecMultiplicative; }
};
class DivNode : public BinaryOpNode {
public:
DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_div; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecMultiplicative; }
};
class ModNode : public BinaryOpNode {
public:
ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_mod; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecMultiplicative; }
};
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 opcode() const JSC_FAST_CALL { return op_add; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecAdditive; }
};
class SubNode : public BinaryOpNode {
public:
SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_sub; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecAdditive; }
};
class LeftShiftNode : public BinaryOpNode {
public:
LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_lshift; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecShift; }
};
class RightShiftNode : public BinaryOpNode {
public:
RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_rshift; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecShift; }
};
class UnsignedRightShiftNode : public BinaryOpNode {
public:
UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_urshift; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecShift; }
};
class LessNode : public BinaryOpNode {
public:
LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_less; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
};
class GreaterNode : public ReverseBinaryOpNode {
public:
GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: ReverseBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_less; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
};
class LessEqNode : public BinaryOpNode {
public:
LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_lesseq; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
};
class GreaterEqNode : public ReverseBinaryOpNode {
public:
GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: ReverseBinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_lesseq; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
};
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* emitCode(CodeGenerator&, 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::boolean(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_instanceof; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
virtual RegisterID* emitCode(CodeGenerator&, 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 opcode() const JSC_FAST_CALL { return op_in; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
};
class EqualNode : public BinaryOpNode {
public:
EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_eq; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecEquality; }
};
class NotEqualNode : public BinaryOpNode {
public:
NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_neq; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecEquality; }
};
class StrictEqualNode : public BinaryOpNode {
public:
StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_stricteq; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecEquality; }
};
class NotStrictEqualNode : public BinaryOpNode {
public:
NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::boolean(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_nstricteq; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecEquality; }
};
class BitAndNode : public BinaryOpNode {
public:
BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitand; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecBitwiseAnd; }
};
class BitOrNode : public BinaryOpNode {
public:
BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitor; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecBitwiseOr; }
};
class BitXOrNode : public BinaryOpNode {
public:
BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL
: BinaryOpNode(globalData, ResultType::reusableNumber(), expr1, expr2, rightHasAssignments)
{
}
virtual OpcodeID opcode() const JSC_FAST_CALL { return op_bitxor; }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecBitwiseXor; }
};
/**
* 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::boolean())
, m_expr1(expr1)
, m_expr2(expr2)
, m_operator(oper)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return (m_operator == OpLogicalAnd) ? PrecLogicalAnd : PrecLogicalOr; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecConditional; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecExpression; }
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)
{
}
virtual Precedence precedence() const { return PrecAssignment; }
};
class ConstDeclNode : public ExpressionNode {
public:
ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
PassRefPtr<ConstDeclNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
Identifier m_ident;
ListRefPtr<ConstDeclNode> m_next;
RefPtr<ExpressionNode> m_init;
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual RegisterID* emitCodeSingle(CodeGenerator&) JSC_FAST_CALL;
};
class ConstStatementNode : public StatementNode {
public:
ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next) JSC_FAST_CALL
: StatementNode(globalData)
, m_next(next)
{
}
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual RegisterID* emitCode(CodeGenerator&, 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);
}
private:
StatementVector m_statements;
};
class BlockNode : public StatementNode {
public:
BlockNode(JSGlobalData*, SourceElements* children) JSC_FAST_CALL;
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
StatementVector& children() { return m_children; }
virtual bool isBlock() const JSC_FAST_CALL { return true; }
protected:
StatementVector m_children;
};
class EmptyStatementNode : public StatementNode {
public:
EmptyStatementNode(JSGlobalData* globalData) JSC_FAST_CALL // debug
: StatementNode(globalData)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
};
class ExprStatementNode : public StatementNode {
public:
ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
: StatementNode(globalData)
, m_expr(expr)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
private:
RefPtr<ExpressionNode> m_expr;
};
class VarStatementNode : public StatementNode {
public:
VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
: StatementNode(globalData)
, m_expr(expr)
{
}
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
private:
RefPtr<ExpressionNode> m_expr;
};
class TryNode : public StatementNode {
public:
TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock) JSC_FAST_CALL
: StatementNode(globalData)
, m_tryBlock(tryBlock)
, m_exceptionIdent(exceptionIdent)
, m_catchBlock(catchBlock)
, m_finallyBlock(finallyBlock)
{
}
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL;
private:
RefPtr<StatementNode> m_tryBlock;
Identifier m_exceptionIdent;
RefPtr<StatementNode> m_catchBlock;
RefPtr<StatementNode> m_finallyBlock;
};
class ParameterNode : public Node {
public:
ParameterNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL
: Node(globalData)
, m_ident(ident)
{
}
ParameterNode(JSGlobalData* globalData, ParameterNode* l, const Identifier& ident) JSC_FAST_CALL
: Node(globalData)
, m_ident(ident)
{
l->m_next = this;
}
Identifier ident() JSC_FAST_CALL { return m_ident; }
ParameterNode *nextParam() JSC_FAST_CALL { return m_next.get(); }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
PassRefPtr<ParameterNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
private:
friend class FuncDeclNode;
friend class FuncExprNode;
Identifier m_ident;
ListRefPtr<ParameterNode> m_next;
};
class ScopeNode : public BlockNode {
public:
ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
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(); }
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() { return m_varStack; }
FunctionStack& functionStack() { return m_functionStack; }
int neededConstants()
{
// We may need 1 more constant than the count given by the parser,
// because of the various uses of jsUndefined().
return m_numConstants + 1;
}
protected:
void setSource(const SourceCode& source) { m_source = source; }
VarStack m_varStack;
FunctionStack m_functionStack;
private:
SourceCode m_source;
CodeFeatures m_features;
int m_numConstants;
};
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)
generateCode(scopeChain);
return *m_code;
}
private:
ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
void generateCode(ScopeChainNode*) JSC_FAST_CALL;
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
Vector<size_t> m_varIndexes; // Storage indexes belonging to the nodes in m_varStack. (Recorded to avoid double lookup.)
Vector<size_t> m_functionIndexes; // Storage indexes belonging to the nodes in m_functionStack. (Recorded to avoid double lookup.)
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)
generateCode(scopeChain);
return *m_code;
}
private:
EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
void generateCode(ScopeChainNode*) JSC_FAST_CALL;
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
OwnPtr<EvalCodeBlock> m_code;
};
class FunctionBodyNode : public ScopeNode {
public:
static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL;
~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* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
SymbolTable& symbolTable() { return m_symbolTable; } // FIXME: Remove this
CodeBlock& byteCode(ScopeChainNode* scopeChain) JSC_FAST_CALL
{
ASSERT(scopeChain);
if (!m_code)
generateCode(scopeChain);
return *m_code;
}
CodeBlock& generatedByteCode() JSC_FAST_CALL
{
ASSERT(m_code);
return *m_code;
}
bool isGenerated() JSC_FAST_CALL
{
return m_code;
}
void mark();
void finishParsing(const SourceCode&, ParameterNode*);
void finishParsing(Identifier* parameters, size_t parameterCount);
UString toSourceString() const JSC_FAST_CALL { return UString("{") + source().toString() + UString("}"); }
// 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();
}
protected:
FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
private:
void generateCode(ScopeChainNode*) JSC_FAST_CALL;
Identifier* m_parameters;
size_t m_parameterCount;
SymbolTable m_symbolTable;
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { return PrecMember; }
virtual bool needsParensIfLeftmost() const { return true; }
FunctionBodyNode* body() { return m_body.get(); }
private:
// Used for streamTo
friend class PropertyNode;
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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 Node {
public:
CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL
: Node(globalData)
, m_expr(expr)
{
}
CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr, SourceElements* children) JSC_FAST_CALL
: Node(globalData)
, m_expr(expr)
{
if (children)
children->releaseContentsIntoVector(m_children);
}
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
ExpressionNode* expr() const { return m_expr.get(); }
StatementVector& children() { return m_children; }
private:
RefPtr<ExpressionNode> m_expr;
StatementVector m_children;
};
class ClauseListNode : public Node {
public:
ClauseListNode(JSGlobalData* globalData, CaseClauseNode* clause) JSC_FAST_CALL
: Node(globalData)
, m_clause(clause)
{
}
ClauseListNode(JSGlobalData* globalData, ClauseListNode* clauseList, CaseClauseNode* clause) JSC_FAST_CALL
: Node(globalData)
, m_clause(clause)
{
clauseList->m_next = this;
}
CaseClauseNode* getClause() const JSC_FAST_CALL { return m_clause.get(); }
ClauseListNode* getNext() const JSC_FAST_CALL { return m_next.get(); }
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
PassRefPtr<ClauseListNode> releaseNext() JSC_FAST_CALL { return m_next.release(); }
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
private:
friend class CaseBlockNode;
RefPtr<CaseClauseNode> m_clause;
ListRefPtr<ClauseListNode> m_next;
};
class CaseBlockNode : public Node {
public:
CaseBlockNode(JSGlobalData* globalData, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) JSC_FAST_CALL
: Node(globalData)
, m_list1(list1)
, m_defaultClause(defaultClause)
, m_list2(list2)
{
}
RegisterID* emitCodeForBlock(CodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const JSC_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
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 RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) JSC_FAST_CALL;
virtual void streamTo(SourceStream&) const 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_