Index: src/mips/full-codegen-mips.cc |
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc |
index 2afad13ecdc90a202fe3075bef4dbe140a925bd2..479b8bcb361efe11c077dbb609a48b0ca06d8874 100644 |
--- a/src/mips/full-codegen-mips.cc |
+++ b/src/mips/full-codegen-mips.cc |
@@ -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. |