Commit 42b77f31 authored by rossberg@chromium.org's avatar rossberg@chromium.org

MIPS: Refactoring of code generation for declarations, in preparation for modules.

Port r11331 (bd7843a0)

Original commit message:
Refactoring of code generation for declarations, in preparation for modules.

Do proper dispatch on declaration type instead of mingling together
different code generation paths. Once we add more declaration forms,
this is more scalable.

BUG=
TEST=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11372 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 18af012b
...@@ -275,11 +275,11 @@ void FullCodeGenerator::Generate() { ...@@ -275,11 +275,11 @@ void FullCodeGenerator::Generate() {
// For named function expressions, declare the function name as a // For named function expressions, declare the function name as a
// constant. // constant.
if (scope()->is_function_scope() && scope()->function() != NULL) { if (scope()->is_function_scope() && scope()->function() != NULL) {
VariableProxy* proxy = scope()->function(); VariableDeclaration* function = scope()->function();
ASSERT(proxy->var()->mode() == CONST || ASSERT(function->proxy()->var()->mode() == CONST ||
proxy->var()->mode() == CONST_HARMONY); function->proxy()->var()->mode() == CONST_HARMONY);
ASSERT(proxy->var()->location() != Variable::UNALLOCATED); ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
EmitDeclaration(proxy, proxy->var()->mode(), NULL); VisitVariableDeclaration(function);
} }
VisitDeclarations(scope()->declarations()); VisitDeclarations(scope()->declarations());
} }
...@@ -789,15 +789,32 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, ...@@ -789,15 +789,32 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
} }
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
VariableMode mode, // The variable in the declaration always resides in the current function
FunctionLiteral* function) { // context.
ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
if (FLAG_debug_code) {
// Check that we're not inside a with or catch context.
__ lw(a1, FieldMemOperand(cp, HeapObject::kMapOffset));
__ LoadRoot(t0, Heap::kWithContextMapRootIndex);
__ Check(ne, "Declaration in with context.",
a1, Operand(t0));
__ LoadRoot(t0, Heap::kCatchContextMapRootIndex);
__ Check(ne, "Declaration in catch context.",
a1, Operand(t0));
}
}
void FullCodeGenerator::VisitVariableDeclaration(
VariableDeclaration* declaration) {
// If it was not possible to allocate the variable at compile time, we // 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 // need to "declare" it at runtime to make sure it actually exists in the
// local context. // local context.
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var(); Variable* variable = proxy->var();
bool binding_needs_init = (function == NULL) && bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
(mode == CONST || mode == CONST_HARMONY || mode == LET);
switch (variable->location()) { switch (variable->location()) {
case Variable::UNALLOCATED: case Variable::UNALLOCATED:
++global_count_; ++global_count_;
...@@ -805,48 +822,17 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, ...@@ -805,48 +822,17 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
case Variable::PARAMETER: case Variable::PARAMETER:
case Variable::LOCAL: case Variable::LOCAL:
if (function != NULL) { if (hole_init) {
Comment cmnt(masm_, "[ Declaration"); Comment cmnt(masm_, "[ VariableDeclaration");
VisitForAccumulatorValue(function);
__ sw(result_register(), StackOperand(variable));
} else if (binding_needs_init) {
Comment cmnt(masm_, "[ Declaration");
__ LoadRoot(t0, Heap::kTheHoleValueRootIndex); __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
__ sw(t0, StackOperand(variable)); __ sw(t0, StackOperand(variable));
} }
break; break;
case Variable::CONTEXT: case Variable::CONTEXT:
// The variable in the decl always resides in the current function if (hole_init) {
// context. Comment cmnt(masm_, "[ VariableDeclaration");
ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); EmitDebugCheckDeclarationContext(variable);
if (FLAG_debug_code) {
// Check that we're not inside a with or catch context.
__ lw(a1, FieldMemOperand(cp, HeapObject::kMapOffset));
__ LoadRoot(t0, Heap::kWithContextMapRootIndex);
__ Check(ne, "Declaration in with context.",
a1, Operand(t0));
__ LoadRoot(t0, Heap::kCatchContextMapRootIndex);
__ Check(ne, "Declaration in catch context.",
a1, Operand(t0));
}
if (function != NULL) {
Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
__ sw(result_register(), ContextOperand(cp, variable->index()));
int offset = Context::SlotOffset(variable->index());
// We know that we have written a function, which is not a smi.
__ RecordWriteContextSlot(cp,
offset,
result_register(),
a2,
kRAHasBeenSaved,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
} else if (binding_needs_init) {
Comment cmnt(masm_, "[ Declaration");
__ LoadRoot(at, Heap::kTheHoleValueRootIndex); __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ sw(at, ContextOperand(cp, variable->index())); __ sw(at, ContextOperand(cp, variable->index()));
// No write barrier since the_hole_value is in old space. // No write barrier since the_hole_value is in old space.
...@@ -855,13 +841,11 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, ...@@ -855,13 +841,11 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
break; break;
case Variable::LOOKUP: { case Variable::LOOKUP: {
Comment cmnt(masm_, "[ Declaration"); Comment cmnt(masm_, "[ VariableDeclaration");
__ li(a2, Operand(variable->name())); __ li(a2, Operand(variable->name()));
// Declaration nodes are always introduced in one of four modes. // Declaration nodes are always introduced in one of four modes.
ASSERT(mode == VAR || ASSERT(mode == VAR || mode == LET ||
mode == CONST || mode == CONST || mode == CONST_HARMONY);
mode == CONST_HARMONY ||
mode == LET);
PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY)
? READ_ONLY : NONE; ? READ_ONLY : NONE;
__ li(a1, Operand(Smi::FromInt(attr))); __ li(a1, Operand(Smi::FromInt(attr)));
...@@ -869,11 +853,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, ...@@ -869,11 +853,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
// Note: For variables we must not push an initial value (such as // Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we // 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value. // must not destroy the current value.
if (function != NULL) { if (hole_init) {
__ Push(cp, a2, a1);
// Push initial value for function declaration.
VisitForStackValue(function);
} else if (binding_needs_init) {
__ LoadRoot(a0, Heap::kTheHoleValueRootIndex); __ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
__ Push(cp, a2, a1, a0); __ Push(cp, a2, a1, a0);
} else { } else {
...@@ -888,6 +868,107 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, ...@@ -888,6 +868,107 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
} }
void FullCodeGenerator::VisitFunctionDeclaration(
FunctionDeclaration* declaration) {
VariableProxy* proxy = declaration->proxy();
Variable* variable = proxy->var();
switch (variable->location()) {
case Variable::UNALLOCATED:
++global_count_;
break;
case Variable::PARAMETER:
case Variable::LOCAL: {
Comment cmnt(masm_, "[ FunctionDeclaration");
VisitForAccumulatorValue(declaration->fun());
__ sw(result_register(), StackOperand(variable));
break;
}
case Variable::CONTEXT: {
Comment cmnt(masm_, "[ FunctionDeclaration");
EmitDebugCheckDeclarationContext(variable);
VisitForAccumulatorValue(declaration->fun());
__ sw(result_register(), ContextOperand(cp, variable->index()));
int offset = Context::SlotOffset(variable->index());
// We know that we have written a function, which is not a smi.
__ RecordWriteContextSlot(cp,
offset,
result_register(),
a2,
kRAHasBeenSaved,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
case Variable::LOOKUP: {
Comment cmnt(masm_, "[ FunctionDeclaration");
__ li(a2, Operand(variable->name()));
__ li(a1, Operand(Smi::FromInt(NONE)));
__ Push(cp, a2, a1);
// Push initial value for function declaration.
VisitForStackValue(declaration->fun());
__ CallRuntime(Runtime::kDeclareContextSlot, 4);
break;
}
}
}
void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
VariableProxy* proxy = declaration->proxy();
Variable* variable = proxy->var();
switch (variable->location()) {
case Variable::UNALLOCATED:
++global_count_;
break;
case Variable::CONTEXT: {
Comment cmnt(masm_, "[ ModuleDeclaration");
EmitDebugCheckDeclarationContext(variable);
// TODO(rossberg): initialize module instance object
break;
}
case Variable::PARAMETER:
case Variable::LOCAL:
case Variable::LOOKUP:
UNREACHABLE();
}
}
void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
VariableProxy* proxy = declaration->proxy();
Variable* variable = proxy->var();
switch (variable->location()) {
case Variable::UNALLOCATED:
++global_count_;
break;
case Variable::CONTEXT: {
Comment cmnt(masm_, "[ ImportDeclaration");
EmitDebugCheckDeclarationContext(variable);
// TODO(rossberg)
break;
}
case Variable::PARAMETER:
case Variable::LOCAL:
case Variable::LOOKUP:
UNREACHABLE();
}
}
void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
// TODO(rossberg)
}
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals. // Call the runtime to declare the globals.
// The context is the first argument. // 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