| Index: src/arm/full-codegen-arm.cc | 
| diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc | 
| index 77f4e4414dac6f553d45e5722fed23e478d28905..e6a8891db1fd31a0d7bb9d785d9a2f6c9cc863f0 100644 | 
| --- a/src/arm/full-codegen-arm.cc | 
| +++ b/src/arm/full-codegen-arm.cc | 
| @@ -291,11 +291,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()); | 
| } | 
| @@ -731,15 +731,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. | 
| +    __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset)); | 
| +    __ CompareRoot(r1, Heap::kWithContextMapRootIndex); | 
| +    __ Check(ne, "Declaration in with context."); | 
| +    __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); | 
| +    __ Check(ne, "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_; | 
| @@ -747,46 +762,17 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, | 
|  | 
| case Variable::PARAMETER: | 
| case Variable::LOCAL: | 
| -      if (function != NULL) { | 
| -        Comment cmnt(masm_, "[ Declaration"); | 
| -        VisitForAccumulatorValue(function); | 
| -        __ str(result_register(), StackOperand(variable)); | 
| -      } else if (binding_needs_init) { | 
| -        Comment cmnt(masm_, "[ Declaration"); | 
| +      if (hole_init) { | 
| +        Comment cmnt(masm_, "[ VariableDeclaration"); | 
| __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 
| __ str(ip, 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. | 
| -        __ ldr(r1, FieldMemOperand(cp, HeapObject::kMapOffset)); | 
| -        __ CompareRoot(r1, Heap::kWithContextMapRootIndex); | 
| -        __ Check(ne, "Declaration in with context."); | 
| -        __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); | 
| -        __ Check(ne, "Declaration in catch context."); | 
| -      } | 
| -      if (function != NULL) { | 
| -        Comment cmnt(masm_, "[ Declaration"); | 
| -        VisitForAccumulatorValue(function); | 
| -        __ str(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(), | 
| -                                  r2, | 
| -                                  kLRHasBeenSaved, | 
| -                                  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(ip, Heap::kTheHoleValueRootIndex); | 
| __ str(ip, ContextOperand(cp, variable->index())); | 
| // No write barrier since the_hole_value is in old space. | 
| @@ -795,13 +781,11 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, | 
| break; | 
|  | 
| case Variable::LOOKUP: { | 
| -      Comment cmnt(masm_, "[ Declaration"); | 
| +      Comment cmnt(masm_, "[ VariableDeclaration"); | 
| __ mov(r2, 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; | 
| __ mov(r1, Operand(Smi::FromInt(attr))); | 
| @@ -809,11 +793,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) { | 
| -        __ Push(cp, r2, r1); | 
| -        // Push initial value for function declaration. | 
| -        VisitForStackValue(function); | 
| -      } else if (binding_needs_init) { | 
| +      if (hole_init) { | 
| __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 
| __ Push(cp, r2, r1, r0); | 
| } else { | 
| @@ -827,6 +807,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()); | 
| +      __ str(result_register(), StackOperand(variable)); | 
| +      break; | 
| +    } | 
| + | 
| +    case Variable::CONTEXT: { | 
| +      Comment cmnt(masm_, "[ FunctionDeclaration"); | 
| +      EmitDebugCheckDeclarationContext(variable); | 
| +      VisitForAccumulatorValue(declaration->fun()); | 
| +      __ str(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(), | 
| +                                r2, | 
| +                                kLRHasBeenSaved, | 
| +                                kDontSaveFPRegs, | 
| +                                EMIT_REMEMBERED_SET, | 
| +                                OMIT_SMI_CHECK); | 
| +      PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 
| +      break; | 
| +    } | 
| + | 
| +    case Variable::LOOKUP: { | 
| +      Comment cmnt(masm_, "[ FunctionDeclaration"); | 
| +      __ mov(r2, Operand(variable->name())); | 
| +      __ mov(r1, Operand(Smi::FromInt(NONE))); | 
| +      __ Push(cp, r2, r1); | 
| +      // 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. | 
|  |