Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 9d4fe2e50529e779b45cde69b4c3140274d8a3a5..65cd6c1de93ad041ad7b0bbc4bb157aed495cfd9 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -6364,7 +6364,8 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
int position, |
BailoutId assignment_id, |
HValue* object, |
- HValue* value, |
+ HValue* store_value, |
+ HValue* result_value, |
SmallMapList* types, |
Handle<String> name) { |
// Use monomorphic store if property lookup results in the same field index |
@@ -6410,12 +6411,14 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
HInstruction* store; |
CHECK_ALIVE_OR_RETURN( |
store = BuildStoreNamedField( |
- object, name, value, types->at(count - 1), &lookup), |
+ object, name, store_value, types->at(count - 1), &lookup), |
true); |
- Push(value); |
+ if (result_value != NULL) Push(result_value); |
+ Push(store_value); |
store->set_position(position); |
AddInstruction(store); |
AddSimulate(assignment_id); |
+ if (result_value != NULL) Drop(1); |
ast_context()->ReturnValue(Pop()); |
return true; |
} |
@@ -6426,11 +6429,13 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
int position, |
BailoutId assignment_id, |
HValue* object, |
- HValue* value, |
+ HValue* store_value, |
+ HValue* result_value, |
SmallMapList* types, |
Handle<String> name) { |
if (TryStorePolymorphicAsMonomorphic( |
- position, assignment_id, object, value, types, name)) { |
+ position, assignment_id, object, |
+ store_value, result_value, types, name)) { |
return; |
} |
@@ -6456,12 +6461,15 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
set_current_block(if_true); |
HInstruction* instr; |
- CHECK_ALIVE( |
- instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
+ CHECK_ALIVE(instr = BuildStoreNamedField( |
+ object, name, store_value, map, &lookup)); |
instr->set_position(position); |
// Goto will add the HSimulate for the store. |
AddInstruction(instr); |
- if (!ast_context()->IsEffect()) Push(value); |
+ if (!ast_context()->IsEffect()) { |
+ if (result_value != NULL) Push(result_value); |
+ Push(store_value); |
+ } |
current_block()->Goto(join); |
set_current_block(if_false); |
@@ -6474,12 +6482,15 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
} else { |
- HInstruction* instr = BuildStoreNamedGeneric(object, name, value); |
+ HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); |
instr->set_position(position); |
AddInstruction(instr); |
if (join != NULL) { |
- if (!ast_context()->IsEffect()) Push(value); |
+ if (!ast_context()->IsEffect()) { |
+ if (result_value != NULL) Push(result_value); |
+ Push(store_value); |
+ } |
current_block()->Goto(join); |
} else { |
// The HSimulate for the store should not see the stored value in |
@@ -6489,19 +6500,24 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
if (ast_context()->IsEffect()) { |
AddSimulate(id, REMOVABLE_SIMULATE); |
} else { |
- Push(value); |
+ if (result_value != NULL) Push(result_value); |
+ Push(store_value); |
AddSimulate(id, REMOVABLE_SIMULATE); |
- Drop(1); |
+ Drop(result_value != NULL ? 2 : 1); |
} |
} |
- return ast_context()->ReturnValue(value); |
+ return ast_context()->ReturnValue( |
+ result_value != NULL ? result_value : store_value); |
} |
} |
ASSERT(join != NULL); |
join->SetJoinId(id); |
set_current_block(join); |
- if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
+ if (!ast_context()->IsEffect()) { |
+ if (result_value != NULL) Drop(1); |
+ ast_context()->ReturnValue(Pop()); |
+ } |
} |
@@ -6582,7 +6598,8 @@ void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
BailoutId assignment_id, |
Property* prop, |
HValue* object, |
- HValue* value) { |
+ HValue* store_value, |
+ HValue* result_value) { |
Literal* key = prop->key()->AsLiteral(); |
Handle<String> name = Handle<String>::cast(key->handle()); |
ASSERT(!name.is_null()); |
@@ -6600,37 +6617,42 @@ void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
Handle<JSObject> holder; |
if (LookupSetter(map, name, &setter, &holder)) { |
AddCheckConstantFunction(holder, object, map); |
- if (FLAG_inline_accessors && |
- TryInlineSetter(setter, id, assignment_id, value)) { |
+ // Don't try to inline if the result_value is different from the |
+ // store_value. That case isn't handled yet by the inlining. |
+ if (result_value == NULL && |
+ FLAG_inline_accessors && |
+ TryInlineSetter(setter, id, assignment_id, store_value)) { |
return; |
} |
Drop(2); |
AddInstruction(new(zone()) HPushArgument(object)); |
- AddInstruction(new(zone()) HPushArgument(value)); |
+ AddInstruction(new(zone()) HPushArgument(store_value)); |
instr = new(zone()) HCallConstantFunction(setter, 2); |
} else { |
Drop(2); |
CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
name, |
- value, |
+ store_value, |
map)); |
} |
- |
} else if (types != NULL && types->length() > 1) { |
Drop(2); |
return HandlePolymorphicStoreNamedField( |
- id, position, assignment_id, object, value, types, name); |
+ id, position, assignment_id, object, |
+ store_value, result_value, types, name); |
} else { |
Drop(2); |
- instr = BuildStoreNamedGeneric(object, name, value); |
+ instr = BuildStoreNamedGeneric(object, name, store_value); |
} |
- Push(value); |
+ if (result_value != NULL) Push(result_value); |
+ Push(store_value); |
instr->set_position(position); |
AddInstruction(instr); |
if (instr->HasObservableSideEffects()) { |
AddSimulate(assignment_id, REMOVABLE_SIMULATE); |
} |
+ if (result_value != NULL) Drop(1); |
return ast_context()->ReturnValue(Pop()); |
} |
@@ -9254,35 +9276,11 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
} |
after = BuildIncrement(returns_original_input, expr); |
- input = Pop(); |
- HInstruction* store; |
- if (!monomorphic || map->is_observed()) { |
- // If we don't know the monomorphic type, do a generic store. |
- CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after)); |
- } else { |
- Handle<JSFunction> setter; |
- Handle<JSObject> holder; |
- if (LookupSetter(map, name, &setter, &holder)) { |
- store = BuildCallSetter(object, after, map, setter, holder); |
- } else { |
- CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, |
- name, |
- after, |
- map)); |
- } |
- } |
- AddInstruction(store); |
- |
- // Overwrite the receiver in the bailout environment with the result |
- // of the operation, and the placeholder with the original value if |
- // necessary. |
- environment()->SetExpressionStackAt(0, after); |
- if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
- if (store->HasObservableSideEffects()) { |
- AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
- } |
+ HValue* result = returns_original_input ? Pop() : NULL; |
+ return BuildStoreNamed(prop, expr->id(), expr->position(), |
+ expr->AssignmentId(), prop, object, after, result); |
} else { |
// Keyed property. |
if (returns_original_input) Push(graph()->GetConstantUndefined()); |