| Index: src/full-codegen/s390/full-codegen-s390.cc
 | 
| diff --git a/src/full-codegen/s390/full-codegen-s390.cc b/src/full-codegen/s390/full-codegen-s390.cc
 | 
| index 0db853bfc3d59e8661399c8430fe1927ef8bd15b..94b52112ef23894eac1670a194fe2d3132aa33d6 100644
 | 
| --- a/src/full-codegen/s390/full-codegen-s390.cc
 | 
| +++ b/src/full-codegen/s390/full-codegen-s390.cc
 | 
| @@ -694,9 +694,9 @@ void FullCodeGenerator::VisitVariableDeclaration(
 | 
|      VariableDeclaration* declaration) {
 | 
|    VariableProxy* proxy = declaration->proxy();
 | 
|    Variable* variable = proxy->var();
 | 
| -  DCHECK(!variable->binding_needs_init());
 | 
|    switch (variable->location()) {
 | 
|      case VariableLocation::UNALLOCATED: {
 | 
| +      DCHECK(!variable->binding_needs_init());
 | 
|        globals_->Add(variable->name(), zone());
 | 
|        FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
 | 
|        DCHECK(!slot.IsInvalid());
 | 
| @@ -706,7 +706,22 @@ void FullCodeGenerator::VisitVariableDeclaration(
 | 
|      }
 | 
|      case VariableLocation::PARAMETER:
 | 
|      case VariableLocation::LOCAL:
 | 
| +      if (variable->binding_needs_init()) {
 | 
| +        Comment cmnt(masm_, "[ VariableDeclaration");
 | 
| +        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
 | 
| +        __ StoreP(ip, StackOperand(variable));
 | 
| +      }
 | 
| +      break;
 | 
| +
 | 
|      case VariableLocation::CONTEXT:
 | 
| +      if (variable->binding_needs_init()) {
 | 
| +        Comment cmnt(masm_, "[ VariableDeclaration");
 | 
| +        EmitDebugCheckDeclarationContext(variable);
 | 
| +        __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
 | 
| +        __ StoreP(ip, ContextMemOperand(cp, variable->index()));
 | 
| +        // No write barrier since the_hole_value is in old space.
 | 
| +        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
 | 
| +      }
 | 
|        break;
 | 
|  
 | 
|      case VariableLocation::LOOKUP:
 | 
| @@ -1082,6 +1097,20 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
 | 
|        DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
 | 
|        Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
 | 
|                                                 : "[ Stack variable");
 | 
| +      if (proxy->hole_check_mode() == HoleCheckMode::kRequired) {
 | 
| +        // Throw a reference error when using an uninitialized let/const
 | 
| +        // binding in harmony mode.
 | 
| +        Label done;
 | 
| +        GetVar(r2, var);
 | 
| +        __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
 | 
| +        __ bne(&done);
 | 
| +        __ mov(r2, Operand(var->name()));
 | 
| +        __ push(r2);
 | 
| +        __ CallRuntime(Runtime::kThrowReferenceError);
 | 
| +        __ bind(&done);
 | 
| +        context()->Plug(r2);
 | 
| +        break;
 | 
| +      }
 | 
|        context()->Plug(var);
 | 
|        break;
 | 
|      }
 | 
| @@ -1393,7 +1422,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
 | 
|    switch (assign_type) {
 | 
|      case VARIABLE: {
 | 
|        VariableProxy* proxy = expr->target()->AsVariableProxy();
 | 
| -      EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot());
 | 
| +      EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(),
 | 
| +                             proxy->hole_check_mode());
 | 
|        PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
 | 
|        context()->Plug(r2);
 | 
|        break;
 | 
| @@ -1619,7 +1649,8 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
 | 
|      case VARIABLE: {
 | 
|        VariableProxy* proxy = expr->AsVariableProxy();
 | 
|        EffectContext context(this);
 | 
| -      EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot);
 | 
| +      EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot,
 | 
| +                             proxy->hole_check_mode());
 | 
|        break;
 | 
|      }
 | 
|      case NAMED_PROPERTY: {
 | 
| @@ -1661,22 +1692,60 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
 | 
|  }
 | 
|  
 | 
|  void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
 | 
| -                                               FeedbackVectorSlot slot) {
 | 
| -  DCHECK(!var->binding_needs_init());
 | 
| +                                               FeedbackVectorSlot slot,
 | 
| +                                               HoleCheckMode hole_check_mode) {
 | 
|    if (var->IsUnallocated()) {
 | 
|      // Global var, const, or let.
 | 
|      __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
 | 
|      CallStoreIC(slot, var->name());
 | 
|  
 | 
| -  } else if (var->mode() == CONST && op != Token::INIT) {
 | 
| -    if (var->throw_on_const_assignment(language_mode())) {
 | 
| +  } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
 | 
| +    // Non-initializing assignment to let variable needs a write barrier.
 | 
| +    DCHECK(!var->IsLookupSlot());
 | 
| +    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
 | 
| +    MemOperand location = VarOperand(var, r3);
 | 
| +    // Perform an initialization check for lexically declared variables.
 | 
| +    if (hole_check_mode == HoleCheckMode::kRequired) {
 | 
| +      Label assign;
 | 
| +      __ LoadP(r5, location);
 | 
| +      __ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
 | 
| +      __ bne(&assign);
 | 
| +      __ mov(r5, Operand(var->name()));
 | 
| +      __ push(r5);
 | 
| +      __ CallRuntime(Runtime::kThrowReferenceError);
 | 
| +      __ bind(&assign);
 | 
| +    }
 | 
| +    if (var->mode() != CONST) {
 | 
| +      EmitStoreToStackLocalOrContextSlot(var, location);
 | 
| +    } else if (var->throw_on_const_assignment(language_mode())) {
 | 
|        __ CallRuntime(Runtime::kThrowConstAssignError);
 | 
|      }
 | 
| +  } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
 | 
| +    // Initializing assignment to const {this} needs a write barrier.
 | 
| +    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
 | 
| +    Label uninitialized_this;
 | 
| +    MemOperand location = VarOperand(var, r3);
 | 
| +    __ LoadP(r5, location);
 | 
| +    __ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
 | 
| +    __ beq(&uninitialized_this);
 | 
| +    __ mov(r3, Operand(var->name()));
 | 
| +    __ push(r3);
 | 
| +    __ CallRuntime(Runtime::kThrowReferenceError);
 | 
| +    __ bind(&uninitialized_this);
 | 
| +    EmitStoreToStackLocalOrContextSlot(var, location);
 | 
|    } else {
 | 
| -    DCHECK(!var->is_this());
 | 
| +    DCHECK(var->mode() != CONST || op == Token::INIT);
 | 
|      DCHECK((var->IsStackAllocated() || var->IsContextSlot()));
 | 
|      DCHECK(!var->IsLookupSlot());
 | 
| +    // Assignment to var or initializing assignment to let/const in harmony
 | 
| +    // mode.
 | 
|      MemOperand location = VarOperand(var, r3);
 | 
| +    if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
 | 
| +      // Check for an uninitialized let binding.
 | 
| +      __ LoadP(r4, location);
 | 
| +      __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
 | 
| +      __ Check(eq, kLetBindingReInitialization);
 | 
| +    }
 | 
|      EmitStoreToStackLocalOrContextSlot(var, location);
 | 
|    }
 | 
|  }
 | 
| @@ -2368,8 +2437,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 | 
|        if (expr->is_postfix()) {
 | 
|          {
 | 
|            EffectContext context(this);
 | 
| -          EmitVariableAssignment(proxy->var(), Token::ASSIGN,
 | 
| -                                 expr->CountSlot());
 | 
| +          EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
 | 
| +                                 proxy->hole_check_mode());
 | 
|            PrepareForBailoutForId(expr->AssignmentId(),
 | 
|                                   BailoutState::TOS_REGISTER);
 | 
|            context.Plug(r2);
 | 
| @@ -2380,7 +2449,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
 | 
|            context()->PlugTOS();
 | 
|          }
 | 
|        } else {
 | 
| -        EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot());
 | 
| +        EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
 | 
| +                               proxy->hole_check_mode());
 | 
|          PrepareForBailoutForId(expr->AssignmentId(),
 | 
|                                 BailoutState::TOS_REGISTER);
 | 
|          context()->Plug(r2);
 | 
| 
 |