| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 73d3e498e5c2782eaeb36c6c368573365e81975e..aaf1a1bacd58364a0340502a69d3a2f2c3243e3a 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());
|
| + }
|
| }
|
|
|
|
|
| @@ -4699,20 +4705,32 @@ 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) {
|
| + // If we need to return ToNumber(input), we force a representation change.
|
| + 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;
|
| }
|
|
|
| @@ -4725,18 +4743,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; // The input to the count operation, after ToNumber.
|
| + 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()) {
|
| @@ -4756,19 +4781,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();
|
| @@ -4784,11 +4805,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);
|
| @@ -4797,19 +4815,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 {
|
| + } 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()));
|
| @@ -4820,11 +4831,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);
|
| @@ -4835,16 +4843,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);
|
| }
|
|
|
|
|
|
|