Index: src/ia32/full-codegen-ia32.cc |
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc |
index b42ce95f8db220aaf55491600d95c2e9477a0905..4e2509b6a6bac293a9e084c18af0c7ffc65aa9f7 100644 |
--- a/src/ia32/full-codegen-ia32.cc |
+++ b/src/ia32/full-codegen-ia32.cc |
@@ -266,11 +266,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()); |
} |
@@ -750,15 +750,30 @@ 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. |
+ __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); |
+ __ cmp(ebx, isolate()->factory()->with_context_map()); |
+ __ Check(not_equal, "Declaration in with context."); |
+ __ cmp(ebx, isolate()->factory()->catch_context_map()); |
+ __ Check(not_equal, "Declaration in catch context."); |
+ } |
+} |
+ |
+ |
+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_; |
@@ -766,44 +781,17 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, |
case Variable::PARAMETER: |
case Variable::LOCAL: |
- if (function != NULL) { |
- Comment cmnt(masm_, "[ Declaration"); |
- VisitForAccumulatorValue(function); |
- __ mov(StackOperand(variable), result_register()); |
- } else if (binding_needs_init) { |
- Comment cmnt(masm_, "[ Declaration"); |
+ if (hole_init) { |
+ Comment cmnt(masm_, "[ VariableDeclaration"); |
__ mov(StackOperand(variable), |
Immediate(isolate()->factory()->the_hole_value())); |
} |
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. |
- __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset)); |
- __ cmp(ebx, isolate()->factory()->with_context_map()); |
- __ Check(not_equal, "Declaration in with context."); |
- __ cmp(ebx, isolate()->factory()->catch_context_map()); |
- __ Check(not_equal, "Declaration in catch context."); |
- } |
- if (function != NULL) { |
- Comment cmnt(masm_, "[ Declaration"); |
- VisitForAccumulatorValue(function); |
- __ mov(ContextOperand(esi, variable->index()), result_register()); |
- // We know that we have written a function, which is not a smi. |
- __ RecordWriteContextSlot(esi, |
- Context::SlotOffset(variable->index()), |
- result_register(), |
- ecx, |
- 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); |
__ mov(ContextOperand(esi, variable->index()), |
Immediate(isolate()->factory()->the_hole_value())); |
// No write barrier since the hole value is in old space. |
@@ -812,14 +800,12 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, |
break; |
case Variable::LOOKUP: { |
- Comment cmnt(masm_, "[ Declaration"); |
+ Comment cmnt(masm_, "[ VariableDeclaration"); |
__ push(esi); |
__ push(Immediate(variable->name())); |
- // Declaration nodes are always introduced in one of four modes. |
- ASSERT(mode == VAR || |
- mode == CONST || |
- mode == CONST_HARMONY || |
- mode == LET); |
+ // VariableDeclaration nodes are always introduced in one of four modes. |
+ ASSERT(mode == VAR || mode == LET || |
+ mode == CONST || mode == CONST_HARMONY); |
PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) |
? READ_ONLY : NONE; |
__ push(Immediate(Smi::FromInt(attr))); |
@@ -827,9 +813,7 @@ 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) { |
- VisitForStackValue(function); |
- } else if (binding_needs_init) { |
+ if (hole_init) { |
__ push(Immediate(isolate()->factory()->the_hole_value())); |
} else { |
__ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. |
@@ -841,6 +825,104 @@ 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()); |
+ __ mov(StackOperand(variable), result_register()); |
+ break; |
+ } |
+ |
+ case Variable::CONTEXT: { |
+ Comment cmnt(masm_, "[ FunctionDeclaration"); |
+ EmitDebugCheckDeclarationContext(variable); |
+ VisitForAccumulatorValue(declaration->fun()); |
+ __ mov(ContextOperand(esi, variable->index()), result_register()); |
+ // We know that we have written a function, which is not a smi. |
+ __ RecordWriteContextSlot(esi, |
+ Context::SlotOffset(variable->index()), |
+ result_register(), |
+ ecx, |
+ kDontSaveFPRegs, |
+ EMIT_REMEMBERED_SET, |
+ OMIT_SMI_CHECK); |
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
+ break; |
+ } |
+ |
+ case Variable::LOOKUP: { |
+ Comment cmnt(masm_, "[ FunctionDeclaration"); |
+ __ push(esi); |
+ __ push(Immediate(variable->name())); |
+ __ push(Immediate(Smi::FromInt(NONE))); |
+ 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. |
__ push(esi); // The context is the first argument. |