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;
+ const CodeFeatures StrictModeFeature = 1 << 7;
+ const CodeFeatures ShadowsArgumentsFeature = 1 << 8;
+
+
+ const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature;
enum Operator {
OpEqual,
OpLogicalOr
};
+ typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet;
+
namespace DeclarationStacks {
enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
typedef Vector<std::pair<const Identifier*, unsigned> > VarStack;
virtual bool isCommaNode() const { return false; }
virtual bool isSimpleArray() const { return false; }
virtual bool isAdd() const { return false; }
+ virtual bool isSubtract() const { return false; }
virtual bool hasConditionContextCodegen() const { return false; }
virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); }
uint16_t endOffset() const { return m_endOffset; }
protected:
- RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* message);
- RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* message, const UString&);
- RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* message, const Identifier&);
+ RegisterID* emitThrowReferenceError(BytecodeGenerator&, const UString& message);
private:
uint32_t m_divot;
class PropertyNode : public ParserArenaFreeable {
public:
- enum Type { Constant, Getter, Setter };
+ enum Type { Constant = 1, Getter = 2, Setter = 4 };
PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type);
PropertyNode(JSGlobalData*, double name, ExpressionNode* value, Type);
const Identifier& name() const { return m_name; }
+ Type type() const { return m_type; }
private:
friend class PropertyListNode;
RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
+ ExpressionNode* lhs() { return m_expr1; };
+ ExpressionNode* rhs() { return m_expr2; };
+
private:
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
class SubNode : public BinaryOpNode {
public:
SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+
+ virtual bool isSubtract() const { return true; }
};
class LeftShiftNode : public BinaryOpNode {
public:
BlockNode(JSGlobalData*, SourceElements* = 0);
+ StatementNode* singleStatement() const;
StatementNode* lastStatement() const;
private:
public:
ReturnNode(JSGlobalData*, ExpressionNode* value);
+ ExpressionNode* value() { return m_value; }
+
private:
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
ParameterNode* m_next;
};
- struct ScopeNodeData : FastAllocBase {
+ struct ScopeNodeData {
+ WTF_MAKE_FAST_ALLOCATED;
+ public:
typedef DeclarationStacks::VarStack VarStack;
typedef DeclarationStacks::FunctionStack FunctionStack;
- ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, int numConstants);
+ ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, int numConstants);
ParserArena m_arena;
VarStack m_varStack;
FunctionStack m_functionStack;
int m_numConstants;
SourceElements* m_statements;
+ IdentifierSet m_capturedVariables;
};
class ScopeNode : public StatementNode, public ParserArenaRefCounted {
typedef DeclarationStacks::VarStack VarStack;
typedef DeclarationStacks::FunctionStack FunctionStack;
- ScopeNode(JSGlobalData*);
- ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants);
+ ScopeNode(JSGlobalData*, bool inStrictContext);
+ ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants);
using ParserArenaRefCounted::operator new;
CodeFeatures features() { return m_features; }
bool usesEval() const { return m_features & EvalFeature; }
- bool usesArguments() const { return m_features & ArgumentsFeature; }
+ bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); }
+ bool isStrictMode() const { return m_features & StrictModeFeature; }
void setUsesArguments() { m_features |= ArgumentsFeature; }
bool usesThis() const { return m_features & ThisFeature; }
- bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
+ bool needsActivationForMoreThanVariables() const { ASSERT(m_data); return m_features & (EvalFeature | WithFeature | CatchFeature); }
+ bool needsActivation() const { ASSERT(m_data); return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); }
+ bool hasCapturedVariables() const { return !!m_data->m_capturedVariables.size(); }
+ size_t capturedVariableCount() const { return m_data->m_capturedVariables.size(); }
+ bool captures(const Identifier& ident) { return m_data->m_capturedVariables.contains(ident.impl()); }
VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; }
FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; }
class ProgramNode : public ScopeNode {
public:
- static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+ static const bool isFunctionNode = false;
+ static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
static const bool scopeIsFunction = false;
private:
- ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+ ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
class EvalNode : public ScopeNode {
public:
- static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+ static const bool isFunctionNode = false;
+ static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
static const bool scopeIsFunction = false;
private:
- EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+ EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
class FunctionParameters : public Vector<Identifier>, public RefCounted<FunctionParameters> {
+ WTF_MAKE_FAST_ALLOCATED;
public:
static PassRefPtr<FunctionParameters> create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); }
class FunctionBodyNode : public ScopeNode {
public:
- static FunctionBodyNode* create(JSGlobalData*);
- static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+ static const bool isFunctionNode = true;
+ static FunctionBodyNode* create(JSGlobalData*, bool isStrictMode);
+ static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
FunctionParameters* parameters() const { return m_parameters.get(); }
size_t parameterCount() const { return m_parameters->size(); }
static const bool scopeIsFunction = true;
private:
- FunctionBodyNode(JSGlobalData*);
- FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+ FunctionBodyNode(JSGlobalData*, bool inStrictContext);
+ FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
Identifier m_ident;
RefPtr<FunctionParameters> m_parameters;