Collect AstNode type information

Review URL: https://chromiumcodereview.appspot.com/9221011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10631 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9463c00d
......@@ -126,18 +126,7 @@ Assignment::Assignment(Isolate* isolate,
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 {
......@@ -179,6 +168,11 @@ LanguageMode FunctionLiteral::language_mode() const {
}
bool FunctionLiteral::ShouldSelfOptimize() {
return !flags()->Contains(kDontSelfOptimize);
}
ObjectLiteral::Property::Property(Literal* key, Expression* value) {
emit_store_ = true;
key_ = key;
......@@ -197,9 +191,7 @@ ObjectLiteral::Property::Property(Literal* key, Expression* value) {
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;
}
......@@ -431,223 +423,6 @@ bool Declaration::IsInlineable() const {
}
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
......@@ -1214,4 +989,164 @@ CaseClause::CaseClause(Isolate* isolate,
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
......@@ -39,6 +39,7 @@
#include "small-pointer-list.h"
#include "smart-array-pointer.h"
#include "token.h"
#include "utils.h"
#include "variables.h"
#include "zone-inl.h"
......@@ -103,6 +104,8 @@ namespace internal {
EXPRESSION_NODE_LIST(V)
// Forward declarations
class AstConstructionVisitor;
template<class> class AstNodeFactory;
class AstVisitor;
class BreakableStatement;
class Expression;
......@@ -136,6 +139,35 @@ typedef ZoneList<Handle<String> > ZoneStringList;
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,
......@@ -152,14 +184,11 @@ class AstNode: public ZoneObject {
// 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() { }
......@@ -180,19 +209,15 @@ class AstNode: public ZoneObject {
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;
}
......@@ -326,8 +351,8 @@ class Expression: public AstNode {
unsigned test_id() const { return test_id_; }
private:
unsigned id_;
unsigned test_id_;
int id_;
int test_id_;
};
......@@ -376,21 +401,8 @@ class BreakableStatement: public Statement {
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_; }
......@@ -399,6 +411,19 @@ class Block: public BreakableStatement {
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_;
......@@ -408,6 +433,17 @@ class Block: public BreakableStatement {
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,
......@@ -424,14 +460,6 @@ class Declaration: public AstNode {
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_;
......@@ -477,14 +505,6 @@ class IterationStatement: public BreakableStatement {
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) {
......@@ -504,7 +524,16 @@ class DoWhileStatement: public IterationStatement {
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_;
......@@ -516,13 +545,6 @@ class DoWhileStatement: public IterationStatement {
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) {
......@@ -537,13 +559,22 @@ class WhileStatement: public IterationStatement {
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.
......@@ -554,17 +585,6 @@ class WhileStatement: public IterationStatement {
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,
......@@ -596,7 +616,20 @@ class ForStatement: public IterationStatement {
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_;
......@@ -612,13 +645,6 @@ class ForStatement: public IterationStatement {
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) {
......@@ -629,13 +655,22 @@ class ForInStatement: public IterationStatement {
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_;
......@@ -645,16 +680,17 @@ class ForInStatement: public IterationStatement {
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_;
};
......@@ -662,13 +698,15 @@ class ExpressionStatement: public Statement {
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_;
......@@ -677,13 +715,15 @@ class ContinueStatement: public Statement {
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_;
......@@ -692,13 +732,15 @@ class BreakStatement: public Statement {
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_;
......@@ -707,15 +749,17 @@ class ReturnStatement: public Statement {
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_;
......@@ -771,13 +815,6 @@ class CaseClause: public ZoneObject {
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) {
......@@ -787,7 +824,14 @@ class SwitchStatement: public BreakableStatement {
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_;
......@@ -802,22 +846,8 @@ class SwitchStatement: public BreakableStatement {
// 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(); }
......@@ -829,6 +859,21 @@ class IfStatement: public Statement {
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_;
......@@ -843,7 +888,7 @@ class IfStatement: public 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
......@@ -855,7 +900,6 @@ class TargetCollector: public AstNode {
virtual TargetCollector* AsTargetCollector() { return this; }
ZoneList<Label*>* targets() { return &targets_; }
virtual bool IsInlineable() const;
private:
ZoneList<Label*> targets_;
......@@ -864,12 +908,6 @@ class TargetCollector: public AstNode {
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;
}
......@@ -877,7 +915,12 @@ class TryStatement: public Statement {
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.
......@@ -890,6 +933,15 @@ class TryStatement: public Statement {
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,
......@@ -901,13 +953,6 @@ class TryCatchStatement: public TryStatement {
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_;
......@@ -917,14 +962,16 @@ class TryCatchStatement: public TryStatement {
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_;
......@@ -934,7 +981,11 @@ class TryFinallyStatement: public TryStatement {
class DebuggerStatement: public Statement {
public:
DECLARE_NODE_TYPE(DebuggerStatement)
virtual bool IsInlineable() const;
protected:
template<class> friend class AstNodeFactory;
DebuggerStatement() {}
};
......@@ -942,15 +993,15 @@ class EmptyStatement: public Statement {
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.
......@@ -989,7 +1040,13 @@ class Literal: public Expression {
}
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_;
......@@ -999,15 +1056,6 @@ class Literal: public Expression {
// 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_; }
......@@ -1017,7 +1065,16 @@ class MaterializedLiteral: public Expression {
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_;
......@@ -1044,7 +1101,6 @@ class ObjectLiteral: public MaterializedLiteral {
};
Property(Literal* key, Expression* value);
Property(bool is_getter, FunctionLiteral* value);
Literal* key() { return key_; }
Expression* value() { return value_; }
......@@ -1055,6 +1111,12 @@ class ObjectLiteral: public MaterializedLiteral {
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_;
......@@ -1062,20 +1124,6 @@ class ObjectLiteral: public MaterializedLiteral {
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 {
......@@ -1098,6 +1146,23 @@ class ObjectLiteral: public MaterializedLiteral {
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_;
......@@ -1109,6 +1174,14 @@ class ObjectLiteral: public MaterializedLiteral {
// 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,
......@@ -1117,11 +1190,6 @@ class RegExpLiteral: public MaterializedLiteral {
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_;
......@@ -1131,6 +1199,17 @@ class RegExpLiteral: public MaterializedLiteral {
// 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,
......@@ -1142,14 +1221,6 @@ class ArrayLiteral: public MaterializedLiteral {
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_;
......@@ -1159,21 +1230,12 @@ class ArrayLiteral: public MaterializedLiteral {
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);
}
......@@ -1196,6 +1258,15 @@ class VariableProxy: public Expression {
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_;
......@@ -1209,24 +1280,9 @@ class VariableProxy: public Expression {
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_; }
......@@ -1242,6 +1298,23 @@ class Property: public Expression {
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_;
......@@ -1258,23 +1331,8 @@ class Property: public Expression {
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_; }
......@@ -1299,6 +1357,21 @@ class Call: public Expression {
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_;
......@@ -1317,6 +1390,15 @@ class Call: public Expression {
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,
......@@ -1326,14 +1408,6 @@ class CallNew: public Expression {
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_;
......@@ -1347,6 +1421,16 @@ class CallNew: public Expression {
// 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,
......@@ -1356,15 +1440,6 @@ class CallRuntime: public Expression {
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_;
......@@ -1374,6 +1449,20 @@ class CallRuntime: public Expression {
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,
......@@ -1391,19 +1480,6 @@ class UnaryOperation: public 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_;
......@@ -1418,22 +1494,8 @@ class UnaryOperation: public 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_; }
......@@ -1444,6 +1506,21 @@ class BinaryOperation: public Expression {
// 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_;
......@@ -1457,19 +1534,6 @@ class BinaryOperation: public Expression {
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_; }
......@@ -1485,8 +1549,6 @@ class CountOperation: public Expression {
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_; }
......@@ -1495,6 +1557,22 @@ class CountOperation: public Expression {
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_;
......@@ -1509,20 +1587,6 @@ class CountOperation: public Expression {
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));
}
DECLARE_NODE_TYPE(CompareOperation)
Token::Value op() const { return op_; }
......@@ -1530,8 +1594,6 @@ class CompareOperation: public Expression {
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; }
......@@ -1542,6 +1604,23 @@ class CompareOperation: public Expression {
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_;
......@@ -1555,6 +1634,21 @@ class CompareOperation: public Expression {
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,
......@@ -1568,22 +1662,7 @@ class Conditional: public 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_;
......@@ -1598,16 +1677,8 @@ class Conditional: public Expression {
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;
......@@ -1639,6 +1710,25 @@ class Assignment: public Expression {
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_;
......@@ -1658,14 +1748,16 @@ class Assignment: public Expression {
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_;
......@@ -1681,38 +1773,6 @@ class FunctionLiteral: public Expression {
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_; }
......@@ -1752,18 +1812,61 @@ class FunctionLiteral: public Expression {
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_;
......@@ -1782,17 +1885,20 @@ class FunctionLiteral: public Expression {
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_;
......@@ -1801,9 +1907,12 @@ class SharedFunctionInfoLiteral: public Expression {
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) {}
};
......@@ -2207,6 +2316,342 @@ class AstVisitor BASE_EMBEDDED {
};
// ----------------------------------------------------------------------------
// 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:
......@@ -652,6 +652,8 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
// 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
......@@ -750,6 +752,9 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
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));
}
......
......@@ -2865,7 +2865,8 @@ MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
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);
......
......@@ -4796,8 +4796,8 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
// 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;
}
......@@ -4807,6 +4807,17 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
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.
......@@ -4851,8 +4862,6 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
return false;
}
int count_before = AstNode::Count();
// Parse and allocate variables.
CompilationInfo target_info(target);
if (!ParserApi::Parse(&target_info, kNoParsingFlags) ||
......@@ -4872,11 +4881,17 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
}
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;
}
......@@ -4895,13 +4910,6 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
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.
......
......@@ -362,7 +362,7 @@ typedef List<HeapObject*, PreallocatedStorage> DebugObjectCache;
/* 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) \
......
......@@ -3576,6 +3576,8 @@ SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
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) \
......@@ -3626,6 +3628,9 @@ PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
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
......@@ -3708,6 +3713,9 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
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)
......@@ -3777,16 +3785,6 @@ void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
}
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);
......
......@@ -5203,8 +5203,11 @@ class SharedFunctionInfo: public HeapObject {
// 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(
......@@ -5278,6 +5281,12 @@ class SharedFunctionInfo: public HeapObject {
// 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();
......@@ -5372,12 +5381,10 @@ class SharedFunctionInfo: public HeapObject {
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;
......@@ -5395,8 +5402,11 @@ class SharedFunctionInfo: public HeapObject {
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
......@@ -5408,7 +5418,7 @@ class SharedFunctionInfo: public HeapObject {
// 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;
......@@ -5432,8 +5442,11 @@ class SharedFunctionInfo: public HeapObject {
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
......@@ -5480,6 +5493,8 @@ class SharedFunctionInfo: public HeapObject {
kBoundFunction,
kIsAnonymous,
kNameShouldPrintAsAnonymous,
kDontCrankshaft,
kDontInline,
kCompilerHintsCount // Pseudo entry
};
......
......@@ -481,62 +481,6 @@ class Parser::BlockState BASE_EMBEDDED {
};
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)
......@@ -548,7 +492,8 @@ Parser::FunctionState::FunctionState(Parser* parser,
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);
......@@ -674,8 +619,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
}
if (ok) {
result = new(zone()) FunctionLiteral(
isolate(),
result = factory()->NewFunctionLiteral(
no_name,
top_scope_,
body,
......@@ -685,8 +629,10 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
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();
}
......@@ -1274,7 +1220,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
case Token::SEMICOLON:
Next();
return EmptyStatement();
return factory()->NewEmptyStatement();
case Token::IF:
stmt = ParseIfStatement(labels, ok);
......@@ -1322,7 +1268,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* 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) {
......@@ -1454,9 +1400,9 @@ VariableProxy* Parser::Declare(Handle<String> name,
// 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()) {
......@@ -1564,10 +1510,11 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
// 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));
}
......@@ -1589,7 +1536,7 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) {
// 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();
}
......@@ -1603,7 +1550,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
// (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_);
......@@ -1626,7 +1573,7 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
// '{' 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.
......@@ -1786,7 +1733,7 @@ Block* Parser::ParseVariableDeclarations(
// 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 {
......@@ -1907,7 +1854,7 @@ Block* Parser::ParseVariableDeclarations(
// 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) {
......@@ -1918,9 +1865,7 @@ Block* Parser::ParseVariableDeclarations(
// 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(),
initialize = factory()->NewCallRuntime(
isolate()->factory()->InitializeConstGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
arguments);
......@@ -1928,7 +1873,7 @@ Block* Parser::ParseVariableDeclarations(
// 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
......@@ -1943,15 +1888,13 @@ Block* Parser::ParseVariableDeclarations(
// 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(),
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
......@@ -1964,8 +1907,8 @@ Block* Parser::ParseVariableDeclarations(
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;
}
......@@ -1976,10 +1919,11 @@ Block* Parser::ParseVariableDeclarations(
// '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();
......@@ -2059,7 +2003,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
// Parsed expression statement.
ExpectSemicolon(CHECK_OK);
return new(zone()) ExpressionStatement(expr);
return factory()->NewExpressionStatement(expr);
}
......@@ -2077,10 +2021,9 @@ IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
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);
}
......@@ -2110,7 +2053,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
return NULL;
}
ExpectSemicolon(CHECK_OK);
return new(zone()) ContinueStatement(target);
return factory()->NewContinueStatement(target);
}
......@@ -2129,7 +2072,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
// 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);
......@@ -2146,7 +2089,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
return NULL;
}
ExpectSemicolon(CHECK_OK);
return new(zone()) BreakStatement(target);
return factory()->NewBreakStatement(target);
}
......@@ -2166,11 +2109,11 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
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
......@@ -2183,7 +2126,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
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;
}
......@@ -2213,7 +2156,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
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);
}
......@@ -2255,7 +2198,7 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
// 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);
......@@ -2291,8 +2234,7 @@ Statement* Parser::ParseThrowStatement(bool* 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));
}
......@@ -2379,13 +2321,10 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
// 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.
}
......@@ -2395,17 +2334,12 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
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());
}
......@@ -2420,7 +2354,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
// 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);
......@@ -2451,7 +2385,7 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* 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);
......@@ -2486,8 +2420,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* 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);
......@@ -2496,7 +2430,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* 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;
......@@ -2534,9 +2468,9 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
// 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);
......@@ -2544,14 +2478,11 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* 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);
......@@ -2578,7 +2509,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
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);
......@@ -2595,13 +2526,13 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* 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.
......@@ -2616,7 +2547,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
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);
......@@ -2636,7 +2567,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* 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);
......@@ -2660,8 +2591,8 @@ Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
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;
}
......@@ -2736,7 +2667,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
fni_->Leave();
}
return new(zone()) Assignment(isolate(), op, expression, right, pos);
return factory()->NewAssignment(op, expression, right, pos);
}
......@@ -2758,8 +2689,8 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
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);
}
......@@ -2790,41 +2721,47 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
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:
......@@ -2843,15 +2780,15 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
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);
}
}
}
......@@ -2884,7 +2821,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
// 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();
......@@ -2892,9 +2829,9 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
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;
}
......@@ -2911,7 +2848,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
}
return new(zone()) UnaryOperation(isolate(), op, expression, position);
return factory()->NewUnaryOperation(op, expression, position);
} else if (Token::IsCountOp(op)) {
op = Next();
......@@ -2933,8 +2870,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
MarkAsLValue(expression);
int position = scanner().location().beg_pos;
return new(zone()) CountOperation(isolate(),
op,
return factory()->NewCountOperation(op,
true /* prefix */,
expression,
position);
......@@ -2971,8 +2907,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
Token::Value next = Next();
int position = scanner().location().beg_pos;
expression =
new(zone()) CountOperation(isolate(),
next,
factory()->NewCountOperation(next,
false /* postfix */,
expression,
position);
......@@ -2998,7 +2933,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
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;
}
......@@ -3031,7 +2966,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
callee->IsVariable(isolate()->factory()->eval_symbol())) {
top_scope_->DeclarationScope()->RecordEvalCall();
}
result = NewCall(result, args, pos);
result = factory()->NewCall(result, args, pos);
break;
}
......@@ -3039,10 +2974,8 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
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;
}
......@@ -3078,10 +3011,8 @@ Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
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;
}
......@@ -3133,7 +3064,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
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());
......@@ -3149,10 +3080,8 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
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;
}
......@@ -3161,7 +3090,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
// 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:
......@@ -3180,7 +3109,7 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
Expect(Token::DEBUGGER, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return new(zone()) DebuggerStatement();
return factory()->NewDebuggerStatement();
}
......@@ -3245,33 +3174,31 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
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;
}
......@@ -3281,14 +3208,14 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
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;
}
......@@ -3482,8 +3409,8 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
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);
}
......@@ -3760,9 +3687,7 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
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;
......@@ -3827,7 +3752,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
}
// 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: {
......@@ -3836,10 +3761,10 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
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: {
......@@ -3848,14 +3773,14 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
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();
......@@ -3910,8 +3835,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
&is_simple,
&fast_elements,
&depth);
return new(zone()) ObjectLiteral(isolate(),
constant_properties,
return factory()->NewObjectLiteral(constant_properties,
properties,
literal_index,
is_simple,
......@@ -3936,8 +3860,7 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
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);
}
......@@ -3968,7 +3891,7 @@ ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
class SingletonLogger : public ParserRecorder {
public:
SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
~SingletonLogger() { }
virtual ~SingletonLogger() { }
void Reset() { has_error_ = false; }
......@@ -4089,6 +4012,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
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);
......@@ -4151,7 +4075,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> 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.
......@@ -4238,13 +4163,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
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,
body->Add(factory()->NewExpressionStatement(
factory()->NewAssignment(fvar_init_op,
fproxy,
new(zone()) ThisFunction(isolate()),
factory()->NewThisFunction(),
RelocInfo::kNoPosition)));
}
ParseSourceElements(body, Token::RBRACE, CHECK_OK);
......@@ -4306,6 +4231,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
scope->end_position(),
CHECK_OK);
}
ast_properties = *factory()->visitor()->ast_properties();
}
if (is_extended_mode()) {
......@@ -4313,8 +4239,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
}
FunctionLiteral* function_literal =
new(zone()) FunctionLiteral(isolate(),
function_name,
factory()->NewFunctionLiteral(function_name,
scope,
body,
materialized_literal_count,
......@@ -4323,9 +4248,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
only_simple_this_property_assignments,
this_property_assignments,
num_parameters,
has_duplicate_parameters,
type,
has_duplicate_parameters);
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;
......@@ -4395,7 +4322,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
}
// 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);
}
......@@ -4451,17 +4378,12 @@ void Parser::ExpectSemicolon(bool* ok) {
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());
}
......@@ -4639,11 +4561,6 @@ void Parser::RegisterTargetUse(Label* target, Target* stop) {
}
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));
......@@ -4687,15 +4604,11 @@ Expression* Parser::NewThrowError(Handle<String> constructor,
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);
}
// ----------------------------------------------------------------------------
......@@ -5667,7 +5580,7 @@ bool ParserApi::Parse(CompilationInfo* info, int parsing_flags) {
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:
......@@ -435,9 +435,8 @@ class Parser {
v8::Extension* extension,
ScriptDataImpl* pre_data);
virtual ~Parser() {
if (reusable_preparser_ != NULL) {
delete reusable_preparser_;
}
reusable_preparser_ = NULL;
}
// Returns NULL if parsing failed.
......@@ -477,7 +476,69 @@ class Parser {
};
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,
......@@ -651,7 +712,6 @@ class Parser {
// Get odd-ball literals.
Literal* GetLiteralUndefined();
Literal* GetLiteralTheHole();
Literal* GetLiteralNumber(double value);
Handle<String> ParseIdentifier(bool* ok);
Handle<String> ParseIdentifierOrStrictReservedWord(
......@@ -699,31 +759,12 @@ class Parser {
// 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);
......@@ -746,6 +787,10 @@ class Parser {
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:
......@@ -42,12 +42,18 @@ class Processor: public AstVisitor {
: 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_;
......@@ -64,15 +70,13 @@ class Processor: public AstVisitor {
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.
......@@ -237,8 +241,6 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
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
......@@ -246,10 +248,11 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
// 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:
......@@ -272,8 +272,11 @@ bool Scope::Analyze(CompilationInfo* info) {
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()
......@@ -415,7 +418,8 @@ Variable* Scope::LocalLookup(Handle<String> name) {
}
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()) {
......@@ -423,7 +427,7 @@ Variable* Scope::LookupFunctionVar(Handle<String> name) {
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 {
......@@ -443,15 +447,6 @@ Variable* Scope::Lookup(Handle<String> name) {
}
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());
......@@ -489,18 +484,6 @@ Variable* Scope::DeclareGlobal(Handle<String> name) {
}
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.
......@@ -623,7 +606,8 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
}
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) {
......@@ -634,7 +618,7 @@ void Scope::AllocateVariables(Scope* global_scope) {
PropagateScopeInfo(outer_scope_calls_non_strict_eval);
// 2) Resolve variables.
ResolveVariablesRecursively(global_scope);
ResolveVariablesRecursively(global_scope, factory);
// 3) Allocate variables.
AllocateVariablesRecursively();
......@@ -897,7 +881,8 @@ Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
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);
......@@ -914,11 +899,11 @@ Variable* Scope::LookupRecursive(Handle<String> 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();
}
......@@ -951,7 +936,8 @@ Variable* Scope::LookupRecursive(Handle<String> name,
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
......@@ -960,7 +946,7 @@ void Scope::ResolveVariable(Scope* global_scope,
// 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.
......@@ -1001,17 +987,19 @@ void Scope::ResolveVariable(Scope* global_scope,
}
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:
......@@ -115,7 +115,8 @@ class Scope: public ZoneObject {
// 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.
......@@ -124,7 +125,16 @@ class Scope: public ZoneObject {
// 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
......@@ -144,8 +154,18 @@ class Scope: public ZoneObject {
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
......@@ -332,7 +352,8 @@ class Scope: public ZoneObject {
// 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_; }
......@@ -519,10 +540,13 @@ class Scope: public ZoneObject {
// 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:
......@@ -40,7 +40,8 @@ TEST(List) {
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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment