Commit 751508d6 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Split AST Declaration class, in preparation for new module declaration forms.

Turns Declaration into an abstract class, and introduces VariableDeclaration as a concrete subclass.

R=kmillikin@chromium.org
BUG=
TEST=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10662 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d7934bd4
......@@ -286,11 +286,11 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
// For named function expressions, declare the function name as a
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
int ignored = 0;
VariableProxy* proxy = scope()->function();
ASSERT(proxy->var()->mode() == CONST ||
proxy->var()->mode() == CONST_HARMONY);
EmitDeclaration(proxy, proxy->var()->mode(), NULL, &ignored);
ASSERT(proxy->var()->location() != Variable::UNALLOCATED);
EmitDeclaration(proxy, proxy->var()->mode(), NULL);
}
VisitDeclarations(scope()->declarations());
}
......@@ -727,8 +727,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* function,
int* global_count) {
FunctionLiteral* function) {
// If it was not possible to allocate the variable at compile time, we
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
......@@ -737,7 +736,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
(mode == CONST || mode == CONST_HARMONY || mode == LET);
switch (variable->location()) {
case Variable::UNALLOCATED:
++(*global_count);
++global_count_;
break;
case Variable::PARAMETER:
......@@ -822,9 +821,6 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
}
void FullCodeGenerator::VisitDeclaration(Declaration* decl) { }
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
// The context is the first argument.
......
......@@ -414,7 +414,11 @@ bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
// Inlining support
bool Declaration::IsInlineable() const {
return proxy()->var()->IsStackAllocated() && fun() == NULL;
return proxy()->var()->IsStackAllocated();
}
bool VariableDeclaration::IsInlineable() const {
return Declaration::IsInlineable() && fun() == NULL;
}
......@@ -990,7 +994,7 @@ CaseClause::CaseClause(Isolate* isolate,
increase_node_count(); \
}
INCREASE_NODE_COUNT(Declaration)
INCREASE_NODE_COUNT(VariableDeclaration)
INCREASE_NODE_COUNT(Block)
INCREASE_NODE_COUNT(ExpressionStatement)
INCREASE_NODE_COUNT(EmptyStatement)
......
......@@ -59,6 +59,9 @@ namespace internal {
// Nodes of the abstract syntax tree. Only concrete classes are
// enumerated here.
#define DECLARATION_NODE_LIST(V) \
V(VariableDeclaration) \
#define STATEMENT_NODE_LIST(V) \
V(Block) \
V(ExpressionStatement) \
......@@ -99,7 +102,7 @@ namespace internal {
V(ThisFunction)
#define AST_NODE_LIST(V) \
V(Declaration) \
DECLARATION_NODE_LIST(V) \
STATEMENT_NODE_LIST(V) \
EXPRESSION_NODE_LIST(V)
......@@ -107,6 +110,7 @@ namespace internal {
class AstConstructionVisitor;
template<class> class AstNodeFactory;
class AstVisitor;
class Declaration;
class BreakableStatement;
class Expression;
class IterationStatement;
......@@ -202,6 +206,7 @@ class AstNode: public ZoneObject {
AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
#undef DECLARE_NODE_FUNCTIONS
virtual Declaration* AsDeclaration() { return NULL; }
virtual Statement* AsStatement() { return NULL; }
virtual Expression* AsExpression() { return NULL; }
virtual TargetCollector* AsTargetCollector() { return NULL; }
......@@ -433,43 +438,63 @@ 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_; }
virtual bool IsInlineable() const;
protected:
template<class> friend class AstNodeFactory;
virtual Declaration* AsDeclaration() { return this; }
virtual VariableDeclaration* AsVariableDeclaration() { return NULL; }
protected:
Declaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* fun,
Scope* scope)
: proxy_(proxy),
mode_(mode),
fun_(fun),
scope_(scope) {
ASSERT(mode == VAR ||
mode == CONST ||
mode == CONST_HARMONY ||
mode == LET);
// At the moment there are no "const functions"'s in JavaScript...
ASSERT(fun == NULL || mode == VAR || mode == LET);
}
private:
VariableProxy* proxy_;
VariableMode mode_;
FunctionLiteral* fun_;
// Nested scope from which the declaration originated.
Scope* scope_;
};
class VariableDeclaration: public Declaration {
public:
DECLARE_NODE_TYPE(VariableDeclaration)
virtual VariableDeclaration* AsVariableDeclaration() { return this; }
FunctionLiteral* fun() const { return fun_; } // may be NULL
virtual bool IsInlineable() const;
protected:
template<class> friend class AstNodeFactory;
VariableDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* fun,
Scope* scope)
: Declaration(proxy, mode, scope),
fun_(fun) {
// At the moment there are no "const functions"'s in JavaScript...
ASSERT(fun == NULL || mode == VAR || mode == LET);
}
private:
FunctionLiteral* fun_;
};
class IterationStatement: public BreakableStatement {
public:
// Type testing & conversion.
......@@ -2366,6 +2391,15 @@ class AstNodeFactory BASE_EMBEDDED {
visitor_.Visit##NodeType((node)); \
return node;
VariableDeclaration* NewVariableDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* fun,
Scope* scope) {
VariableDeclaration* decl =
new(zone_) VariableDeclaration(proxy, mode, fun, scope);
VISIT_AND_RETURN(VariableDeclaration, decl)
}
Block* NewBlock(ZoneStringList* labels,
int capacity,
bool is_initializer_block) {
......@@ -2374,14 +2408,6 @@ class AstNodeFactory BASE_EMBEDDED {
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); \
......
......@@ -51,7 +51,8 @@ void BreakableStatementChecker::Check(Expression* expr) {
}
void BreakableStatementChecker::VisitDeclaration(Declaration* decl) {
void BreakableStatementChecker::VisitVariableDeclaration(
VariableDeclaration* decl) {
}
......@@ -526,41 +527,47 @@ void FullCodeGenerator::DoTest(const TestContext* context) {
}
void FullCodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
}
void FullCodeGenerator::VisitDeclarations(
ZoneList<Declaration*>* declarations) {
int length = declarations->length();
int global_count = 0;
for (int i = 0; i < length; i++) {
Declaration* decl = declarations->at(i);
EmitDeclaration(decl->proxy(), decl->mode(), decl->fun(), &global_count);
}
int save_global_count = global_count_;
global_count_ = 0;
AstVisitor::VisitDeclarations(declarations);
// Batch declare global functions and variables.
if (global_count > 0) {
if (global_count_ > 0) {
Handle<FixedArray> array =
isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
isolate()->factory()->NewFixedArray(2 * global_count_, TENURED);
int length = declarations->length();
for (int j = 0, i = 0; i < length; i++) {
Declaration* decl = declarations->at(i);
Variable* var = decl->proxy()->var();
if (var->IsUnallocated()) {
array->set(j++, *(var->name()));
if (decl->fun() == NULL) {
if (var->binding_needs_init()) {
// In case this binding needs initialization use the hole.
array->set_the_hole(j++);
VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
if (decl != NULL) {
Variable* var = decl->proxy()->var();
if (var->IsUnallocated()) {
array->set(j++, *(var->name()));
if (decl->fun() == NULL) {
if (var->binding_needs_init()) {
// In case this binding needs initialization use the hole.
array->set_the_hole(j++);
} else {
array->set_undefined(j++);
}
} else {
array->set_undefined(j++);
Handle<SharedFunctionInfo> function =
Compiler::BuildFunctionInfo(decl->fun(), script());
// Check for stack-overflow exception.
if (function.is_null()) {
SetStackOverflow();
return;
}
array->set(j++, *function);
}
} else {
Handle<SharedFunctionInfo> function =
Compiler::BuildFunctionInfo(decl->fun(), script());
// Check for stack-overflow exception.
if (function.is_null()) {
SetStackOverflow();
return;
}
array->set(j++, *function);
}
}
}
......@@ -568,6 +575,8 @@ void FullCodeGenerator::VisitDeclarations(
// declaration the global functions and variables.
DeclareGlobals(array);
}
global_count_ = save_global_count;
}
......
......@@ -83,6 +83,7 @@ class FullCodeGenerator: public AstVisitor {
scope_(NULL),
nesting_stack_(NULL),
loop_depth_(0),
global_count_(0),
context_(NULL),
bailout_entries_(0),
stack_checks_(2), // There's always at least one.
......@@ -416,10 +417,10 @@ class FullCodeGenerator: public AstVisitor {
// Platform-specific code for a variable, constant, or function
// declaration. Functions have an initial value.
// Increments global_count_ for unallocated variables.
void EmitDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* function,
int* global_count);
FunctionLiteral* function);
// Platform-specific code for checking the stack limit at the back edge of
// a loop.
......@@ -767,6 +768,7 @@ class FullCodeGenerator: public AstVisitor {
Label return_label_;
NestedStatement* nesting_stack_;
int loop_depth_;
int global_count_;
const ExpressionContext* context_;
ZoneList<BailoutEntry> bailout_entries_;
ZoneList<BailoutEntry> stack_checks_;
......
......@@ -2443,7 +2443,7 @@ HGraph* HGraphBuilder::CreateGraph() {
// Handle implicit declaration of the function name in named function
// expressions before other declarations.
if (scope->is_function_scope() && scope->function() != NULL) {
HandleDeclaration(scope->function(), CONST, NULL);
HandleVariableDeclaration(scope->function(), CONST, NULL);
}
VisitDeclarations(scope->declarations());
AddSimulate(AstNode::kDeclarationsId);
......@@ -6540,14 +6540,14 @@ void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
}
void HGraphBuilder::VisitDeclaration(Declaration* decl) {
HandleDeclaration(decl->proxy(), decl->mode(), decl->fun());
void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
HandleVariableDeclaration(decl->proxy(), decl->mode(), decl->fun());
}
void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* function) {
void HGraphBuilder::HandleVariableDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* function) {
Variable* var = proxy->var();
bool binding_needs_init =
(mode == CONST || mode == CONST_HARMONY || mode == LET);
......
......@@ -839,9 +839,9 @@ class HGraphBuilder: public AstVisitor {
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
#undef INLINE_FUNCTION_GENERATOR_DECLARATION
void HandleDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* function);
void HandleVariableDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* function);
void VisitDelete(UnaryOperation* expr);
void VisitVoid(UnaryOperation* expr);
......
......@@ -281,11 +281,11 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
// For named function expressions, declare the function name as a
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
int ignored = 0;
VariableProxy* proxy = scope()->function();
ASSERT(proxy->var()->mode() == CONST ||
proxy->var()->mode() == CONST_HARMONY);
EmitDeclaration(proxy, proxy->var()->mode(), NULL, &ignored);
ASSERT(proxy->var()->location() != Variable::UNALLOCATED);
EmitDeclaration(proxy, proxy->var()->mode(), NULL);
}
VisitDeclarations(scope()->declarations());
}
......@@ -701,8 +701,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* function,
int* global_count) {
FunctionLiteral* function) {
// If it was not possible to allocate the variable at compile time, we
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
......@@ -711,7 +710,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
(mode == CONST || mode == CONST_HARMONY || mode == LET);
switch (variable->location()) {
case Variable::UNALLOCATED:
++(*global_count);
++global_count_;
break;
case Variable::PARAMETER:
......@@ -791,9 +790,6 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
}
void FullCodeGenerator::VisitDeclaration(Declaration* decl) { }
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
__ push(esi); // The context is the first argument.
......
......@@ -1406,7 +1406,7 @@ VariableProxy* Parser::Declare(Handle<String> name,
VariableProxy* proxy = declaration_scope->NewUnresolved(
factory(), name, scanner().location().beg_pos);
declaration_scope->AddDeclaration(
factory()->NewDeclaration(proxy, mode, fun, top_scope_));
factory()->NewVariableDeclaration(proxy, mode, fun, top_scope_));
if ((mode == CONST || mode == CONST_HARMONY) &&
declaration_scope->is_global_scope()) {
......@@ -1627,8 +1627,8 @@ bool Parser::IsEvalOrArguments(Handle<String> string) {
// If the variable declaration declares exactly one non-const
// variable, then *var is set to that variable. In all other cases,
// *var is untouched; in particular, it is the caller's responsibility
// variable, then *out is set to that variable. In all other cases,
// *out is untouched; in particular, it is the caller's responsibility
// to initialize it properly. This mechanism is used for the parsing
// of 'for-in' loops.
Block* Parser::ParseVariableDeclarations(
......
......@@ -58,7 +58,7 @@ void PrettyPrinter::VisitBlock(Block* node) {
}
void PrettyPrinter::VisitDeclaration(Declaration* node) {
void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
Print("var ");
PrintLiteral(node->proxy()->name(), false);
if (node->fun() != NULL) {
......@@ -711,7 +711,7 @@ void AstPrinter::VisitBlock(Block* node) {
}
void AstPrinter::VisitDeclaration(Declaration* node) {
void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
if (node->fun() == NULL) {
// var or const declarations
PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
......
......@@ -209,7 +209,7 @@ void Processor::VisitWithStatement(WithStatement* node) {
// Do nothing:
void Processor::VisitDeclaration(Declaration* node) {}
void Processor::VisitVariableDeclaration(VariableDeclaration* node) {}
void Processor::VisitEmptyStatement(EmptyStatement* node) {}
void Processor::VisitReturnStatement(ReturnStatement* node) {}
void Processor::VisitDebuggerStatement(DebuggerStatement* node) {}
......
......@@ -277,11 +277,11 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
// For named function expressions, declare the function name as a
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
int ignored = 0;
VariableProxy* proxy = scope()->function();
ASSERT(proxy->var()->mode() == CONST ||
proxy->var()->mode() == CONST_HARMONY);
EmitDeclaration(proxy, proxy->var()->mode(), NULL, &ignored);
ASSERT(proxy->var()->location() != Variable::UNALLOCATED);
EmitDeclaration(proxy, proxy->var()->mode(), NULL);
}
VisitDeclarations(scope()->declarations());
}
......@@ -699,8 +699,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* function,
int* global_count) {
FunctionLiteral* function) {
// If it was not possible to allocate the variable at compile time, we
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
......@@ -709,7 +708,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
(mode == CONST || mode == CONST_HARMONY || mode == LET);
switch (variable->location()) {
case Variable::UNALLOCATED:
++(*global_count);
++global_count_;
break;
case Variable::PARAMETER:
......@@ -790,9 +789,6 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
}
void FullCodeGenerator::VisitDeclaration(Declaration* decl) { }
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
__ push(rsi); // The context is the first argument.
......
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