| Index: src/hydrogen.cc
 | 
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
 | 
| index 18d77f3390acd9a457c77bd8249fe76223df4173..17d0131881b879fc2d33a8d24100350ccf5c4d9f 100644
 | 
| --- a/src/hydrogen.cc
 | 
| +++ b/src/hydrogen.cc
 | 
| @@ -1803,6 +1803,12 @@ void HGraph::InsertRepresentationChangesForValue(HValue* value) {
 | 
|      ASSERT(value->IsConstant());
 | 
|      value->DeleteAndReplaceWith(NULL);
 | 
|    }
 | 
| +
 | 
| +  // The only purpose of a HForceRepresentation is to represent the value
 | 
| +  // after the (possible) HChange instruction.  We make it disappear.
 | 
| +  if (value->IsForceRepresentation()) {
 | 
| +    value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -3725,6 +3731,11 @@ HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement(
 | 
|    HLoadExternalArrayPointer* external_elements =
 | 
|        new(zone()) HLoadExternalArrayPointer(elements);
 | 
|    AddInstruction(external_elements);
 | 
| +  if (expr->external_array_type() == kExternalPixelArray) {
 | 
| +    HClampToUint8* clamp = new(zone()) HClampToUint8(val);
 | 
| +    AddInstruction(clamp);
 | 
| +    val = clamp;
 | 
| +  }
 | 
|    return new(zone()) HStoreKeyedSpecializedArrayElement(
 | 
|        external_elements,
 | 
|        key,
 | 
| @@ -4694,20 +4705,35 @@ void HGraphBuilder::VisitNot(UnaryOperation* expr) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -HInstruction* HGraphBuilder::BuildIncrement(HValue* value,
 | 
| -                                            bool increment,
 | 
| +HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input,
 | 
|                                              CountOperation* expr) {
 | 
| -  HConstant* delta = increment
 | 
| -      ? graph_->GetConstant1()
 | 
| -      : graph_->GetConstantMinus1();
 | 
| -  HInstruction* instr = new(zone()) HAdd(value, delta);
 | 
| +  // The input to the count operation is on top of the expression stack.
 | 
|    TypeInfo info = oracle()->IncrementType(expr);
 | 
|    Representation rep = ToRepresentation(info);
 | 
|    if (rep.IsTagged()) {
 | 
|      rep = Representation::Integer32();
 | 
|    }
 | 
| +
 | 
| +  if (returns_original_input) {
 | 
| +    // We need an explicit HValue representing ToNumber(input).  The
 | 
| +    // actual HChange instruction we need is (sometimes) added in a later
 | 
| +    // phase, so it is not available now to be used as an input to HAdd and
 | 
| +    // as the return value.
 | 
| +    HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep);
 | 
| +    AddInstruction(number_input);
 | 
| +    Push(number_input);
 | 
| +  }
 | 
| +
 | 
| +  // The addition has no side effects, so we do not need
 | 
| +  // to simulate the expression stack after this instruction.
 | 
| +  // Any later failures deopt to the load of the input or earlier.
 | 
| +  HConstant* delta = (expr->op() == Token::INC)
 | 
| +      ? graph_->GetConstant1()
 | 
| +      : graph_->GetConstantMinus1();
 | 
| +  HInstruction* instr = new(zone()) HAdd(Top(), delta);
 | 
|    TraceRepresentation(expr->op(), info, instr, rep);
 | 
|    instr->AssumeRepresentation(rep);
 | 
| +  AddInstruction(instr);
 | 
|    return instr;
 | 
|  }
 | 
|  
 | 
| @@ -4720,18 +4746,25 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|    VariableProxy* proxy = target->AsVariableProxy();
 | 
|    Variable* var = proxy->AsVariable();
 | 
|    Property* prop = target->AsProperty();
 | 
| -  ASSERT(var == NULL || prop == NULL);
 | 
| -  bool inc = expr->op() == Token::INC;
 | 
| +  if (var == NULL && prop == NULL) {
 | 
| +    return Bailout("invalid lhs in count operation");
 | 
| +  }
 | 
| +
 | 
| +  // Match the full code generator stack by simulating an extra stack
 | 
| +  // element for postfix operations in a non-effect context.  The return
 | 
| +  // value is ToNumber(input).
 | 
| +  bool returns_original_input =
 | 
| +      expr->is_postfix() && !ast_context()->IsEffect();
 | 
| +  HValue* input = NULL;  // ToNumber(original_input).
 | 
| +  HValue* after = NULL;  // The result after incrementing or decrementing.
 | 
|  
 | 
|    if (var != NULL) {
 | 
| +    // Argument of the count operation is a variable, not a property.
 | 
| +    ASSERT(prop == NULL);
 | 
|      CHECK_ALIVE(VisitForValue(target));
 | 
|  
 | 
| -    // Match the full code generator stack by simulating an extra stack
 | 
| -    // element for postfix operations in a non-effect context.
 | 
| -    bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
 | 
| -    HValue* before = has_extra ? Top() : Pop();
 | 
| -    HInstruction* after = BuildIncrement(before, inc, expr);
 | 
| -    AddInstruction(after);
 | 
| +    after = BuildIncrement(returns_original_input, expr);
 | 
| +    input = returns_original_input ? Top() : Pop();
 | 
|      Push(after);
 | 
|  
 | 
|      if (var->is_global()) {
 | 
| @@ -4751,19 +4784,15 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|      } else {
 | 
|        return Bailout("lookup variable in count operation");
 | 
|      }
 | 
| -    Drop(has_extra ? 2 : 1);
 | 
| -    ast_context()->ReturnValue(expr->is_postfix() ? before : after);
 | 
|  
 | 
| -  } else if (prop != NULL) {
 | 
| +  } else {
 | 
| +    // Argument of the count operation is a property.
 | 
| +    ASSERT(prop != NULL);
 | 
|      prop->RecordTypeFeedback(oracle());
 | 
|  
 | 
|      if (prop->key()->IsPropertyName()) {
 | 
|        // Named property.
 | 
| -
 | 
| -      // Match the full code generator stack by simulating an extra stack
 | 
| -      // element for postfix operations in a non-effect context.
 | 
| -      bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
 | 
| -      if (has_extra) Push(graph_->GetConstantUndefined());
 | 
| +      if (returns_original_input) Push(graph_->GetConstantUndefined());
 | 
|  
 | 
|        CHECK_ALIVE(VisitForValue(prop->obj()));
 | 
|        HValue* obj = Top();
 | 
| @@ -4779,11 +4808,8 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|        PushAndAdd(load);
 | 
|        if (load->HasSideEffects()) AddSimulate(expr->CountId());
 | 
|  
 | 
| -      HValue* before = Pop();
 | 
| -      // There is no deoptimization to after the increment, so we don't need
 | 
| -      // to simulate the expression stack after this instruction.
 | 
| -      HInstruction* after = BuildIncrement(before, inc, expr);
 | 
| -      AddInstruction(after);
 | 
| +      after = BuildIncrement(returns_original_input, expr);
 | 
| +      input = Pop();
 | 
|  
 | 
|        HInstruction* store = BuildStoreNamed(obj, after, prop);
 | 
|        AddInstruction(store);
 | 
| @@ -4792,19 +4818,12 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|        // of the operation, and the placeholder with the original value if
 | 
|        // necessary.
 | 
|        environment()->SetExpressionStackAt(0, after);
 | 
| -      if (has_extra) environment()->SetExpressionStackAt(1, before);
 | 
| +      if (returns_original_input) environment()->SetExpressionStackAt(1, input);
 | 
|        if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
 | 
| -      Drop(has_extra ? 2 : 1);
 | 
| -
 | 
| -      ast_context()->ReturnValue(expr->is_postfix() ? before : after);
 | 
|  
 | 
|      } else {
 | 
|        // Keyed property.
 | 
| -
 | 
| -      // Match the full code generator stack by simulate an extra stack element
 | 
| -      // for postfix operations in a non-effect context.
 | 
| -      bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
 | 
| -      if (has_extra) Push(graph_->GetConstantUndefined());
 | 
| +      if (returns_original_input) Push(graph_->GetConstantUndefined());
 | 
|  
 | 
|        CHECK_ALIVE(VisitForValue(prop->obj()));
 | 
|        CHECK_ALIVE(VisitForValue(prop->key()));
 | 
| @@ -4815,11 +4834,8 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|        PushAndAdd(load);
 | 
|        if (load->HasSideEffects()) AddSimulate(expr->CountId());
 | 
|  
 | 
| -      HValue* before = Pop();
 | 
| -      // There is no deoptimization to after the increment, so we don't need
 | 
| -      // to simulate the expression stack after this instruction.
 | 
| -      HInstruction* after = BuildIncrement(before, inc, expr);
 | 
| -      AddInstruction(after);
 | 
| +      after = BuildIncrement(returns_original_input, expr);
 | 
| +      input = Pop();
 | 
|  
 | 
|        expr->RecordTypeFeedback(oracle());
 | 
|        HInstruction* store = BuildStoreKeyed(obj, key, after, expr);
 | 
| @@ -4830,16 +4846,13 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
 | 
|        // original value if necessary.
 | 
|        Drop(1);
 | 
|        environment()->SetExpressionStackAt(0, after);
 | 
| -      if (has_extra) environment()->SetExpressionStackAt(1, before);
 | 
| +      if (returns_original_input) environment()->SetExpressionStackAt(1, input);
 | 
|        if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
 | 
| -      Drop(has_extra ? 2 : 1);
 | 
| -
 | 
| -      ast_context()->ReturnValue(expr->is_postfix() ? before : after);
 | 
|      }
 | 
| -
 | 
| -  } else {
 | 
| -    return Bailout("invalid lhs in count operation");
 | 
|    }
 | 
| +
 | 
| +  Drop(returns_original_input ? 2 : 1);
 | 
| +  ast_context()->ReturnValue(expr->is_postfix() ? input : after);
 | 
|  }
 | 
|  
 | 
|  
 | 
| 
 |