Index: src/x64/full-codegen-x64.cc |
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc |
index 6739cc84a24248a23fd864e8cc78f3d7770f5639..91eb8c5c8478df52d03b22a3f23ed83f7edcbb71 100644 |
--- a/src/x64/full-codegen-x64.cc |
+++ b/src/x64/full-codegen-x64.cc |
@@ -282,11 +282,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()); |
} |
@@ -703,15 +703,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. |
+ __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); |
+ __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); |
+ __ Check(not_equal, "Declaration in with context."); |
+ __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); |
+ __ 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_; |
@@ -719,45 +734,17 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, |
case Variable::PARAMETER: |
case Variable::LOCAL: |
- if (function != NULL) { |
- Comment cmnt(masm_, "[ Declaration"); |
- VisitForAccumulatorValue(function); |
- __ movq(StackOperand(variable), result_register()); |
- } else if (binding_needs_init) { |
- Comment cmnt(masm_, "[ Declaration"); |
+ if (hole_init) { |
+ Comment cmnt(masm_, "[ VariableDeclaration"); |
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
__ movq(StackOperand(variable), kScratchRegister); |
} |
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. |
- __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); |
- __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); |
- __ Check(not_equal, "Declaration in with context."); |
- __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); |
- __ Check(not_equal, "Declaration in catch context."); |
- } |
- if (function != NULL) { |
- Comment cmnt(masm_, "[ Declaration"); |
- VisitForAccumulatorValue(function); |
- __ movq(ContextOperand(rsi, variable->index()), result_register()); |
- int offset = Context::SlotOffset(variable->index()); |
- // We know that we have written a function, which is not a smi. |
- __ RecordWriteContextSlot(rsi, |
- offset, |
- result_register(), |
- rcx, |
- 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(kScratchRegister, Heap::kTheHoleValueRootIndex); |
__ movq(ContextOperand(rsi, variable->index()), kScratchRegister); |
// No write barrier since the hole value is in old space. |
@@ -766,14 +753,12 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, |
break; |
case Variable::LOOKUP: { |
- Comment cmnt(masm_, "[ Declaration"); |
+ Comment cmnt(masm_, "[ VariableDeclaration"); |
__ push(rsi); |
__ Push(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; |
__ Push(Smi::FromInt(attr)); |
@@ -781,9 +766,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) { |
__ PushRoot(Heap::kTheHoleValueRootIndex); |
} else { |
__ Push(Smi::FromInt(0)); // Indicates no initial value. |
@@ -795,6 +778,105 @@ 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()); |
+ __ movq(StackOperand(variable), result_register()); |
+ break; |
+ } |
+ |
+ case Variable::CONTEXT: { |
+ Comment cmnt(masm_, "[ FunctionDeclaration"); |
+ EmitDebugCheckDeclarationContext(variable); |
+ VisitForAccumulatorValue(declaration->fun()); |
+ __ movq(ContextOperand(rsi, variable->index()), result_register()); |
+ int offset = Context::SlotOffset(variable->index()); |
+ // We know that we have written a function, which is not a smi. |
+ __ RecordWriteContextSlot(rsi, |
+ offset, |
+ result_register(), |
+ rcx, |
+ kDontSaveFPRegs, |
+ EMIT_REMEMBERED_SET, |
+ OMIT_SMI_CHECK); |
+ PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
+ break; |
+ } |
+ |
+ case Variable::LOOKUP: { |
+ Comment cmnt(masm_, "[ FunctionDeclaration"); |
+ __ push(rsi); |
+ __ Push(variable->name()); |
+ __ Push(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(rsi); // The context is the first argument. |