assignment_id_(GetNextId(isolate)),
block_start_(false),
block_end_(false),
- is_monomorphic_(false) {
- ASSERT(Token::IsAssignmentOp(op));
- if (is_compound()) {
- binary_operation_ =
- new(isolate->zone()) BinaryOperation(isolate,
- binary_op(),
- target,
- value,
- pos + 1);
- compound_load_id_ = GetNextId(isolate);
- }
-}
+ is_monomorphic_(false) { }
Token::Value Assignment::binary_op() const {
}
+bool FunctionLiteral::ShouldSelfOptimize() {
+ return !flags()->Contains(kDontSelfOptimize);
+}
+
+
ObjectLiteral::Property::Property(Literal* key, Expression* value) {
emit_store_ = true;
key_ = key;
ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
- Isolate* isolate = Isolate::Current();
emit_store_ = true;
- key_ = new(isolate->zone()) Literal(isolate, value->name());
value_ = value;
kind_ = is_getter ? GETTER : SETTER;
}
}
-bool TargetCollector::IsInlineable() const {
- UNREACHABLE();
- return false;
-}
-
-
-bool ForInStatement::IsInlineable() const {
- return false;
-}
-
-
-bool WithStatement::IsInlineable() const {
- return false;
-}
-
-
-bool SwitchStatement::IsInlineable() const {
- return false;
-}
-
-
-bool TryStatement::IsInlineable() const {
- return false;
-}
-
-
-bool TryCatchStatement::IsInlineable() const {
- return false;
-}
-
-
-bool TryFinallyStatement::IsInlineable() const {
- return false;
-}
-
-
-bool DebuggerStatement::IsInlineable() const {
- return false;
-}
-
-
-bool Throw::IsInlineable() const {
- return exception()->IsInlineable();
-}
-
-
-bool MaterializedLiteral::IsInlineable() const {
- // TODO(1322): Allow materialized literals.
- return false;
-}
-
-
-bool FunctionLiteral::IsInlineable() const {
- // TODO(1322): Allow materialized literals.
- return false;
-}
-
-
-bool ThisFunction::IsInlineable() const {
- return true;
-}
-
-
-bool SharedFunctionInfoLiteral::IsInlineable() const {
- return false;
-}
-
-
-bool ForStatement::IsInlineable() const {
- return (init() == NULL || init()->IsInlineable())
- && (cond() == NULL || cond()->IsInlineable())
- && (next() == NULL || next()->IsInlineable())
- && body()->IsInlineable();
-}
-
-
-bool WhileStatement::IsInlineable() const {
- return cond()->IsInlineable()
- && body()->IsInlineable();
-}
-
-
-bool DoWhileStatement::IsInlineable() const {
- return cond()->IsInlineable()
- && body()->IsInlineable();
-}
-
-
-bool ContinueStatement::IsInlineable() const {
- return true;
-}
-
-
-bool BreakStatement::IsInlineable() const {
- return true;
-}
-
-
-bool EmptyStatement::IsInlineable() const {
- return true;
-}
-
-
-bool Literal::IsInlineable() const {
- return true;
-}
-
-
-bool Block::IsInlineable() const {
- const int count = statements_.length();
- for (int i = 0; i < count; ++i) {
- if (!statements_[i]->IsInlineable()) return false;
- }
- return true;
-}
-
-
-bool ExpressionStatement::IsInlineable() const {
- return expression()->IsInlineable();
-}
-
-
-bool IfStatement::IsInlineable() const {
- return condition()->IsInlineable()
- && then_statement()->IsInlineable()
- && else_statement()->IsInlineable();
-}
-
-
-bool ReturnStatement::IsInlineable() const {
- return expression()->IsInlineable();
-}
-
-
-bool Conditional::IsInlineable() const {
- return condition()->IsInlineable() && then_expression()->IsInlineable() &&
- else_expression()->IsInlineable();
-}
-
-
-bool VariableProxy::IsInlineable() const {
- return var()->IsUnallocated()
- || var()->IsStackAllocated()
- || var()->IsContextSlot();
-}
-
-
-bool Assignment::IsInlineable() const {
- return target()->IsInlineable() && value()->IsInlineable();
-}
-
-
-bool Property::IsInlineable() const {
- return obj()->IsInlineable() && key()->IsInlineable();
-}
-
-
-bool Call::IsInlineable() const {
- if (!expression()->IsInlineable()) return false;
- const int count = arguments()->length();
- for (int i = 0; i < count; ++i) {
- if (!arguments()->at(i)->IsInlineable()) return false;
- }
- return true;
-}
-
-
-bool CallNew::IsInlineable() const {
- if (!expression()->IsInlineable()) return false;
- const int count = arguments()->length();
- for (int i = 0; i < count; ++i) {
- if (!arguments()->at(i)->IsInlineable()) return false;
- }
- return true;
-}
-
-
-bool CallRuntime::IsInlineable() const {
- // Don't try to inline JS runtime calls because we don't (currently) even
- // optimize them.
- if (is_jsruntime()) return false;
- // Don't inline the %_ArgumentsLength or %_Arguments because their
- // implementation will not work. There is no stack frame to get them
- // from.
- if (function()->intrinsic_type == Runtime::INLINE &&
- (name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
- name()->IsEqualTo(CStrVector("_Arguments")))) {
- return false;
- }
- const int count = arguments()->length();
- for (int i = 0; i < count; ++i) {
- if (!arguments()->at(i)->IsInlineable()) return false;
- }
- return true;
-}
-
-
-bool UnaryOperation::IsInlineable() const {
- return expression()->IsInlineable();
-}
-
-
-bool BinaryOperation::IsInlineable() const {
- return left()->IsInlineable() && right()->IsInlineable();
-}
-
-
-bool CompareOperation::IsInlineable() const {
- return left()->IsInlineable() && right()->IsInlineable();
-}
-
-
-bool CountOperation::IsInlineable() const {
- return expression()->IsInlineable();
-}
-
-
// ----------------------------------------------------------------------------
// Recording of type feedback
entry_id_(AstNode::GetNextId(isolate)) {
}
+
+#define INCREASE_NODE_COUNT(NodeType) \
+ void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
+ increase_node_count(); \
+ }
+
+INCREASE_NODE_COUNT(Declaration)
+INCREASE_NODE_COUNT(Block)
+INCREASE_NODE_COUNT(ExpressionStatement)
+INCREASE_NODE_COUNT(EmptyStatement)
+INCREASE_NODE_COUNT(IfStatement)
+INCREASE_NODE_COUNT(ContinueStatement)
+INCREASE_NODE_COUNT(BreakStatement)
+INCREASE_NODE_COUNT(ReturnStatement)
+INCREASE_NODE_COUNT(Conditional)
+INCREASE_NODE_COUNT(Literal)
+INCREASE_NODE_COUNT(Assignment)
+INCREASE_NODE_COUNT(Throw)
+INCREASE_NODE_COUNT(Property)
+INCREASE_NODE_COUNT(UnaryOperation)
+INCREASE_NODE_COUNT(CountOperation)
+INCREASE_NODE_COUNT(BinaryOperation)
+INCREASE_NODE_COUNT(CompareOperation)
+INCREASE_NODE_COUNT(ThisFunction)
+
+#undef INCREASE_NODE_COUNT
+
+
+void AstConstructionVisitor::VisitWithStatement(WithStatement* node) {
+ increase_node_count();
+ add_flag(kDontOptimize);
+ add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitSwitchStatement(SwitchStatement* node) {
+ increase_node_count();
+ add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
+ increase_node_count();
+ add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitWhileStatement(WhileStatement* node) {
+ increase_node_count();
+ add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitForStatement(ForStatement* node) {
+ increase_node_count();
+ add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitForInStatement(ForInStatement* node) {
+ increase_node_count();
+ add_flag(kDontOptimize);
+ add_flag(kDontInline);
+ add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
+ increase_node_count();
+ add_flag(kDontOptimize);
+ add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitTryFinallyStatement(
+ TryFinallyStatement* node) {
+ increase_node_count();
+ add_flag(kDontOptimize);
+ add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
+ increase_node_count();
+ add_flag(kDontOptimize);
+ add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
+ increase_node_count();
+ add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitSharedFunctionInfoLiteral(
+ SharedFunctionInfoLiteral* node) {
+ increase_node_count();
+ add_flag(kDontOptimize);
+ add_flag(kDontInline);
+}
+
+
+void AstConstructionVisitor::VisitVariableProxy(VariableProxy* node) {
+ increase_node_count();
+ // In theory, we'd have to add:
+ // if(node->var()->IsLookupSlot()) { add_flag(kDontInline); }
+ // However, node->var() is usually not bound yet at VariableProxy creation
+ // time, and LOOKUP variables only result from constructs that cannot
+ // be inlined anyway.
+}
+
+
+void AstConstructionVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
+ increase_node_count();
+ add_flag(kDontInline); // TODO(1322): Allow materialized literals.
+}
+
+
+void AstConstructionVisitor::VisitObjectLiteral(ObjectLiteral* node) {
+ increase_node_count();
+ add_flag(kDontInline); // TODO(1322): Allow materialized literals.
+}
+
+
+void AstConstructionVisitor::VisitArrayLiteral(ArrayLiteral* node) {
+ increase_node_count();
+ add_flag(kDontInline); // TODO(1322): Allow materialized literals.
+}
+
+
+void AstConstructionVisitor::VisitCall(Call* node) {
+ increase_node_count();
+ add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitCallNew(CallNew* node) {
+ increase_node_count();
+ add_flag(kDontSelfOptimize);
+}
+
+
+void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
+ increase_node_count();
+ add_flag(kDontSelfOptimize);
+ if (node->is_jsruntime()) {
+ // Don't try to inline JS runtime calls because we don't (currently) even
+ // optimize them.
+ add_flag(kDontInline);
+ } else if (node->function()->intrinsic_type == Runtime::INLINE &&
+ (node->name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
+ node->name()->IsEqualTo(CStrVector("_Arguments")))) {
+ // Don't inline the %_ArgumentsLength or %_Arguments because their
+ // implementation will not work. There is no stack frame to get them
+ // from.
+ add_flag(kDontInline);
+ }
+}
+
} } // namespace v8::internal
#include "small-pointer-list.h"
#include "smart-array-pointer.h"
#include "token.h"
+#include "utils.h"
#include "variables.h"
#include "zone-inl.h"
EXPRESSION_NODE_LIST(V)
// Forward declarations
+class AstConstructionVisitor;
+template<class> class AstNodeFactory;
class AstVisitor;
class BreakableStatement;
class Expression;
typedef ZoneList<Handle<Object> > ZoneObjectList;
+#define DECLARE_NODE_TYPE(type) \
+ virtual void Accept(AstVisitor* v); \
+ virtual AstNode::Type node_type() const { return AstNode::k##type; } \
+
+
+enum AstPropertiesFlag {
+ kDontInline,
+ kDontOptimize,
+ kDontSelfOptimize,
+ kDontSoftInline
+};
+
+
+class AstProperties BASE_EMBEDDED {
+ public:
+ class Flags : public EnumSet<AstPropertiesFlag, int> {};
+
+ AstProperties() : node_count_(0) { }
+
+ Flags* flags() { return &flags_; }
+ int node_count() { return node_count_; }
+ void add_node_count(int count) { node_count_ += count; }
+
+ private:
+ Flags flags_;
+ int node_count_;
+};
+
+
class AstNode: public ZoneObject {
public:
#define DECLARE_TYPE_ENUM(type) k##type,
// that emit code (function declarations).
static const int kDeclarationsId = 3;
- // Override ZoneObject's new to count allocated AST nodes.
void* operator new(size_t size, Zone* zone) {
- Isolate* isolate = zone->isolate();
- isolate->set_ast_node_count(isolate->ast_node_count() + 1);
return zone->New(static_cast<int>(size));
}
- AstNode() {}
+ AstNode() { }
virtual ~AstNode() { }
virtual IterationStatement* AsIterationStatement() { return NULL; }
virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; }
- // True if the node is simple enough for us to inline calls containing it.
- virtual bool IsInlineable() const = 0;
-
- static int Count() { return Isolate::Current()->ast_node_count(); }
static void ResetIds() { Isolate::Current()->set_ast_node_id(0); }
protected:
- static unsigned GetNextId(Isolate* isolate) {
+ static int GetNextId(Isolate* isolate) {
return ReserveIdRange(isolate, 1);
}
- static unsigned ReserveIdRange(Isolate* isolate, int n) {
- unsigned tmp = isolate->ast_node_id();
+ static int ReserveIdRange(Isolate* isolate, int n) {
+ int tmp = isolate->ast_node_id();
isolate->set_ast_node_id(tmp + n);
return tmp;
}
unsigned test_id() const { return test_id_; }
private:
- unsigned id_;
- unsigned test_id_;
+ int id_;
+ int test_id_;
};
class Block: public BreakableStatement {
public:
- Block(Isolate* isolate,
- ZoneStringList* labels,
- int capacity,
- bool is_initializer_block)
- : BreakableStatement(isolate, labels, TARGET_FOR_NAMED_ONLY),
- statements_(capacity),
- is_initializer_block_(is_initializer_block),
- block_scope_(NULL) {
- }
-
-
DECLARE_NODE_TYPE(Block)
- virtual bool IsInlineable() const;
-
void AddStatement(Statement* statement) { statements_.Add(statement); }
ZoneList<Statement*>* statements() { return &statements_; }
Scope* block_scope() const { return block_scope_; }
void set_block_scope(Scope* block_scope) { block_scope_ = block_scope; }
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ Block(Isolate* isolate,
+ ZoneStringList* labels,
+ int capacity,
+ bool is_initializer_block)
+ : BreakableStatement(isolate, labels, TARGET_FOR_NAMED_ONLY),
+ statements_(capacity),
+ is_initializer_block_(is_initializer_block),
+ block_scope_(NULL) {
+ }
+
private:
ZoneList<Statement*> statements_;
bool is_initializer_block_;
class Declaration: public AstNode {
public:
+ DECLARE_NODE_TYPE(Declaration)
+
+ VariableProxy* proxy() const { return proxy_; }
+ VariableMode mode() const { return mode_; }
+ FunctionLiteral* fun() const { return fun_; } // may be NULL
+ bool IsInlineable() const;
+ Scope* scope() const { return scope_; }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
Declaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* fun,
ASSERT(fun == NULL || mode == VAR || mode == LET);
}
- DECLARE_NODE_TYPE(Declaration)
-
- VariableProxy* proxy() const { return proxy_; }
- VariableMode mode() const { return mode_; }
- FunctionLiteral* fun() const { return fun_; } // may be NULL
- virtual bool IsInlineable() const;
- Scope* scope() const { return scope_; }
-
private:
VariableProxy* proxy_;
VariableMode mode_;
class DoWhileStatement: public IterationStatement {
public:
- DoWhileStatement(Isolate* isolate, ZoneStringList* labels)
- : IterationStatement(isolate, labels),
- cond_(NULL),
- condition_position_(-1),
- continue_id_(GetNextId(isolate)),
- back_edge_id_(GetNextId(isolate)) {
- }
-
DECLARE_NODE_TYPE(DoWhileStatement)
void Initialize(Expression* cond, Statement* body) {
virtual int StackCheckId() const { return back_edge_id_; }
int BackEdgeId() const { return back_edge_id_; }
- virtual bool IsInlineable() const;
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ DoWhileStatement(Isolate* isolate, ZoneStringList* labels)
+ : IterationStatement(isolate, labels),
+ cond_(NULL),
+ condition_position_(-1),
+ continue_id_(GetNextId(isolate)),
+ back_edge_id_(GetNextId(isolate)) {
+ }
private:
Expression* cond_;
class WhileStatement: public IterationStatement {
public:
- WhileStatement(Isolate* isolate, ZoneStringList* labels)
- : IterationStatement(isolate, labels),
- cond_(NULL),
- may_have_function_literal_(true),
- body_id_(GetNextId(isolate)) {
- }
-
DECLARE_NODE_TYPE(WhileStatement)
void Initialize(Expression* cond, Statement* body) {
void set_may_have_function_literal(bool value) {
may_have_function_literal_ = value;
}
- virtual bool IsInlineable() const;
// Bailout support.
virtual int ContinueId() const { return EntryId(); }
virtual int StackCheckId() const { return body_id_; }
int BodyId() const { return body_id_; }
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ WhileStatement(Isolate* isolate, ZoneStringList* labels)
+ : IterationStatement(isolate, labels),
+ cond_(NULL),
+ may_have_function_literal_(true),
+ body_id_(GetNextId(isolate)) {
+ }
+
private:
Expression* cond_;
// True if there is a function literal subexpression in the condition.
class ForStatement: public IterationStatement {
public:
- ForStatement(Isolate* isolate, ZoneStringList* labels)
- : IterationStatement(isolate, labels),
- init_(NULL),
- cond_(NULL),
- next_(NULL),
- may_have_function_literal_(true),
- loop_variable_(NULL),
- continue_id_(GetNextId(isolate)),
- body_id_(GetNextId(isolate)) {
- }
-
DECLARE_NODE_TYPE(ForStatement)
void Initialize(Statement* init,
bool is_fast_smi_loop() { return loop_variable_ != NULL; }
Variable* loop_variable() { return loop_variable_; }
void set_loop_variable(Variable* var) { loop_variable_ = var; }
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ ForStatement(Isolate* isolate, ZoneStringList* labels)
+ : IterationStatement(isolate, labels),
+ init_(NULL),
+ cond_(NULL),
+ next_(NULL),
+ may_have_function_literal_(true),
+ loop_variable_(NULL),
+ continue_id_(GetNextId(isolate)),
+ body_id_(GetNextId(isolate)) {
+ }
private:
Statement* init_;
class ForInStatement: public IterationStatement {
public:
- ForInStatement(Isolate* isolate, ZoneStringList* labels)
- : IterationStatement(isolate, labels),
- each_(NULL),
- enumerable_(NULL),
- assignment_id_(GetNextId(isolate)) {
- }
-
DECLARE_NODE_TYPE(ForInStatement)
void Initialize(Expression* each, Expression* enumerable, Statement* body) {
Expression* each() const { return each_; }
Expression* enumerable() const { return enumerable_; }
- virtual bool IsInlineable() const;
// Bailout support.
int AssignmentId() const { return assignment_id_; }
virtual int ContinueId() const { return EntryId(); }
virtual int StackCheckId() const { return EntryId(); }
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ ForInStatement(Isolate* isolate, ZoneStringList* labels)
+ : IterationStatement(isolate, labels),
+ each_(NULL),
+ enumerable_(NULL),
+ assignment_id_(GetNextId(isolate)) {
+ }
+
private:
Expression* each_;
Expression* enumerable_;
class ExpressionStatement: public Statement {
public:
- explicit ExpressionStatement(Expression* expression)
- : expression_(expression) { }
-
DECLARE_NODE_TYPE(ExpressionStatement)
- virtual bool IsInlineable() const;
-
void set_expression(Expression* e) { expression_ = e; }
Expression* expression() const { return expression_; }
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ explicit ExpressionStatement(Expression* expression)
+ : expression_(expression) { }
+
private:
Expression* expression_;
};
class ContinueStatement: public Statement {
public:
- explicit ContinueStatement(IterationStatement* target)
- : target_(target) { }
-
DECLARE_NODE_TYPE(ContinueStatement)
IterationStatement* target() const { return target_; }
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ explicit ContinueStatement(IterationStatement* target)
+ : target_(target) { }
private:
IterationStatement* target_;
class BreakStatement: public Statement {
public:
- explicit BreakStatement(BreakableStatement* target)
- : target_(target) { }
-
DECLARE_NODE_TYPE(BreakStatement)
BreakableStatement* target() const { return target_; }
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ explicit BreakStatement(BreakableStatement* target)
+ : target_(target) { }
private:
BreakableStatement* target_;
class ReturnStatement: public Statement {
public:
- explicit ReturnStatement(Expression* expression)
- : expression_(expression) { }
-
DECLARE_NODE_TYPE(ReturnStatement)
Expression* expression() const { return expression_; }
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ explicit ReturnStatement(Expression* expression)
+ : expression_(expression) { }
private:
Expression* expression_;
class WithStatement: public Statement {
public:
- WithStatement(Expression* expression, Statement* statement)
- : expression_(expression), statement_(statement) { }
-
DECLARE_NODE_TYPE(WithStatement)
Expression* expression() const { return expression_; }
Statement* statement() const { return statement_; }
- virtual bool IsInlineable() const;
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ WithStatement(Expression* expression, Statement* statement)
+ : expression_(expression),
+ statement_(statement) { }
private:
Expression* expression_;
class SwitchStatement: public BreakableStatement {
public:
- SwitchStatement(Isolate* isolate, ZoneStringList* labels)
- : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
- tag_(NULL),
- cases_(NULL) {
- }
-
-
DECLARE_NODE_TYPE(SwitchStatement)
void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
Expression* tag() const { return tag_; }
ZoneList<CaseClause*>* cases() const { return cases_; }
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ SwitchStatement(Isolate* isolate, ZoneStringList* labels)
+ : BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
+ tag_(NULL),
+ cases_(NULL) { }
private:
Expression* tag_;
// given if-statement has a then- or an else-part containing code.
class IfStatement: public Statement {
public:
- IfStatement(Isolate* isolate,
- Expression* condition,
- Statement* then_statement,
- Statement* else_statement)
- : condition_(condition),
- then_statement_(then_statement),
- else_statement_(else_statement),
- if_id_(GetNextId(isolate)),
- then_id_(GetNextId(isolate)),
- else_id_(GetNextId(isolate)) {
- }
-
DECLARE_NODE_TYPE(IfStatement)
- virtual bool IsInlineable() const;
-
bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
bool HasElseStatement() const { return !else_statement()->IsEmpty(); }
int ThenId() const { return then_id_; }
int ElseId() const { return else_id_; }
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ IfStatement(Isolate* isolate,
+ Expression* condition,
+ Statement* then_statement,
+ Statement* else_statement)
+ : condition_(condition),
+ then_statement_(then_statement),
+ else_statement_(else_statement),
+ if_id_(GetNextId(isolate)),
+ then_id_(GetNextId(isolate)),
+ else_id_(GetNextId(isolate)) {
+ }
+
private:
Expression* condition_;
Statement* then_statement_;
// stack in the compiler; this should probably be reworked.
class TargetCollector: public AstNode {
public:
- TargetCollector(): targets_(0) { }
+ TargetCollector() : targets_(0) { }
// Adds a jump target to the collector. The collector stores a pointer not
// a copy of the target to make binding work, so make sure not to pass in
virtual TargetCollector* AsTargetCollector() { return this; }
ZoneList<Label*>* targets() { return &targets_; }
- virtual bool IsInlineable() const;
private:
ZoneList<Label*> targets_;
class TryStatement: public Statement {
public:
- explicit TryStatement(int index, Block* try_block)
- : index_(index),
- try_block_(try_block),
- escaping_targets_(NULL) {
- }
-
void set_escaping_targets(ZoneList<Label*>* targets) {
escaping_targets_ = targets;
}
int index() const { return index_; }
Block* try_block() const { return try_block_; }
ZoneList<Label*>* escaping_targets() const { return escaping_targets_; }
- virtual bool IsInlineable() const;
+
+ protected:
+ TryStatement(int index, Block* try_block)
+ : index_(index),
+ try_block_(try_block),
+ escaping_targets_(NULL) { }
private:
// Unique (per-function) index of this handler. This is not an AST ID.
class TryCatchStatement: public TryStatement {
public:
+ DECLARE_NODE_TYPE(TryCatchStatement)
+
+ Scope* scope() { return scope_; }
+ Variable* variable() { return variable_; }
+ Block* catch_block() const { return catch_block_; }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
TryCatchStatement(int index,
Block* try_block,
Scope* scope,
catch_block_(catch_block) {
}
- DECLARE_NODE_TYPE(TryCatchStatement)
-
- Scope* scope() { return scope_; }
- Variable* variable() { return variable_; }
- Block* catch_block() const { return catch_block_; }
- virtual bool IsInlineable() const;
-
private:
Scope* scope_;
Variable* variable_;
class TryFinallyStatement: public TryStatement {
public:
- TryFinallyStatement(int index, Block* try_block, Block* finally_block)
- : TryStatement(index, try_block),
- finally_block_(finally_block) { }
-
DECLARE_NODE_TYPE(TryFinallyStatement)
Block* finally_block() const { return finally_block_; }
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ TryFinallyStatement(int index, Block* try_block, Block* finally_block)
+ : TryStatement(index, try_block),
+ finally_block_(finally_block) { }
private:
Block* finally_block_;
class DebuggerStatement: public Statement {
public:
DECLARE_NODE_TYPE(DebuggerStatement)
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ DebuggerStatement() {}
};
public:
DECLARE_NODE_TYPE(EmptyStatement)
- virtual bool IsInlineable() const;
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ EmptyStatement() {}
};
class Literal: public Expression {
public:
- Literal(Isolate* isolate, Handle<Object> handle)
- : Expression(isolate), handle_(handle) { }
-
DECLARE_NODE_TYPE(Literal)
// Check if this literal is identical to the other literal.
}
Handle<Object> handle() const { return handle_; }
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ Literal(Isolate* isolate, Handle<Object> handle)
+ : Expression(isolate),
+ handle_(handle) { }
private:
Handle<Object> handle_;
// Base class for literals that needs space in the corresponding JSFunction.
class MaterializedLiteral: public Expression {
public:
- MaterializedLiteral(Isolate* isolate,
- int literal_index,
- bool is_simple,
- int depth)
- : Expression(isolate),
- literal_index_(literal_index),
- is_simple_(is_simple),
- depth_(depth) {}
-
virtual MaterializedLiteral* AsMaterializedLiteral() { return this; }
int literal_index() { return literal_index_; }
bool is_simple() const { return is_simple_; }
int depth() const { return depth_; }
- virtual bool IsInlineable() const;
+
+ protected:
+ MaterializedLiteral(Isolate* isolate,
+ int literal_index,
+ bool is_simple,
+ int depth)
+ : Expression(isolate),
+ literal_index_(literal_index),
+ is_simple_(is_simple),
+ depth_(depth) {}
private:
int literal_index_;
};
Property(Literal* key, Expression* value);
- Property(bool is_getter, FunctionLiteral* value);
Literal* key() { return key_; }
Expression* value() { return value_; }
void set_emit_store(bool emit_store);
bool emit_store();
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ Property(bool is_getter, FunctionLiteral* value);
+ void set_key(Literal* key) { key_ = key; }
+
private:
Literal* key_;
Expression* value_;
bool emit_store_;
};
- ObjectLiteral(Isolate* isolate,
- Handle<FixedArray> constant_properties,
- ZoneList<Property*>* properties,
- int literal_index,
- bool is_simple,
- bool fast_elements,
- int depth,
- bool has_function)
- : MaterializedLiteral(isolate, literal_index, is_simple, depth),
- constant_properties_(constant_properties),
- properties_(properties),
- fast_elements_(fast_elements),
- has_function_(has_function) {}
-
DECLARE_NODE_TYPE(ObjectLiteral)
Handle<FixedArray> constant_properties() const {
kHasFunction = 1 << 1
};
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ ObjectLiteral(Isolate* isolate,
+ Handle<FixedArray> constant_properties,
+ ZoneList<Property*>* properties,
+ int literal_index,
+ bool is_simple,
+ bool fast_elements,
+ int depth,
+ bool has_function)
+ : MaterializedLiteral(isolate, literal_index, is_simple, depth),
+ constant_properties_(constant_properties),
+ properties_(properties),
+ fast_elements_(fast_elements),
+ has_function_(has_function) {}
+
private:
Handle<FixedArray> constant_properties_;
ZoneList<Property*>* properties_;
// Node for capturing a regexp literal.
class RegExpLiteral: public MaterializedLiteral {
public:
+ DECLARE_NODE_TYPE(RegExpLiteral)
+
+ Handle<String> pattern() const { return pattern_; }
+ Handle<String> flags() const { return flags_; }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
RegExpLiteral(Isolate* isolate,
Handle<String> pattern,
Handle<String> flags,
pattern_(pattern),
flags_(flags) {}
- DECLARE_NODE_TYPE(RegExpLiteral)
-
- Handle<String> pattern() const { return pattern_; }
- Handle<String> flags() const { return flags_; }
-
private:
Handle<String> pattern_;
Handle<String> flags_;
// for minimizing the work when constructing it at runtime.
class ArrayLiteral: public MaterializedLiteral {
public:
+ DECLARE_NODE_TYPE(ArrayLiteral)
+
+ Handle<FixedArray> constant_elements() const { return constant_elements_; }
+ ZoneList<Expression*>* values() const { return values_; }
+
+ // Return an AST id for an element that is used in simulate instructions.
+ int GetIdForElement(int i) { return first_element_id_ + i; }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
ArrayLiteral(Isolate* isolate,
Handle<FixedArray> constant_elements,
ZoneList<Expression*>* values,
values_(values),
first_element_id_(ReserveIdRange(isolate, values->length())) {}
- DECLARE_NODE_TYPE(ArrayLiteral)
-
- Handle<FixedArray> constant_elements() const { return constant_elements_; }
- ZoneList<Expression*>* values() const { return values_; }
-
- // Return an AST id for an element that is used in simulate instructions.
- int GetIdForElement(int i) { return first_element_id_ + i; }
-
private:
Handle<FixedArray> constant_elements_;
ZoneList<Expression*>* values_;
class VariableProxy: public Expression {
public:
- VariableProxy(Isolate* isolate, Variable* var);
-
- VariableProxy(Isolate* isolate,
- Handle<String> name,
- bool is_this,
- int position = RelocInfo::kNoPosition);
-
DECLARE_NODE_TYPE(VariableProxy)
virtual bool IsValidLeftHandSide() {
return var_ == NULL ? true : var_->IsValidLeftHandSide();
}
- virtual bool IsInlineable() const;
-
bool IsVariable(Handle<String> n) {
return !is_this() && name().is_identical_to(n);
}
void BindTo(Variable* var);
protected:
+ template<class> friend class AstNodeFactory;
+
+ VariableProxy(Isolate* isolate, Variable* var);
+
+ VariableProxy(Isolate* isolate,
+ Handle<String> name,
+ bool is_this,
+ int position);
+
Handle<String> name_;
Variable* var_; // resolved variable, or NULL
bool is_this_;
class Property: public Expression {
public:
- Property(Isolate* isolate,
- Expression* obj,
- Expression* key,
- int pos)
- : Expression(isolate),
- obj_(obj),
- key_(key),
- pos_(pos),
- is_monomorphic_(false),
- is_array_length_(false),
- is_string_length_(false),
- is_string_access_(false),
- is_function_prototype_(false) { }
-
DECLARE_NODE_TYPE(Property)
virtual bool IsValidLeftHandSide() { return true; }
- virtual bool IsInlineable() const;
Expression* obj() const { return obj_; }
Expression* key() const { return key_; }
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
bool IsArrayLength() { return is_array_length_; }
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ Property(Isolate* isolate,
+ Expression* obj,
+ Expression* key,
+ int pos)
+ : Expression(isolate),
+ obj_(obj),
+ key_(key),
+ pos_(pos),
+ is_monomorphic_(false),
+ is_array_length_(false),
+ is_string_length_(false),
+ is_string_access_(false),
+ is_function_prototype_(false) { }
+
private:
Expression* obj_;
Expression* key_;
class Call: public Expression {
public:
- Call(Isolate* isolate,
- Expression* expression,
- ZoneList<Expression*>* arguments,
- int pos)
- : Expression(isolate),
- expression_(expression),
- arguments_(arguments),
- pos_(pos),
- is_monomorphic_(false),
- check_type_(RECEIVER_MAP_CHECK),
- return_id_(GetNextId(isolate)) {
- }
-
DECLARE_NODE_TYPE(Call)
- virtual bool IsInlineable() const;
-
Expression* expression() const { return expression_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
virtual int position() const { return pos_; }
bool return_is_recorded_;
#endif
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ Call(Isolate* isolate,
+ Expression* expression,
+ ZoneList<Expression*>* arguments,
+ int pos)
+ : Expression(isolate),
+ expression_(expression),
+ arguments_(arguments),
+ pos_(pos),
+ is_monomorphic_(false),
+ check_type_(RECEIVER_MAP_CHECK),
+ return_id_(GetNextId(isolate)) { }
+
private:
Expression* expression_;
ZoneList<Expression*>* arguments_;
class CallNew: public Expression {
public:
+ DECLARE_NODE_TYPE(CallNew)
+
+ Expression* expression() const { return expression_; }
+ ZoneList<Expression*>* arguments() const { return arguments_; }
+ virtual int position() const { return pos_; }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
CallNew(Isolate* isolate,
Expression* expression,
ZoneList<Expression*>* arguments,
arguments_(arguments),
pos_(pos) { }
- DECLARE_NODE_TYPE(CallNew)
-
- virtual bool IsInlineable() const;
-
- Expression* expression() const { return expression_; }
- ZoneList<Expression*>* arguments() const { return arguments_; }
- virtual int position() const { return pos_; }
-
private:
Expression* expression_;
ZoneList<Expression*>* arguments_;
// implemented in JavaScript (see "v8natives.js").
class CallRuntime: public Expression {
public:
+ DECLARE_NODE_TYPE(CallRuntime)
+
+ Handle<String> name() const { return name_; }
+ const Runtime::Function* function() const { return function_; }
+ ZoneList<Expression*>* arguments() const { return arguments_; }
+ bool is_jsruntime() const { return function_ == NULL; }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
CallRuntime(Isolate* isolate,
Handle<String> name,
const Runtime::Function* function,
function_(function),
arguments_(arguments) { }
- DECLARE_NODE_TYPE(CallRuntime)
-
- virtual bool IsInlineable() const;
-
- Handle<String> name() const { return name_; }
- const Runtime::Function* function() const { return function_; }
- ZoneList<Expression*>* arguments() const { return arguments_; }
- bool is_jsruntime() const { return function_ == NULL; }
-
private:
Handle<String> name_;
const Runtime::Function* function_;
class UnaryOperation: public Expression {
public:
+ DECLARE_NODE_TYPE(UnaryOperation)
+
+ virtual bool ResultOverwriteAllowed();
+
+ Token::Value op() const { return op_; }
+ Expression* expression() const { return expression_; }
+ virtual int position() const { return pos_; }
+
+ int MaterializeTrueId() { return materialize_true_id_; }
+ int MaterializeFalseId() { return materialize_false_id_; }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
UnaryOperation(Isolate* isolate,
Token::Value op,
Expression* expression,
}
}
- DECLARE_NODE_TYPE(UnaryOperation)
-
- virtual bool IsInlineable() const;
-
- virtual bool ResultOverwriteAllowed();
-
- Token::Value op() const { return op_; }
- Expression* expression() const { return expression_; }
- virtual int position() const { return pos_; }
-
- int MaterializeTrueId() { return materialize_true_id_; }
- int MaterializeFalseId() { return materialize_false_id_; }
-
private:
Token::Value op_;
Expression* expression_;
class BinaryOperation: public Expression {
public:
- BinaryOperation(Isolate* isolate,
- Token::Value op,
- Expression* left,
- Expression* right,
- int pos)
- : Expression(isolate), op_(op), left_(left), right_(right), pos_(pos) {
- ASSERT(Token::IsBinaryOp(op));
- right_id_ = (op == Token::AND || op == Token::OR)
- ? static_cast<int>(GetNextId(isolate))
- : AstNode::kNoNumber;
- }
-
DECLARE_NODE_TYPE(BinaryOperation)
- virtual bool IsInlineable() const;
-
virtual bool ResultOverwriteAllowed();
Token::Value op() const { return op_; }
// Bailout support.
int RightId() const { return right_id_; }
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ BinaryOperation(Isolate* isolate,
+ Token::Value op,
+ Expression* left,
+ Expression* right,
+ int pos)
+ : Expression(isolate), op_(op), left_(left), right_(right), pos_(pos) {
+ ASSERT(Token::IsBinaryOp(op));
+ right_id_ = (op == Token::AND || op == Token::OR)
+ ? GetNextId(isolate)
+ : AstNode::kNoNumber;
+ }
+
private:
Token::Value op_;
Expression* left_;
class CountOperation: public Expression {
public:
- CountOperation(Isolate* isolate,
- Token::Value op,
- bool is_prefix,
- Expression* expr,
- int pos)
- : Expression(isolate),
- op_(op),
- is_prefix_(is_prefix),
- expression_(expr),
- pos_(pos),
- assignment_id_(GetNextId(isolate)),
- count_id_(GetNextId(isolate)) {}
-
DECLARE_NODE_TYPE(CountOperation)
bool is_prefix() const { return is_prefix_; }
virtual void MarkAsStatement() { is_prefix_ = true; }
- virtual bool IsInlineable() const;
-
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
virtual bool IsMonomorphic() { return is_monomorphic_; }
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
int AssignmentId() const { return assignment_id_; }
int CountId() const { return count_id_; }
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ CountOperation(Isolate* isolate,
+ Token::Value op,
+ bool is_prefix,
+ Expression* expr,
+ int pos)
+ : Expression(isolate),
+ op_(op),
+ is_prefix_(is_prefix),
+ expression_(expr),
+ pos_(pos),
+ assignment_id_(GetNextId(isolate)),
+ count_id_(GetNextId(isolate)) {}
+
private:
Token::Value op_;
bool is_prefix_;
class CompareOperation: public Expression {
- public:
- CompareOperation(Isolate* isolate,
- Token::Value op,
- Expression* left,
- Expression* right,
- int pos)
- : Expression(isolate),
- op_(op),
- left_(left),
- right_(right),
- pos_(pos),
- compare_type_(NONE) {
- ASSERT(Token::IsCompareOp(op));
- }
-
+ public:
DECLARE_NODE_TYPE(CompareOperation)
Token::Value op() const { return op_; }
Expression* right() const { return right_; }
virtual int position() const { return pos_; }
- virtual bool IsInlineable() const;
-
// Type feedback information.
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
bool IsLiteralCompareUndefined(Expression** expr);
bool IsLiteralCompareNull(Expression** expr);
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ CompareOperation(Isolate* isolate,
+ Token::Value op,
+ Expression* left,
+ Expression* right,
+ int pos)
+ : Expression(isolate),
+ op_(op),
+ left_(left),
+ right_(right),
+ pos_(pos),
+ compare_type_(NONE) {
+ ASSERT(Token::IsCompareOp(op));
+ }
+
private:
Token::Value op_;
Expression* left_;
class Conditional: public Expression {
public:
+ DECLARE_NODE_TYPE(Conditional)
+
+ Expression* condition() const { return condition_; }
+ Expression* then_expression() const { return then_expression_; }
+ Expression* else_expression() const { return else_expression_; }
+
+ int then_expression_position() const { return then_expression_position_; }
+ int else_expression_position() const { return else_expression_position_; }
+
+ int ThenId() const { return then_id_; }
+ int ElseId() const { return else_id_; }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
Conditional(Isolate* isolate,
Expression* condition,
Expression* then_expression,
then_expression_position_(then_expression_position),
else_expression_position_(else_expression_position),
then_id_(GetNextId(isolate)),
- else_id_(GetNextId(isolate)) {
- }
-
- DECLARE_NODE_TYPE(Conditional)
-
- virtual bool IsInlineable() const;
-
- Expression* condition() const { return condition_; }
- Expression* then_expression() const { return then_expression_; }
- Expression* else_expression() const { return else_expression_; }
-
- int then_expression_position() const { return then_expression_position_; }
- int else_expression_position() const { return else_expression_position_; }
-
- int ThenId() const { return then_id_; }
- int ElseId() const { return else_id_; }
+ else_id_(GetNextId(isolate)) { }
private:
Expression* condition_;
class Assignment: public Expression {
public:
- Assignment(Isolate* isolate,
- Token::Value op,
- Expression* target,
- Expression* value,
- int pos);
-
DECLARE_NODE_TYPE(Assignment)
- virtual bool IsInlineable() const;
-
Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }
Token::Value binary_op() const;
int CompoundLoadId() const { return compound_load_id_; }
int AssignmentId() const { return assignment_id_; }
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ Assignment(Isolate* isolate,
+ Token::Value op,
+ Expression* target,
+ Expression* value,
+ int pos);
+
+ template<class Visitor>
+ void Init(Isolate* isolate, AstNodeFactory<Visitor>* factory) {
+ ASSERT(Token::IsAssignmentOp(op_));
+ if (is_compound()) {
+ binary_operation_ =
+ factory->NewBinaryOperation(binary_op(), target_, value_, pos_ + 1);
+ compound_load_id_ = GetNextId(isolate);
+ }
+ }
+
private:
Token::Value op_;
Expression* target_;
class Throw: public Expression {
public:
- Throw(Isolate* isolate, Expression* exception, int pos)
- : Expression(isolate), exception_(exception), pos_(pos) {}
-
DECLARE_NODE_TYPE(Throw)
Expression* exception() const { return exception_; }
virtual int position() const { return pos_; }
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ Throw(Isolate* isolate, Expression* exception, int pos)
+ : Expression(isolate), exception_(exception), pos_(pos) {}
private:
Expression* exception_;
DECLARATION
};
- FunctionLiteral(Isolate* isolate,
- Handle<String> name,
- Scope* scope,
- ZoneList<Statement*>* body,
- int materialized_literal_count,
- int expected_property_count,
- int handler_count,
- bool has_only_simple_this_property_assignments,
- Handle<FixedArray> this_property_assignments,
- int parameter_count,
- Type type,
- bool has_duplicate_parameters)
- : Expression(isolate),
- name_(name),
- scope_(scope),
- body_(body),
- this_property_assignments_(this_property_assignments),
- inferred_name_(isolate->factory()->empty_string()),
- materialized_literal_count_(materialized_literal_count),
- expected_property_count_(expected_property_count),
- handler_count_(handler_count),
- parameter_count_(parameter_count),
- function_token_position_(RelocInfo::kNoPosition) {
- bitfield_ =
- HasOnlySimpleThisPropertyAssignments::encode(
- has_only_simple_this_property_assignments) |
- IsExpression::encode(type != DECLARATION) |
- IsAnonymous::encode(type == ANONYMOUS_EXPRESSION) |
- Pretenure::encode(false) |
- HasDuplicateParameters::encode(has_duplicate_parameters);
- }
-
DECLARE_NODE_TYPE(FunctionLiteral)
Handle<String> name() const { return name_; }
bool pretenure() { return Pretenure::decode(bitfield_); }
void set_pretenure() { bitfield_ |= Pretenure::encode(true); }
- virtual bool IsInlineable() const;
bool has_duplicate_parameters() {
return HasDuplicateParameters::decode(bitfield_);
}
+ bool ShouldSelfOptimize();
+
+ int ast_node_count() { return ast_properties_.node_count(); }
+ AstProperties::Flags* flags() { return ast_properties_.flags(); }
+ void set_ast_properties(AstProperties* ast_properties) {
+ ast_properties_ = *ast_properties;
+ }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ FunctionLiteral(Isolate* isolate,
+ Handle<String> name,
+ Scope* scope,
+ ZoneList<Statement*>* body,
+ int materialized_literal_count,
+ int expected_property_count,
+ int handler_count,
+ bool has_only_simple_this_property_assignments,
+ Handle<FixedArray> this_property_assignments,
+ int parameter_count,
+ Type type,
+ bool has_duplicate_parameters)
+ : Expression(isolate),
+ name_(name),
+ scope_(scope),
+ body_(body),
+ this_property_assignments_(this_property_assignments),
+ inferred_name_(isolate->factory()->empty_string()),
+ materialized_literal_count_(materialized_literal_count),
+ expected_property_count_(expected_property_count),
+ handler_count_(handler_count),
+ parameter_count_(parameter_count),
+ function_token_position_(RelocInfo::kNoPosition) {
+ bitfield_ =
+ HasOnlySimpleThisPropertyAssignments::encode(
+ has_only_simple_this_property_assignments) |
+ IsExpression::encode(type != DECLARATION) |
+ IsAnonymous::encode(type == ANONYMOUS_EXPRESSION) |
+ Pretenure::encode(false) |
+ HasDuplicateParameters::encode(has_duplicate_parameters);
+ }
+
private:
Handle<String> name_;
Scope* scope_;
ZoneList<Statement*>* body_;
Handle<FixedArray> this_property_assignments_;
Handle<String> inferred_name_;
+ AstProperties ast_properties_;
int materialized_literal_count_;
int expected_property_count_;
class SharedFunctionInfoLiteral: public Expression {
public:
- SharedFunctionInfoLiteral(
- Isolate* isolate,
- Handle<SharedFunctionInfo> shared_function_info)
- : Expression(isolate), shared_function_info_(shared_function_info) { }
-
DECLARE_NODE_TYPE(SharedFunctionInfoLiteral)
Handle<SharedFunctionInfo> shared_function_info() const {
return shared_function_info_;
}
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ SharedFunctionInfoLiteral(
+ Isolate* isolate,
+ Handle<SharedFunctionInfo> shared_function_info)
+ : Expression(isolate),
+ shared_function_info_(shared_function_info) { }
private:
Handle<SharedFunctionInfo> shared_function_info_;
class ThisFunction: public Expression {
public:
- explicit ThisFunction(Isolate* isolate) : Expression(isolate) {}
DECLARE_NODE_TYPE(ThisFunction)
- virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ explicit ThisFunction(Isolate* isolate): Expression(isolate) {}
};
};
+// ----------------------------------------------------------------------------
+// Construction time visitor.
+
+class AstConstructionVisitor BASE_EMBEDDED {
+ public:
+ AstConstructionVisitor() { }
+
+ AstProperties* ast_properties() { return &properties_; }
+
+ private:
+ template<class> friend class AstNodeFactory;
+
+ // Node visitors.
+#define DEF_VISIT(type) \
+ void Visit##type(type* node);
+ AST_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+ void increase_node_count() { properties_.add_node_count(1); }
+ void add_flag(AstPropertiesFlag flag) { properties_.flags()->Add(flag); }
+
+ AstProperties properties_;
+};
+
+
+class AstNullVisitor BASE_EMBEDDED {
+ public:
+ // Node visitors.
+#define DEF_VISIT(type) \
+ void Visit##type(type* node) {}
+ AST_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+};
+
+
+
+// ----------------------------------------------------------------------------
+// AstNode factory
+
+template<class Visitor>
+class AstNodeFactory BASE_EMBEDDED {
+ public:
+ explicit AstNodeFactory(Isolate* isolate)
+ : isolate_(isolate),
+ zone_(isolate_->zone()) { }
+
+ Visitor* visitor() { return &visitor_; }
+
+#define VISIT_AND_RETURN(NodeType, node) \
+ visitor_.Visit##NodeType((node)); \
+ return node;
+
+ Block* NewBlock(ZoneStringList* labels,
+ int capacity,
+ bool is_initializer_block) {
+ Block* block = new(zone_) Block(
+ isolate_, labels, capacity, is_initializer_block);
+ VISIT_AND_RETURN(Block, block)
+ }
+
+ Declaration* NewDeclaration(VariableProxy* proxy,
+ VariableMode mode,
+ FunctionLiteral* fun,
+ Scope* scope) {
+ Declaration* decl = new(zone_) Declaration(proxy, mode, fun, scope);
+ VISIT_AND_RETURN(Declaration, decl)
+ }
+
+#define STATEMENT_WITH_LABELS(NodeType) \
+ NodeType* New##NodeType(ZoneStringList* labels) { \
+ NodeType* stmt = new(zone_) NodeType(isolate_, labels); \
+ VISIT_AND_RETURN(NodeType, stmt); \
+ }
+ STATEMENT_WITH_LABELS(DoWhileStatement)
+ STATEMENT_WITH_LABELS(WhileStatement)
+ STATEMENT_WITH_LABELS(ForStatement)
+ STATEMENT_WITH_LABELS(ForInStatement)
+ STATEMENT_WITH_LABELS(SwitchStatement)
+#undef STATEMENT_WITH_LABELS
+
+ ExpressionStatement* NewExpressionStatement(Expression* expression) {
+ ExpressionStatement* stmt = new(zone_) ExpressionStatement(expression);
+ VISIT_AND_RETURN(ExpressionStatement, stmt)
+ }
+
+ ContinueStatement* NewContinueStatement(IterationStatement* target) {
+ ContinueStatement* stmt = new(zone_) ContinueStatement(target);
+ VISIT_AND_RETURN(ContinueStatement, stmt)
+ }
+
+ BreakStatement* NewBreakStatement(BreakableStatement* target) {
+ BreakStatement* stmt = new(zone_) BreakStatement(target);
+ VISIT_AND_RETURN(BreakStatement, stmt)
+ }
+
+ ReturnStatement* NewReturnStatement(Expression* expression) {
+ ReturnStatement* stmt = new(zone_) ReturnStatement(expression);
+ VISIT_AND_RETURN(ReturnStatement, stmt)
+ }
+
+ WithStatement* NewWithStatement(Expression* expression,
+ Statement* statement) {
+ WithStatement* stmt = new(zone_) WithStatement(expression, statement);
+ VISIT_AND_RETURN(WithStatement, stmt)
+ }
+
+ IfStatement* NewIfStatement(Expression* condition,
+ Statement* then_statement,
+ Statement* else_statement) {
+ IfStatement* stmt = new(zone_) IfStatement(
+ isolate_, condition, then_statement, else_statement);
+ VISIT_AND_RETURN(IfStatement, stmt)
+ }
+
+ TryCatchStatement* NewTryCatchStatement(int index,
+ Block* try_block,
+ Scope* scope,
+ Variable* variable,
+ Block* catch_block) {
+ TryCatchStatement* stmt = new(zone_) TryCatchStatement(
+ index, try_block, scope, variable, catch_block);
+ VISIT_AND_RETURN(TryCatchStatement, stmt)
+ }
+
+ TryFinallyStatement* NewTryFinallyStatement(int index,
+ Block* try_block,
+ Block* finally_block) {
+ TryFinallyStatement* stmt =
+ new(zone_) TryFinallyStatement(index, try_block, finally_block);
+ VISIT_AND_RETURN(TryFinallyStatement, stmt)
+ }
+
+ DebuggerStatement* NewDebuggerStatement() {
+ DebuggerStatement* stmt = new(zone_) DebuggerStatement();
+ VISIT_AND_RETURN(DebuggerStatement, stmt)
+ }
+
+ EmptyStatement* NewEmptyStatement() {
+ return new(zone_) EmptyStatement();
+ }
+
+ Literal* NewLiteral(Handle<Object> handle) {
+ Literal* lit = new(zone_) Literal(isolate_, handle);
+ VISIT_AND_RETURN(Literal, lit)
+ }
+
+ Literal* NewNumberLiteral(double number) {
+ return NewLiteral(isolate_->factory()->NewNumber(number, TENURED));
+ }
+
+ ObjectLiteral* NewObjectLiteral(
+ Handle<FixedArray> constant_properties,
+ ZoneList<ObjectLiteral::Property*>* properties,
+ int literal_index,
+ bool is_simple,
+ bool fast_elements,
+ int depth,
+ bool has_function) {
+ ObjectLiteral* lit = new(zone_) ObjectLiteral(
+ isolate_, constant_properties, properties, literal_index,
+ is_simple, fast_elements, depth, has_function);
+ VISIT_AND_RETURN(ObjectLiteral, lit)
+ }
+
+ ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter,
+ FunctionLiteral* value) {
+ ObjectLiteral::Property* prop =
+ new(zone_) ObjectLiteral::Property(is_getter, value);
+ prop->set_key(NewLiteral(value->name()));
+ return prop; // Not an AST node, will not be visited.
+ }
+
+ RegExpLiteral* NewRegExpLiteral(Handle<String> pattern,
+ Handle<String> flags,
+ int literal_index) {
+ RegExpLiteral* lit =
+ new(zone_) RegExpLiteral(isolate_, pattern, flags, literal_index);
+ VISIT_AND_RETURN(RegExpLiteral, lit);
+ }
+
+ ArrayLiteral* NewArrayLiteral(Handle<FixedArray> constant_elements,
+ ZoneList<Expression*>* values,
+ int literal_index,
+ bool is_simple,
+ int depth) {
+ ArrayLiteral* lit = new(zone_) ArrayLiteral(
+ isolate_, constant_elements, values, literal_index, is_simple, depth);
+ VISIT_AND_RETURN(ArrayLiteral, lit)
+ }
+
+ VariableProxy* NewVariableProxy(Variable* var) {
+ VariableProxy* proxy = new(zone_) VariableProxy(isolate_, var);
+ VISIT_AND_RETURN(VariableProxy, proxy)
+ }
+
+ VariableProxy* NewVariableProxy(Handle<String> name,
+ bool is_this,
+ int position = RelocInfo::kNoPosition) {
+ VariableProxy* proxy =
+ new(zone_) VariableProxy(isolate_, name, is_this, position);
+ VISIT_AND_RETURN(VariableProxy, proxy)
+ }
+
+ Property* NewProperty(Expression* obj, Expression* key, int pos) {
+ Property* prop = new(zone_) Property(isolate_, obj, key, pos);
+ VISIT_AND_RETURN(Property, prop)
+ }
+
+ Call* NewCall(Expression* expression,
+ ZoneList<Expression*>* arguments,
+ int pos) {
+ Call* call = new(zone_) Call(isolate_, expression, arguments, pos);
+ VISIT_AND_RETURN(Call, call)
+ }
+
+ CallNew* NewCallNew(Expression* expression,
+ ZoneList<Expression*>* arguments,
+ int pos) {
+ CallNew* call = new(zone_) CallNew(isolate_, expression, arguments, pos);
+ VISIT_AND_RETURN(CallNew, call)
+ }
+
+ CallRuntime* NewCallRuntime(Handle<String> name,
+ const Runtime::Function* function,
+ ZoneList<Expression*>* arguments) {
+ CallRuntime* call =
+ new(zone_) CallRuntime(isolate_, name, function, arguments);
+ VISIT_AND_RETURN(CallRuntime, call)
+ }
+
+ UnaryOperation* NewUnaryOperation(Token::Value op,
+ Expression* expression,
+ int pos) {
+ UnaryOperation* node =
+ new(zone_) UnaryOperation(isolate_, op, expression, pos);
+ VISIT_AND_RETURN(UnaryOperation, node)
+ }
+
+ BinaryOperation* NewBinaryOperation(Token::Value op,
+ Expression* left,
+ Expression* right,
+ int pos) {
+ BinaryOperation* node =
+ new(zone_) BinaryOperation(isolate_, op, left, right, pos);
+ VISIT_AND_RETURN(BinaryOperation, node)
+ }
+
+ CountOperation* NewCountOperation(Token::Value op,
+ bool is_prefix,
+ Expression* expr,
+ int pos) {
+ CountOperation* node =
+ new(zone_) CountOperation(isolate_, op, is_prefix, expr, pos);
+ VISIT_AND_RETURN(CountOperation, node)
+ }
+
+ CompareOperation* NewCompareOperation(Token::Value op,
+ Expression* left,
+ Expression* right,
+ int pos) {
+ CompareOperation* node =
+ new(zone_) CompareOperation(isolate_, op, left, right, pos);
+ VISIT_AND_RETURN(CompareOperation, node)
+ }
+
+ Conditional* NewConditional(Expression* condition,
+ Expression* then_expression,
+ Expression* else_expression,
+ int then_expression_position,
+ int else_expression_position) {
+ Conditional* cond = new(zone_) Conditional(
+ isolate_, condition, then_expression, else_expression,
+ then_expression_position, else_expression_position);
+ VISIT_AND_RETURN(Conditional, cond)
+ }
+
+ Assignment* NewAssignment(Token::Value op,
+ Expression* target,
+ Expression* value,
+ int pos) {
+ Assignment* assign =
+ new(zone_) Assignment(isolate_, op, target, value, pos);
+ assign->Init(isolate_, this);
+ VISIT_AND_RETURN(Assignment, assign)
+ }
+
+ Throw* NewThrow(Expression* exception, int pos) {
+ Throw* t = new(zone_) Throw(isolate_, exception, pos);
+ VISIT_AND_RETURN(Throw, t)
+ }
+
+ FunctionLiteral* NewFunctionLiteral(
+ Handle<String> name,
+ Scope* scope,
+ ZoneList<Statement*>* body,
+ int materialized_literal_count,
+ int expected_property_count,
+ int handler_count,
+ bool has_only_simple_this_property_assignments,
+ Handle<FixedArray> this_property_assignments,
+ int parameter_count,
+ bool has_duplicate_parameters,
+ FunctionLiteral::Type type,
+ bool visit_with_visitor) {
+ FunctionLiteral* lit = new(zone_) FunctionLiteral(
+ isolate_, name, scope, body,
+ materialized_literal_count, expected_property_count, handler_count,
+ has_only_simple_this_property_assignments, this_property_assignments,
+ parameter_count, type, has_duplicate_parameters);
+ if (visit_with_visitor) {
+ visitor_.VisitFunctionLiteral(lit);
+ }
+ return lit;
+ }
+
+ SharedFunctionInfoLiteral* NewSharedFunctionInfoLiteral(
+ Handle<SharedFunctionInfo> shared_function_info) {
+ SharedFunctionInfoLiteral* lit =
+ new(zone_) SharedFunctionInfoLiteral(isolate_, shared_function_info);
+ VISIT_AND_RETURN(SharedFunctionInfoLiteral, lit)
+ }
+
+ ThisFunction* NewThisFunction() {
+ ThisFunction* fun = new(zone_) ThisFunction(isolate_);
+ VISIT_AND_RETURN(ThisFunction, fun)
+ }
+
+#undef VISIT_AND_RETURN
+
+ private:
+ Isolate* isolate_;
+ Zone* zone_;
+ Visitor visitor_;
+};
+
+
} } // namespace v8::internal
#endif // V8_AST_H_
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// Check the function has compiled code.
ASSERT(shared->is_compiled());
shared->set_code_age(0);
+ shared->set_dont_crankshaft(lit->flags()->Contains(kDontOptimize));
+ shared->set_dont_inline(lit->flags()->Contains(kDontInline));
if (info->AllowOptimize() && !shared->optimization_disabled()) {
// If we're asked to always optimize, we compile the optimized
function_info->set_language_mode(lit->language_mode());
function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
+ function_info->set_ast_node_count(lit->ast_node_count());
+ function_info->set_dont_crankshaft(lit->flags()->Contains(kDontOptimize));
+ function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
}
share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER);
share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER);
share->set_this_property_assignments(undefined_value(), SKIP_WRITE_BARRIER);
- share->set_deopt_counter(Smi::FromInt(FLAG_deopt_every_n_times));
+ share->set_deopt_counter(FLAG_deopt_every_n_times);
+ share->set_ast_node_count(0);
// Set integer fields (smi or int, depending on the architecture).
share->set_length(0);
// Do a quick check on source code length to avoid parsing large
// inlining candidates.
- if ((FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize)
- || target->shared()->SourceSize() > kUnlimitedMaxSourceSize) {
+ if ((FLAG_limit_inlining && target_shared->SourceSize() > kMaxSourceSize)
+ || target_shared->SourceSize() > kUnlimitedMaxSourceSize) {
TraceInline(target, caller, "target text too big");
return false;
}
TraceInline(target, caller, "target not inlineable");
return false;
}
+ if (target_shared->dont_inline() || target_shared->dont_crankshaft()) {
+ TraceInline(target, caller, "target contains unsupported syntax [early]");
+ return false;
+ }
+
+ int nodes_added = target_shared->ast_node_count();
+ if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
+ nodes_added > kUnlimitedMaxInlinedSize) {
+ TraceInline(target, caller, "target AST is too large [early]");
+ return false;
+ }
#if !defined(V8_TARGET_ARCH_IA32)
// Target must be able to use caller's context.
return false;
}
- int count_before = AstNode::Count();
-
// Parse and allocate variables.
CompilationInfo target_info(target);
if (!ParserApi::Parse(&target_info, kNoParsingFlags) ||
}
FunctionLiteral* function = target_info.function();
- // Count the number of AST nodes added by inlining this call.
- int nodes_added = AstNode::Count() - count_before;
+ // The following conditions must be checked again after re-parsing, because
+ // earlier the information might not have been complete due to lazy parsing.
+ nodes_added = function->ast_node_count();
if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
nodes_added > kUnlimitedMaxInlinedSize) {
- TraceInline(target, caller, "target AST is too large");
+ TraceInline(target, caller, "target AST is too large [late]");
+ return false;
+ }
+ AstProperties::Flags* flags(function->flags());
+ if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) {
+ TraceInline(target, caller, "target contains unsupported syntax [late]");
return false;
}
return false;
}
}
- // All statements in the body must be inlineable.
- for (int i = 0, count = function->body()->length(); i < count; ++i) {
- if (!function->body()->at(i)->IsInlineable()) {
- TraceInline(target, caller, "target contains unsupported syntax");
- return false;
- }
- }
// Generate the deoptimization data for the unoptimized version of
// the target function if we don't already have it.
/* Serializer state. */ \
V(ExternalReferenceTable*, external_reference_table, NULL) \
/* AstNode state. */ \
- V(unsigned, ast_node_id, 0) \
+ V(int, ast_node_id, 0) \
V(unsigned, ast_node_count, 0) \
/* SafeStackFrameIterator activations count. */ \
V(int, safe_stack_iterator_counter, 0) \
SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
kThisPropertyAssignmentsCountOffset)
SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
+SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
+SMI_ACCESSORS(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
#else
#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
this_property_assignments_count,
kThisPropertyAssignmentsCountOffset)
PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
+
+PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
+PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
#endif
kNameShouldPrintAsAnonymous)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_crankshaft,
+ kDontCrankshaft)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
}
-Smi* SharedFunctionInfo::deopt_counter() {
- return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
-}
-
-
-void SharedFunctionInfo::set_deopt_counter(Smi* value) {
- WRITE_FIELD(this, kDeoptCounterOffset, value);
-}
-
-
bool SharedFunctionInfo::is_compiled() {
return code() !=
Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
// A counter used to determine when to stress the deoptimizer with a
// deopt.
- inline Smi* deopt_counter();
- inline void set_deopt_counter(Smi* counter);
+ inline int deopt_counter();
+ inline void set_deopt_counter(int counter);
+
+ inline int ast_node_count();
+ inline void set_ast_node_count(int count);
// Add information on assignments of the form this.x = ...;
void SetThisPropertyAssignmentsInfo(
// through the API, which does not change this flag).
DECL_BOOLEAN_ACCESSORS(is_anonymous)
+ // Indicates that the function cannot be crankshafted.
+ DECL_BOOLEAN_ACCESSORS(dont_crankshaft)
+
+ // Indicates that the function cannot be inlined.
+ DECL_BOOLEAN_ACCESSORS(dont_inline)
+
// Indicates whether or not the code in the shared function support
// deoptimization.
inline bool has_deoptimization_support();
kInferredNameOffset + kPointerSize;
static const int kThisPropertyAssignmentsOffset =
kInitialMapOffset + kPointerSize;
- static const int kDeoptCounterOffset =
- kThisPropertyAssignmentsOffset + kPointerSize;
#if V8_HOST_ARCH_32_BIT
// Smi fields.
static const int kLengthOffset =
- kDeoptCounterOffset + kPointerSize;
+ kThisPropertyAssignmentsOffset + kPointerSize;
static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
static const int kExpectedNofPropertiesOffset =
kFormalParameterCountOffset + kPointerSize;
kCompilerHintsOffset + kPointerSize;
static const int kOptCountOffset =
kThisPropertyAssignmentsCountOffset + kPointerSize;
+ static const int kAstNodeCountOffset = kOptCountOffset + kPointerSize;
+ static const int kDeoptCounterOffset =
+ kAstNodeCountOffset + kPointerSize;
// Total size.
- static const int kSize = kOptCountOffset + kPointerSize;
+ static const int kSize = kDeoptCounterOffset + kPointerSize;
#else
// The only reason to use smi fields instead of int fields
// is to allow iteration without maps decoding during
// word is not set and thus this word cannot be treated as pointer
// to HeapObject during old space traversal.
static const int kLengthOffset =
- kDeoptCounterOffset + kPointerSize;
+ kThisPropertyAssignmentsOffset + kPointerSize;
static const int kFormalParameterCountOffset =
kLengthOffset + kIntSize;
static const int kOptCountOffset =
kThisPropertyAssignmentsCountOffset + kIntSize;
+ static const int kAstNodeCountOffset = kOptCountOffset + kIntSize;
+ static const int kDeoptCounterOffset = kAstNodeCountOffset + kIntSize;
+
// Total size.
- static const int kSize = kOptCountOffset + kIntSize;
+ static const int kSize = kDeoptCounterOffset + kIntSize;
#endif
kBoundFunction,
kIsAnonymous,
kNameShouldPrintAsAnonymous,
+ kDontCrankshaft,
+ kDontInline,
kCompilerHintsCount // Pseudo entry
};
};
-class Parser::FunctionState BASE_EMBEDDED {
- public:
- FunctionState(Parser* parser, Scope* scope, Isolate* isolate);
- ~FunctionState();
-
- int NextMaterializedLiteralIndex() {
- return next_materialized_literal_index_++;
- }
- int materialized_literal_count() {
- return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
- }
-
- int NextHandlerIndex() { return next_handler_index_++; }
- int handler_count() { return next_handler_index_; }
-
- void SetThisPropertyAssignmentInfo(
- bool only_simple_this_property_assignments,
- Handle<FixedArray> this_property_assignments) {
- only_simple_this_property_assignments_ =
- only_simple_this_property_assignments;
- this_property_assignments_ = this_property_assignments;
- }
- bool only_simple_this_property_assignments() {
- return only_simple_this_property_assignments_;
- }
- Handle<FixedArray> this_property_assignments() {
- return this_property_assignments_;
- }
-
- void AddProperty() { expected_property_count_++; }
- int expected_property_count() { return expected_property_count_; }
-
- private:
- // Used to assign an index to each literal that needs materialization in
- // the function. Includes regexp literals, and boilerplate for object and
- // array literals.
- int next_materialized_literal_index_;
-
- // Used to assign a per-function index to try and catch handlers.
- int next_handler_index_;
-
- // Properties count estimation.
- int expected_property_count_;
-
- // Keeps track of assignments to properties of this. Used for
- // optimizing constructors.
- bool only_simple_this_property_assignments_;
- Handle<FixedArray> this_property_assignments_;
-
- Parser* parser_;
- FunctionState* outer_function_state_;
- Scope* outer_scope_;
- unsigned saved_ast_node_id_;
-};
-
-
Parser::FunctionState::FunctionState(Parser* parser,
Scope* scope,
Isolate* isolate)
parser_(parser),
outer_function_state_(parser->current_function_state_),
outer_scope_(parser->top_scope_),
- saved_ast_node_id_(isolate->ast_node_id()) {
+ saved_ast_node_id_(isolate->ast_node_id()),
+ factory_(isolate) {
parser->top_scope_ = scope;
parser->current_function_state_ = this;
isolate->set_ast_node_id(AstNode::kDeclarationsId + 1);
}
if (ok) {
- result = new(zone()) FunctionLiteral(
- isolate(),
+ result = factory()->NewFunctionLiteral(
no_name,
top_scope_,
body,
function_state.only_simple_this_property_assignments(),
function_state.this_property_assignments(),
0,
+ false, // Does not have duplicate parameters.
FunctionLiteral::ANONYMOUS_EXPRESSION,
- false); // Does not have duplicate parameters.
+ false); // Top-level literal doesn't count for the AST's properties.
+ result->set_ast_properties(factory()->visitor()->ast_properties());
} else if (stack_overflow_) {
isolate()->StackOverflow();
}
case Token::SEMICOLON:
Next();
- return EmptyStatement();
+ return factory()->NewEmptyStatement();
case Token::IF:
stmt = ParseIfStatement(labels, ok);
// one must take great care not to treat it as a
// fall-through. It is much easier just to wrap the entire
// try-statement in a statement block and put the labels there
- Block* result = new(zone()) Block(isolate(), labels, 1, false);
+ Block* result = factory()->NewBlock(labels, 1, false);
Target target(&this->target_stack_, result);
TryStatement* statement = ParseTryStatement(CHECK_OK);
if (statement) {
// a performance issue since it may lead to repeated
// Runtime::DeclareContextSlot() calls.
VariableProxy* proxy = declaration_scope->NewUnresolved(
- name, scanner().location().beg_pos);
+ factory(), name, scanner().location().beg_pos);
declaration_scope->AddDeclaration(
- new(zone()) Declaration(proxy, mode, fun, top_scope_));
+ factory()->NewDeclaration(proxy, mode, fun, top_scope_));
if ((mode == CONST || mode == CONST_HARMONY) &&
declaration_scope->is_global_scope()) {
// introduced dynamically when we meet their declarations, whereas
// other functions are set up when entering the surrounding scope.
SharedFunctionInfoLiteral* lit =
- new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
+ factory()->NewSharedFunctionInfoLiteral(shared);
VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
- return new(zone()) ExpressionStatement(new(zone()) Assignment(
- isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
+ return factory()->NewExpressionStatement(
+ factory()->NewAssignment(
+ Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
}
// initial value upon entering the corresponding scope.
VariableMode mode = is_extended_mode() ? LET : VAR;
Declare(name, mode, fun, true, CHECK_OK);
- return EmptyStatement();
+ return factory()->NewEmptyStatement();
}
// (ECMA-262, 3rd, 12.2)
//
// Construct block expecting 16 statements.
- Block* result = new(zone()) Block(isolate(), labels, 16, false);
+ Block* result = factory()->NewBlock(labels, 16, false);
Target target(&this->target_stack_, result);
Expect(Token::LBRACE, CHECK_OK);
InitializationBlockFinder block_finder(top_scope_, target_stack_);
// '{' SourceElement* '}'
// Construct block expecting 16 statements.
- Block* body = new(zone()) Block(isolate(), labels, 16, false);
+ Block* body = factory()->NewBlock(labels, 16, false);
Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
// Parse the statements and collect escaping labels.
// is inside an initializer block, it is ignored.
//
// Create new block with one expected declaration.
- Block* block = new(zone()) Block(isolate(), NULL, 1, true);
+ Block* block = factory()->NewBlock(NULL, 1, true);
int nvars = 0; // the number of variables declared
Handle<String> name;
do {
// Compute the arguments for the runtime call.
ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
// We have at least 1 parameter.
- arguments->Add(NewLiteral(name));
+ arguments->Add(factory()->NewLiteral(name));
CallRuntime* initialize;
if (is_const) {
// and add it to the initialization statement block.
// Note that the function does different things depending on
// the number of arguments (1 or 2).
- initialize =
- new(zone()) CallRuntime(
- isolate(),
- isolate()->factory()->InitializeConstGlobal_symbol(),
- Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
- arguments);
+ initialize = factory()->NewCallRuntime(
+ isolate()->factory()->InitializeConstGlobal_symbol(),
+ Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
+ arguments);
} else {
// Add strict mode.
// We may want to pass singleton to avoid Literal allocations.
LanguageMode language_mode = initialization_scope->language_mode();
- arguments->Add(NewNumberLiteral(language_mode));
+ arguments->Add(factory()->NewNumberLiteral(language_mode));
// Be careful not to assign a value to the global variable if
// we're in a with. The initialization value should not
// and add it to the initialization statement block.
// Note that the function does different things depending on
// the number of arguments (2 or 3).
- initialize =
- new(zone()) CallRuntime(
- isolate(),
- isolate()->factory()->InitializeVarGlobal_symbol(),
- Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
- arguments);
+ initialize = factory()->NewCallRuntime(
+ isolate()->factory()->InitializeVarGlobal_symbol(),
+ Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
+ arguments);
}
- block->AddStatement(new(zone()) ExpressionStatement(initialize));
+ block->AddStatement(factory()->NewExpressionStatement(initialize));
} else if (needs_init) {
// Constant initializations always assign to the declared constant which
// is always at the function scope level. This is only relevant for
ASSERT(proxy->var() != NULL);
ASSERT(value != NULL);
Assignment* assignment =
- new(zone()) Assignment(isolate(), init_op, proxy, value, position);
- block->AddStatement(new(zone()) ExpressionStatement(assignment));
+ factory()->NewAssignment(init_op, proxy, value, position);
+ block->AddStatement(factory()->NewExpressionStatement(assignment));
value = NULL;
}
// 'var' initializations are simply assignments (with all the consequences
// if they are inside a 'with' statement - they may change a 'with' object
// property).
- VariableProxy* proxy = initialization_scope->NewUnresolved(name);
+ VariableProxy* proxy =
+ initialization_scope->NewUnresolved(factory(), name);
Assignment* assignment =
- new(zone()) Assignment(isolate(), init_op, proxy, value, position);
- block->AddStatement(new(zone()) ExpressionStatement(assignment));
+ factory()->NewAssignment(init_op, proxy, value, position);
+ block->AddStatement(factory()->NewExpressionStatement(assignment));
}
if (fni_ != NULL) fni_->Leave();
// Parsed expression statement.
ExpectSemicolon(CHECK_OK);
- return new(zone()) ExpressionStatement(expr);
+ return factory()->NewExpressionStatement(expr);
}
Next();
else_statement = ParseStatement(labels, CHECK_OK);
} else {
- else_statement = EmptyStatement();
+ else_statement = factory()->NewEmptyStatement();
}
- return new(zone()) IfStatement(
- isolate(), condition, then_statement, else_statement);
+ return factory()->NewIfStatement(condition, then_statement, else_statement);
}
return NULL;
}
ExpectSemicolon(CHECK_OK);
- return new(zone()) ContinueStatement(target);
+ return factory()->NewContinueStatement(target);
}
// empty statements, e.g. 'l1: l2: l3: break l2;'
if (!label.is_null() && ContainsLabel(labels, label)) {
ExpectSemicolon(CHECK_OK);
- return EmptyStatement();
+ return factory()->NewEmptyStatement();
}
BreakableStatement* target = NULL;
target = LookupBreakTarget(label, CHECK_OK);
return NULL;
}
ExpectSemicolon(CHECK_OK);
- return new(zone()) BreakStatement(target);
+ return factory()->NewBreakStatement(target);
}
tok == Token::RBRACE ||
tok == Token::EOS) {
ExpectSemicolon(CHECK_OK);
- result = new(zone()) ReturnStatement(GetLiteralUndefined());
+ result = factory()->NewReturnStatement(GetLiteralUndefined());
} else {
Expression* expr = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
- result = new(zone()) ReturnStatement(expr);
+ result = factory()->NewReturnStatement(expr);
}
// An ECMAScript program is considered syntactically incorrect if it
declaration_scope->is_eval_scope()) {
Handle<String> type = isolate()->factory()->illegal_return_symbol();
Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
- return new(zone()) ExpressionStatement(throw_error);
+ return factory()->NewExpressionStatement(throw_error);
}
return result;
}
stmt = ParseStatement(labels, CHECK_OK);
with_scope->set_end_position(scanner().location().end_pos);
}
- return new(zone()) WithStatement(expr, stmt);
+ return factory()->NewWithStatement(expr, stmt);
}
// SwitchStatement ::
// 'switch' '(' Expression ')' '{' CaseClause* '}'
- SwitchStatement* statement = new(zone()) SwitchStatement(isolate(), labels);
+ SwitchStatement* statement = factory()->NewSwitchStatement(labels);
Target target(&this->target_stack_, statement);
Expect(Token::SWITCH, CHECK_OK);
Expression* exception = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
- return new(zone()) ExpressionStatement(
- new(zone()) Throw(isolate(), exception, pos));
+ return factory()->NewExpressionStatement(factory()->NewThrow(exception, pos));
}
// If we have both, create an inner try/catch.
ASSERT(catch_scope != NULL && catch_variable != NULL);
int index = current_function_state_->NextHandlerIndex();
- TryCatchStatement* statement = new(zone()) TryCatchStatement(index,
- try_block,
- catch_scope,
- catch_variable,
- catch_block);
+ TryCatchStatement* statement = factory()->NewTryCatchStatement(
+ index, try_block, catch_scope, catch_variable, catch_block);
statement->set_escaping_targets(try_collector.targets());
- try_block = new(zone()) Block(isolate(), NULL, 1, false);
+ try_block = factory()->NewBlock(NULL, 1, false);
try_block->AddStatement(statement);
catch_block = NULL; // Clear to indicate it's been handled.
}
ASSERT(finally_block == NULL);
ASSERT(catch_scope != NULL && catch_variable != NULL);
int index = current_function_state_->NextHandlerIndex();
- result = new(zone()) TryCatchStatement(index,
- try_block,
- catch_scope,
- catch_variable,
- catch_block);
+ result = factory()->NewTryCatchStatement(
+ index, try_block, catch_scope, catch_variable, catch_block);
} else {
ASSERT(finally_block != NULL);
int index = current_function_state_->NextHandlerIndex();
- result = new(zone()) TryFinallyStatement(index,
- try_block,
- finally_block);
+ result = factory()->NewTryFinallyStatement(index, try_block, finally_block);
// Combine the jump targets of the try block and the possible catch block.
try_collector.targets()->AddAll(*catch_collector.targets());
}
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
- DoWhileStatement* loop = new(zone()) DoWhileStatement(isolate(), labels);
+ DoWhileStatement* loop = factory()->NewDoWhileStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::DO, CHECK_OK);
// WhileStatement ::
// 'while' '(' Expression ')' Statement
- WhileStatement* loop = new(zone()) WhileStatement(isolate(), labels);
+ WhileStatement* loop = factory()->NewWhileStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::WHILE, CHECK_OK);
ParseVariableDeclarations(kForStatement, NULL, &name, CHECK_OK);
if (peek() == Token::IN && !name.is_null()) {
- VariableProxy* each = top_scope_->NewUnresolved(name);
- ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
+ VariableProxy* each = top_scope_->NewUnresolved(factory(), name);
+ ForInStatement* loop = factory()->NewForInStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
Statement* body = ParseStatement(NULL, CHECK_OK);
loop->Initialize(each, enumerable, body);
- Block* result = new(zone()) Block(isolate(), NULL, 2, false);
+ Block* result = factory()->NewBlock(NULL, 2, false);
result->AddStatement(variable_statement);
result->AddStatement(loop);
top_scope_ = saved_scope;
// TODO(keuchel): Move the temporary variable to the block scope, after
// implementing stack allocated block scoped variables.
Variable* temp = top_scope_->DeclarationScope()->NewTemporary(name);
- VariableProxy* temp_proxy = new(zone()) VariableProxy(isolate(), temp);
- VariableProxy* each = top_scope_->NewUnresolved(name);
- ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
+ VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
+ VariableProxy* each = top_scope_->NewUnresolved(factory(), name);
+ ForInStatement* loop = factory()->NewForInStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
Statement* body = ParseStatement(NULL, CHECK_OK);
- Block* body_block = new(zone()) Block(isolate(), NULL, 3, false);
- Assignment* assignment = new(zone()) Assignment(isolate(),
- Token::ASSIGN,
- each,
- temp_proxy,
- RelocInfo::kNoPosition);
+ Block* body_block = factory()->NewBlock(NULL, 3, false);
+ Assignment* assignment = factory()->NewAssignment(
+ Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
Statement* assignment_statement =
- new(zone()) ExpressionStatement(assignment);
+ factory()->NewExpressionStatement(assignment);
body_block->AddStatement(variable_statement);
body_block->AddStatement(assignment_statement);
body_block->AddStatement(body);
isolate()->factory()->invalid_lhs_in_for_in_symbol();
expression = NewThrowReferenceError(type);
}
- ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
+ ForInStatement* loop = factory()->NewForInStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
return loop;
} else {
- init = new(zone()) ExpressionStatement(expression);
+ init = factory()->NewExpressionStatement(expression);
}
}
}
// Standard 'for' loop
- ForStatement* loop = new(zone()) ForStatement(isolate(), labels);
+ ForStatement* loop = factory()->NewForStatement(labels);
Target target(&this->target_stack_, loop);
// Parsed initializer at this point.
Statement* next = NULL;
if (peek() != Token::RPAREN) {
Expression* exp = ParseExpression(true, CHECK_OK);
- next = new(zone()) ExpressionStatement(exp);
+ next = factory()->NewExpressionStatement(exp);
}
Expect(Token::RPAREN, CHECK_OK);
// for (; c; n) b
// }
ASSERT(init != NULL);
- Block* result = new(zone()) Block(isolate(), NULL, 2, false);
+ Block* result = factory()->NewBlock(NULL, 2, false);
result->AddStatement(init);
result->AddStatement(loop);
result->set_block_scope(for_scope);
Expect(Token::COMMA, CHECK_OK);
int position = scanner().location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- result = new(zone()) BinaryOperation(
- isolate(), Token::COMMA, result, right, position);
+ result =
+ factory()->NewBinaryOperation(Token::COMMA, result, right, position);
}
return result;
}
fni_->Leave();
}
- return new(zone()) Assignment(isolate(), op, expression, right, pos);
+ return factory()->NewAssignment(op, expression, right, pos);
}
Expect(Token::COLON, CHECK_OK);
int right_position = scanner().peek_location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- return new(zone()) Conditional(
- isolate(), expression, left, right, left_position, right_position);
+ return factory()->NewConditional(
+ expression, left, right, left_position, right_position);
}
switch (op) {
case Token::ADD:
- x = NewNumberLiteral(x_val + y_val);
+ x = factory()->NewNumberLiteral(x_val + y_val);
continue;
case Token::SUB:
- x = NewNumberLiteral(x_val - y_val);
+ x = factory()->NewNumberLiteral(x_val - y_val);
continue;
case Token::MUL:
- x = NewNumberLiteral(x_val * y_val);
+ x = factory()->NewNumberLiteral(x_val * y_val);
continue;
case Token::DIV:
- x = NewNumberLiteral(x_val / y_val);
+ x = factory()->NewNumberLiteral(x_val / y_val);
continue;
- case Token::BIT_OR:
- x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
+ case Token::BIT_OR: {
+ int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
+ x = factory()->NewNumberLiteral(value);
continue;
- case Token::BIT_AND:
- x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
+ }
+ case Token::BIT_AND: {
+ int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
+ x = factory()->NewNumberLiteral(value);
continue;
- case Token::BIT_XOR:
- x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
+ }
+ case Token::BIT_XOR: {
+ int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
+ x = factory()->NewNumberLiteral(value);
continue;
+ }
case Token::SHL: {
int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
- x = NewNumberLiteral(value);
+ x = factory()->NewNumberLiteral(value);
continue;
}
case Token::SHR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
uint32_t value = DoubleToUint32(x_val) >> shift;
- x = NewNumberLiteral(value);
+ x = factory()->NewNumberLiteral(value);
continue;
}
case Token::SAR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
- x = NewNumberLiteral(value);
+ x = factory()->NewNumberLiteral(value);
continue;
}
default:
case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
default: break;
}
- x = new(zone()) CompareOperation(isolate(), cmp, x, y, position);
+ x = factory()->NewCompareOperation(cmp, x, y, position);
if (cmp != op) {
// The comparison was negated - add a NOT.
- x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
+ x = factory()->NewUnaryOperation(Token::NOT, x, position);
}
} else {
// We have a "normal" binary operation.
- x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
+ x = factory()->NewBinaryOperation(op, x, y, position);
}
}
}
// Convert the literal to a boolean condition and negate it.
bool condition = literal->ToBoolean()->IsTrue();
Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
- return NewLiteral(result);
+ return factory()->NewLiteral(result);
} else if (literal->IsNumber()) {
// Compute some expressions involving only number literals.
double value = literal->Number();
case Token::ADD:
return expression;
case Token::SUB:
- return NewNumberLiteral(-value);
+ return factory()->NewNumberLiteral(-value);
case Token::BIT_NOT:
- return NewNumberLiteral(~DoubleToInt32(value));
+ return factory()->NewNumberLiteral(~DoubleToInt32(value));
default:
break;
}
}
}
- return new(zone()) UnaryOperation(isolate(), op, expression, position);
+ return factory()->NewUnaryOperation(op, expression, position);
} else if (Token::IsCountOp(op)) {
op = Next();
MarkAsLValue(expression);
int position = scanner().location().beg_pos;
- return new(zone()) CountOperation(isolate(),
- op,
- true /* prefix */,
- expression,
- position);
+ return factory()->NewCountOperation(op,
+ true /* prefix */,
+ expression,
+ position);
} else {
return ParsePostfixExpression(ok);
Token::Value next = Next();
int position = scanner().location().beg_pos;
expression =
- new(zone()) CountOperation(isolate(),
- next,
- false /* postfix */,
- expression,
- position);
+ factory()->NewCountOperation(next,
+ false /* postfix */,
+ expression,
+ position);
}
return expression;
}
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
- result = new(zone()) Property(isolate(), result, index, pos);
+ result = factory()->NewProperty(result, index, pos);
Expect(Token::RBRACK, CHECK_OK);
break;
}
callee->IsVariable(isolate()->factory()->eval_symbol())) {
top_scope_->DeclarationScope()->RecordEvalCall();
}
- result = NewCall(result, args, pos);
+ result = factory()->NewCall(result, args, pos);
break;
}
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
- result = new(zone()) Property(isolate(),
- result,
- NewLiteral(name),
- pos);
+ result =
+ factory()->NewProperty(result, factory()->NewLiteral(name), pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
if (!stack->is_empty()) {
int last = stack->pop();
- result = new(zone()) CallNew(isolate(),
- result,
- new(zone()) ZoneList<Expression*>(0),
- last);
+ result = factory()->NewCallNew(
+ result, new(zone()) ZoneList<Expression*>(0), last);
}
return result;
}
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
- result = new(zone()) Property(isolate(), result, index, pos);
+ result = factory()->NewProperty(result, index, pos);
if (fni_ != NULL) {
if (index->IsPropertyName()) {
fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
- result = new(zone()) Property(isolate(),
- result,
- NewLiteral(name),
- pos);
+ result =
+ factory()->NewProperty(result, factory()->NewLiteral(name), pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
// Consume one of the new prefixes (already parsed).
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
int last = stack->pop();
- result = new(zone()) CallNew(isolate(), result, args, last);
+ result = factory()->NewCallNew(result, args, last);
break;
}
default:
Expect(Token::DEBUGGER, CHECK_OK);
ExpectSemicolon(CHECK_OK);
- return new(zone()) DebuggerStatement();
+ return factory()->NewDebuggerStatement();
}
switch (peek()) {
case Token::THIS: {
Consume(Token::THIS);
- result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
+ result = factory()->NewVariableProxy(top_scope_->receiver());
break;
}
case Token::NULL_LITERAL:
Consume(Token::NULL_LITERAL);
- result = new(zone()) Literal(
- isolate(), isolate()->factory()->null_value());
+ result = factory()->NewLiteral(isolate()->factory()->null_value());
break;
case Token::TRUE_LITERAL:
Consume(Token::TRUE_LITERAL);
- result = new(zone()) Literal(
- isolate(), isolate()->factory()->true_value());
+ result = factory()->NewLiteral(isolate()->factory()->true_value());
break;
case Token::FALSE_LITERAL:
Consume(Token::FALSE_LITERAL);
- result = new(zone()) Literal(
- isolate(), isolate()->factory()->false_value());
+ result = factory()->NewLiteral(isolate()->factory()->false_value());
break;
case Token::IDENTIFIER:
case Token::FUTURE_STRICT_RESERVED_WORD: {
Handle<String> name = ParseIdentifier(CHECK_OK);
if (fni_ != NULL) fni_->PushVariableName(name);
- result = top_scope_->NewUnresolved(name, scanner().location().beg_pos);
+ result = top_scope_->NewUnresolved(
+ factory(), name, scanner().location().beg_pos);
break;
}
double value = StringToDouble(isolate()->unicode_cache(),
scanner().literal_ascii_string(),
ALLOW_HEX | ALLOW_OCTALS);
- result = NewNumberLiteral(value);
+ result = factory()->NewNumberLiteral(value);
break;
}
case Token::STRING: {
Consume(Token::STRING);
Handle<String> symbol = GetSymbol(CHECK_OK);
- result = NewLiteral(symbol);
+ result = factory()->NewLiteral(symbol);
if (fni_ != NULL) fni_->PushLiteralName(symbol);
break;
}
literals->set(0, Smi::FromInt(elements_kind));
literals->set(1, *element_values);
- return new(zone()) ArrayLiteral(
- isolate(), literals, values, literal_index, is_simple, depth);
+ return factory()->NewArrayLiteral(
+ literals, values, literal_index, is_simple, depth);
}
CHECK_OK);
// Allow any number of parameters for compatibilty with JSC.
// Specification only allows zero parameters for get and one for set.
- ObjectLiteral::Property* property =
- new(zone()) ObjectLiteral::Property(is_getter, value);
- return property;
+ return factory()->NewObjectLiteralProperty(is_getter, value);
} else {
ReportUnexpectedToken(next);
*ok = false;
}
// Failed to parse as get/set property, so it's just a property
// called "get" or "set".
- key = NewLiteral(id);
+ key = factory()->NewLiteral(id);
break;
}
case Token::STRING: {
if (fni_ != NULL) fni_->PushLiteralName(string);
uint32_t index;
if (!string.is_null() && string->AsArrayIndex(&index)) {
- key = NewNumberLiteral(index);
+ key = factory()->NewNumberLiteral(index);
break;
}
- key = NewLiteral(string);
+ key = factory()->NewLiteral(string);
break;
}
case Token::NUMBER: {
double value = StringToDouble(isolate()->unicode_cache(),
scanner().literal_ascii_string(),
ALLOW_HEX | ALLOW_OCTALS);
- key = NewNumberLiteral(value);
+ key = factory()->NewNumberLiteral(value);
break;
}
default:
if (Token::IsKeyword(next)) {
Consume(next);
Handle<String> string = GetSymbol(CHECK_OK);
- key = NewLiteral(string);
+ key = factory()->NewLiteral(string);
} else {
// Unexpected token.
Token::Value next = Next();
&is_simple,
&fast_elements,
&depth);
- return new(zone()) ObjectLiteral(isolate(),
- constant_properties,
- properties,
- literal_index,
- is_simple,
- fast_elements,
- depth,
- has_function);
+ return factory()->NewObjectLiteral(constant_properties,
+ properties,
+ literal_index,
+ is_simple,
+ fast_elements,
+ depth,
+ has_function);
}
Handle<String> js_flags = NextLiteralString(TENURED);
Next();
- return new(zone()) RegExpLiteral(
- isolate(), js_pattern, js_flags, literal_index);
+ return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index);
}
class SingletonLogger : public ParserRecorder {
public:
SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
- ~SingletonLogger() { }
+ virtual ~SingletonLogger() { }
void Reset() { has_error_ = false; }
bool only_simple_this_property_assignments;
Handle<FixedArray> this_property_assignments;
bool has_duplicate_parameters = false;
+ AstProperties ast_properties;
// Parse function body.
{ FunctionState function_state(this, scope, isolate());
top_scope_->SetScopeName(function_name);
} else {
fvar_mode = CONST;
}
- fvar = top_scope_->DeclareFunctionVar(function_name, fvar_mode);
+ fvar =
+ top_scope_->DeclareFunctionVar(function_name, fvar_mode, factory());
}
// Determine whether the function will be lazily compiled.
if (!is_lazily_compiled) {
body = new(zone()) ZoneList<Statement*>(8);
if (fvar != NULL) {
- VariableProxy* fproxy = top_scope_->NewUnresolved(function_name);
+ VariableProxy* fproxy =
+ top_scope_->NewUnresolved(factory(), function_name);
fproxy->BindTo(fvar);
- body->Add(new(zone()) ExpressionStatement(
- new(zone()) Assignment(isolate(),
- fvar_init_op,
- fproxy,
- new(zone()) ThisFunction(isolate()),
- RelocInfo::kNoPosition)));
+ body->Add(factory()->NewExpressionStatement(
+ factory()->NewAssignment(fvar_init_op,
+ fproxy,
+ factory()->NewThisFunction(),
+ RelocInfo::kNoPosition)));
}
ParseSourceElements(body, Token::RBRACE, CHECK_OK);
scope->end_position(),
CHECK_OK);
}
+ ast_properties = *factory()->visitor()->ast_properties();
}
if (is_extended_mode()) {
}
FunctionLiteral* function_literal =
- new(zone()) FunctionLiteral(isolate(),
- function_name,
- scope,
- body,
- materialized_literal_count,
- expected_property_count,
- handler_count,
- only_simple_this_property_assignments,
- this_property_assignments,
- num_parameters,
- type,
- has_duplicate_parameters);
+ factory()->NewFunctionLiteral(function_name,
+ scope,
+ body,
+ materialized_literal_count,
+ expected_property_count,
+ handler_count,
+ only_simple_this_property_assignments,
+ this_property_assignments,
+ num_parameters,
+ has_duplicate_parameters,
+ type,
+ true);
function_literal->set_function_token_position(function_token_position);
+ function_literal->set_ast_properties(&ast_properties);
if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
return function_literal;
}
// We have a valid intrinsics call or a call to a builtin.
- return new(zone()) CallRuntime(isolate(), name, function, args);
+ return factory()->NewCallRuntime(name, function, args);
}
Literal* Parser::GetLiteralUndefined() {
- return NewLiteral(isolate()->factory()->undefined_value());
+ return factory()->NewLiteral(isolate()->factory()->undefined_value());
}
Literal* Parser::GetLiteralTheHole() {
- return NewLiteral(isolate()->factory()->the_hole_value());
-}
-
-
-Literal* Parser::GetLiteralNumber(double value) {
- return NewNumberLiteral(value);
+ return factory()->NewLiteral(isolate()->factory()->the_hole_value());
}
}
-Literal* Parser::NewNumberLiteral(double number) {
- return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
-}
-
-
Expression* Parser::NewThrowReferenceError(Handle<String> type) {
return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
type, HandleVector<Object>(NULL, 0));
elements, FAST_ELEMENTS, TENURED);
ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
- args->Add(NewLiteral(type));
- args->Add(NewLiteral(array));
- CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
- constructor,
- NULL,
- args);
- return new(zone()) Throw(isolate(),
- call_constructor,
- scanner().location().beg_pos);
+ args->Add(factory()->NewLiteral(type));
+ args->Add(factory()->NewLiteral(array));
+ CallRuntime* call_constructor =
+ factory()->NewCallRuntime(constructor, NULL, args);
+ return factory()->NewThrow(call_constructor, scanner().location().beg_pos);
}
// ----------------------------------------------------------------------------
parsing_flags |= EXTENDED_MODE;
}
if (FLAG_allow_natives_syntax || info->is_native()) {
- // We requre %identifier(..) syntax.
+ // We require %identifier(..) syntax.
parsing_flags |= kAllowNativesSyntax;
}
if (info->is_lazy()) {
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
v8::Extension* extension,
ScriptDataImpl* pre_data);
virtual ~Parser() {
- if (reusable_preparser_ != NULL) {
- delete reusable_preparser_;
- }
+ delete reusable_preparser_;
+ reusable_preparser_ = NULL;
}
// Returns NULL if parsing failed.
};
class BlockState;
- class FunctionState;
+
+ class FunctionState BASE_EMBEDDED {
+ public:
+ FunctionState(Parser* parser,
+ Scope* scope,
+ Isolate* isolate);
+ ~FunctionState();
+
+ int NextMaterializedLiteralIndex() {
+ return next_materialized_literal_index_++;
+ }
+ int materialized_literal_count() {
+ return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
+ }
+
+ int NextHandlerIndex() { return next_handler_index_++; }
+ int handler_count() { return next_handler_index_; }
+
+ void SetThisPropertyAssignmentInfo(
+ bool only_simple_this_property_assignments,
+ Handle<FixedArray> this_property_assignments) {
+ only_simple_this_property_assignments_ =
+ only_simple_this_property_assignments;
+ this_property_assignments_ = this_property_assignments;
+ }
+ bool only_simple_this_property_assignments() {
+ return only_simple_this_property_assignments_;
+ }
+ Handle<FixedArray> this_property_assignments() {
+ return this_property_assignments_;
+ }
+
+ void AddProperty() { expected_property_count_++; }
+ int expected_property_count() { return expected_property_count_; }
+
+ AstNodeFactory<AstConstructionVisitor>* factory() { return &factory_; }
+
+ private:
+ // Used to assign an index to each literal that needs materialization in
+ // the function. Includes regexp literals, and boilerplate for object and
+ // array literals.
+ int next_materialized_literal_index_;
+
+ // Used to assign a per-function index to try and catch handlers.
+ int next_handler_index_;
+
+ // Properties count estimation.
+ int expected_property_count_;
+
+ // Keeps track of assignments to properties of this. Used for
+ // optimizing constructors.
+ bool only_simple_this_property_assignments_;
+ Handle<FixedArray> this_property_assignments_;
+
+ Parser* parser_;
+ FunctionState* outer_function_state_;
+ Scope* outer_scope_;
+ int saved_ast_node_id_;
+ AstNodeFactory<AstConstructionVisitor> factory_;
+ };
+
+
+
FunctionLiteral* ParseLazy(CompilationInfo* info,
UC16CharacterStream* source,
// Get odd-ball literals.
Literal* GetLiteralUndefined();
Literal* GetLiteralTheHole();
- Literal* GetLiteralNumber(double value);
Handle<String> ParseIdentifier(bool* ok);
Handle<String> ParseIdentifierOrStrictReservedWord(
// Factory methods.
- Statement* EmptyStatement() {
- static v8::internal::EmptyStatement* empty =
- ::new v8::internal::EmptyStatement();
- return empty;
- }
-
Scope* NewScope(Scope* parent, ScopeType type);
Handle<String> LookupSymbol(int symbol_id);
Handle<String> LookupCachedSymbol(int symbol_id);
- Expression* NewCall(Expression* expression,
- ZoneList<Expression*>* arguments,
- int pos) {
- return new(zone()) Call(isolate(), expression, arguments, pos);
- }
-
- inline Literal* NewLiteral(Handle<Object> handle) {
- return new(zone()) Literal(isolate(), handle);
- }
-
- // Create a number literal.
- Literal* NewNumberLiteral(double value);
-
// Generate AST node that throw a ReferenceError with the given type.
Expression* NewThrowReferenceError(Handle<String> type);
preparser::PreParser::PreParseResult LazyParseFunctionLiteral(
SingletonLogger* logger);
+ AstNodeFactory<AstConstructionVisitor>* factory() {
+ return current_function_state_->factory();
+ }
+
Isolate* isolate_;
ZoneList<Handle<String> > symbol_cache_;
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
: result_(result),
result_assigned_(false),
is_set_(false),
- in_try_(false) {
- }
+ in_try_(false),
+ factory_(isolate()) { }
+
+ virtual ~Processor() { }
void Process(ZoneList<Statement*>* statements);
bool result_assigned() const { return result_assigned_; }
+ AstNodeFactory<AstNullVisitor>* factory() {
+ return &factory_;
+ }
+
private:
Variable* result_;
bool is_set_;
bool in_try_;
+ AstNodeFactory<AstNullVisitor> factory_;
+
Expression* SetResult(Expression* value) {
result_assigned_ = true;
- Zone* zone = isolate()->zone();
- VariableProxy* result_proxy = new(zone) VariableProxy(isolate(), result_);
- return new(zone) Assignment(isolate(),
- Token::ASSIGN,
- result_proxy,
- value,
- RelocInfo::kNoPosition);
+ VariableProxy* result_proxy = factory()->NewVariableProxy(result_);
+ return factory()->NewAssignment(
+ Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition);
}
// Node visitors.
if (processor.result_assigned()) {
ASSERT(function->end_position() != RelocInfo::kNoPosition);
- Isolate* isolate = info->isolate();
- Zone* zone = isolate->zone();
// Set the position of the assignment statement one character past the
// source code, such that it definitely is not in the source code range
// of an immediate inner scope. For example in
// the end position of the function generated for executing the eval code
// coincides with the end of the with scope which is the position of '1'.
int position = function->end_position();
- VariableProxy* result_proxy = new(zone) VariableProxy(
- isolate, result->name(), false, position);
+ VariableProxy* result_proxy = processor.factory()->NewVariableProxy(
+ result->name(), false, position);
result_proxy->BindTo(result);
- Statement* result_statement = new(zone) ReturnStatement(result_proxy);
+ Statement* result_statement =
+ processor.factory()->NewReturnStatement(result_proxy);
result_statement->set_statement_pos(position);
body->Add(result_statement);
}
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
top = top->outer_scope();
}
- // Allocated the variables.
- top->AllocateVariables(info->global_scope());
+ // Allocate the variables.
+ {
+ AstNodeFactory<AstNullVisitor> ast_node_factory(info->isolate());
+ top->AllocateVariables(info->global_scope(), &ast_node_factory);
+ }
#ifdef DEBUG
if (info->isolate()->bootstrapper()->IsActive()
}
-Variable* Scope::LookupFunctionVar(Handle<String> name) {
+Variable* Scope::LookupFunctionVar(Handle<String> name,
+ AstNodeFactory<AstNullVisitor>* factory) {
if (function_ != NULL && function_->name().is_identical_to(name)) {
return function_->var();
} else if (!scope_info_.is_null()) {
VariableMode mode;
int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
if (index < 0) return NULL;
- Variable* var = DeclareFunctionVar(name, mode);
+ Variable* var = DeclareFunctionVar(name, mode, factory);
var->AllocateTo(Variable::CONTEXT, index);
return var;
} else {
}
-Variable* Scope::DeclareFunctionVar(Handle<String> name, VariableMode mode) {
- ASSERT(is_function_scope() && function_ == NULL);
- Variable* function_var = new Variable(
- this, name, mode, true, Variable::NORMAL, kCreatedInitialized);
- function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
- return function_var;
-}
-
-
void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
ASSERT(!already_resolved());
ASSERT(is_function_scope());
}
-VariableProxy* Scope::NewUnresolved(Handle<String> name, int position) {
- // Note that we must not share the unresolved variables with
- // the same name because they may be removed selectively via
- // RemoveUnresolved().
- ASSERT(!already_resolved());
- VariableProxy* proxy = new(isolate_->zone()) VariableProxy(
- isolate_, name, false, position);
- unresolved_.Add(proxy);
- return proxy;
-}
-
-
void Scope::RemoveUnresolved(VariableProxy* var) {
// Most likely (always?) any variable we want to remove
// was just added before, so we search backwards.
}
-void Scope::AllocateVariables(Scope* global_scope) {
+void Scope::AllocateVariables(Scope* global_scope,
+ AstNodeFactory<AstNullVisitor>* factory) {
// 1) Propagate scope information.
bool outer_scope_calls_non_strict_eval = false;
if (outer_scope_ != NULL) {
PropagateScopeInfo(outer_scope_calls_non_strict_eval);
// 2) Resolve variables.
- ResolveVariablesRecursively(global_scope);
+ ResolveVariablesRecursively(global_scope, factory);
// 3) Allocate variables.
AllocateVariablesRecursively();
Variable* Scope::LookupRecursive(Handle<String> name,
- BindingKind* binding_kind) {
+ BindingKind* binding_kind,
+ AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(binding_kind != NULL);
// Try to find the variable in this scope.
Variable* var = LocalLookup(name);
// if any. We can do this for all scopes, since the function variable is
// only present - if at all - for function scopes.
*binding_kind = UNBOUND;
- var = LookupFunctionVar(name);
+ var = LookupFunctionVar(name, factory);
if (var != NULL) {
*binding_kind = BOUND;
} else if (outer_scope_ != NULL) {
- var = outer_scope_->LookupRecursive(name, binding_kind);
+ var = outer_scope_->LookupRecursive(name, binding_kind, factory);
if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
var->ForceContextAllocation();
}
void Scope::ResolveVariable(Scope* global_scope,
- VariableProxy* proxy) {
+ VariableProxy* proxy,
+ AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(global_scope == NULL || global_scope->is_global_scope());
// If the proxy is already resolved there's nothing to do
// Otherwise, try to resolve the variable.
BindingKind binding_kind;
- Variable* var = LookupRecursive(proxy->name(), &binding_kind);
+ Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
switch (binding_kind) {
case BOUND:
// We found a variable binding.
}
-void Scope::ResolveVariablesRecursively(Scope* global_scope) {
+void Scope::ResolveVariablesRecursively(
+ Scope* global_scope,
+ AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(global_scope == NULL || global_scope->is_global_scope());
// Resolve unresolved variables for this scope.
for (int i = 0; i < unresolved_.length(); i++) {
- ResolveVariable(global_scope, unresolved_[i]);
+ ResolveVariable(global_scope, unresolved_[i], factory);
}
// Resolve unresolved variables for inner scopes.
for (int i = 0; i < inner_scopes_.length(); i++) {
- inner_scopes_[i]->ResolveVariablesRecursively(global_scope);
+ inner_scopes_[i]->ResolveVariablesRecursively(global_scope, factory);
}
}
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// between this scope and the outer scope. (ECMA-262, 3rd., requires that
// the name of named function literal is kept in an intermediate scope
// in between this scope and the next outer scope.)
- Variable* LookupFunctionVar(Handle<String> name);
+ Variable* LookupFunctionVar(Handle<String> name,
+ AstNodeFactory<AstNullVisitor>* factory);
// Lookup a variable in this scope or outer scopes.
// Returns the variable or NULL if not found.
// Declare the function variable for a function literal. This variable
// is in an intermediate scope between this function scope and the the
// outer scope. Only possible for function scopes; at most one variable.
- Variable* DeclareFunctionVar(Handle<String> name, VariableMode mode);
+ template<class Visitor>
+ Variable* DeclareFunctionVar(Handle<String> name,
+ VariableMode mode,
+ AstNodeFactory<Visitor>* factory) {
+ ASSERT(is_function_scope() && function_ == NULL);
+ Variable* function_var = new Variable(
+ this, name, mode, true, Variable::NORMAL, kCreatedInitialized);
+ function_ = factory->NewVariableProxy(function_var);
+ return function_var;
+ }
// Declare a parameter in this scope. When there are duplicated
// parameters the rightmost one 'wins'. However, the implementation
Variable* DeclareGlobal(Handle<String> name);
// Create a new unresolved variable.
- VariableProxy* NewUnresolved(Handle<String> name,
- int position = RelocInfo::kNoPosition);
+ template<class Visitor>
+ VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory,
+ Handle<String> name,
+ int position = RelocInfo::kNoPosition) {
+ // Note that we must not share the unresolved variables with
+ // the same name because they may be removed selectively via
+ // RemoveUnresolved().
+ ASSERT(!already_resolved());
+ VariableProxy* proxy = factory->NewVariableProxy(name, false, position);
+ unresolved_.Add(proxy);
+ return proxy;
+ }
// Remove a unresolved variable. During parsing, an unresolved variable
// may have been added optimistically, but then only the variable name
// In the case of code compiled and run using 'eval', the context
// parameter is the context in which eval was called. In all other
// cases the context parameter is an empty handle.
- void AllocateVariables(Scope* global_scope);
+ void AllocateVariables(Scope* global_scope,
+ AstNodeFactory<AstNullVisitor>* factory);
// Current number of var or const locals.
int num_var_or_const() { return num_var_or_const_; }
// scope. If the code is executed because of a call to 'eval', the context
// parameter should be set to the calling context of 'eval'.
Variable* LookupRecursive(Handle<String> name,
- BindingKind* binding_kind);
+ BindingKind* binding_kind,
+ AstNodeFactory<AstNullVisitor>* factory);
void ResolveVariable(Scope* global_scope,
- VariableProxy* proxy);
- void ResolveVariablesRecursively(Scope* global_scope);
+ VariableProxy* proxy,
+ AstNodeFactory<AstNullVisitor>* factory);
+ void ResolveVariablesRecursively(Scope* global_scope,
+ AstNodeFactory<AstNullVisitor>* factory);
// Scope analysis.
bool PropagateScopeInfo(bool outer_scope_calls_non_strict_eval);
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
CHECK_EQ(0, list->length());
ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
- AstNode* node = new(ZONE) EmptyStatement();
+ AstNodeFactory<AstNullVisitor> factory(Isolate::Current());
+ AstNode* node = factory.NewEmptyStatement();
list->Add(node);
CHECK_EQ(1, list->length());
CHECK_EQ(node, list->at(0));