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() {
// For named function expressions, declare the function name as a
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
VariableProxy* proxy = scope()->function();
ASSERT(proxy->var()->mode() == CONST ||
proxy->var()->mode() == CONST_HARMONY);
ASSERT(proxy->var()->location() != Variable::UNALLOCATED);
EmitDeclaration(proxy, proxy->var()->mode(), NULL);
VariableDeclaration* function = scope()->function();
ASSERT(function->proxy()->var()->mode() == CONST ||
function->proxy()->var()->mode() == CONST_HARMONY);
ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
VisitVariableDeclaration(function);
}
VisitDeclarations(scope()->declarations());
}
......@@ -789,15 +789,32 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
}
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* function) {
void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
// The variable in the declaration always resides in the current 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
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var();
bool binding_needs_init = (function == NULL) &&
(mode == CONST || mode == CONST_HARMONY || mode == LET);
bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
switch (variable->location()) {
case Variable::UNALLOCATED:
++global_count_;
......@@ -805,48 +822,17 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
case Variable::PARAMETER:
case Variable::LOCAL:
if (function != NULL) {
Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
__ sw(result_register(), StackOperand(variable));
} else if (binding_needs_init) {
Comment cmnt(masm_, "[ Declaration");
__ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
__ sw(t0, StackOperand(variable));
if (hole_init) {
Comment cmnt(masm_, "[ VariableDeclaration");
__ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
__ sw(t0, StackOperand(variable));
}
break;
case Variable::CONTEXT:
// The variable in the decl always resides in the current 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));
}
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");
if (hole_init) {
Comment cmnt(masm_, "[ VariableDeclaration");
EmitDebugCheckDeclarationContext(variable);
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ sw(at, ContextOperand(cp, variable->index()));
// No write barrier since the_hole_value is in old space.
......@@ -855,13 +841,11 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
break;
case Variable::LOOKUP: {
Comment cmnt(masm_, "[ Declaration");
Comment cmnt(masm_, "[ VariableDeclaration");
__ li(a2, Operand(variable->name()));
// Declaration nodes are always introduced in one of four modes.
ASSERT(mode == VAR ||
mode == CONST ||
mode == CONST_HARMONY ||
mode == LET);
ASSERT(mode == VAR || mode == LET ||
mode == CONST || mode == CONST_HARMONY);
PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY)
? READ_ONLY : NONE;
__ li(a1, Operand(Smi::FromInt(attr)));
......@@ -869,13 +853,9 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
// Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value.
if (function != NULL) {
__ Push(cp, a2, a1);
// Push initial value for function declaration.
VisitForStackValue(function);
} else if (binding_needs_init) {
__ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
__ Push(cp, a2, a1, a0);
if (hole_init) {
__ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
__ Push(cp, a2, a1, a0);
} else {
ASSERT(Smi::FromInt(0) == 0);
__ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value.
......@@ -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) {
// Call the runtime to declare the globals.
// 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