Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(579)

Side by Side Diff: src/hydrogen.cc

Issue 7033008: Fix error in postfix ++ in Crankshaft. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix typo, remove unneeded code. Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1785 matching lines...) Expand 10 before | Expand all | Expand 10 after
1796 HValue* use_value = it.value(); 1796 HValue* use_value = it.value();
1797 int use_index = it.index(); 1797 int use_index = it.index();
1798 Representation req = use_value->RequiredInputRepresentation(use_index); 1798 Representation req = use_value->RequiredInputRepresentation(use_index);
1799 if (req.IsNone() || req.Equals(r)) continue; 1799 if (req.IsNone() || req.Equals(r)) continue;
1800 InsertRepresentationChangeForUse(value, use_value, use_index, req); 1800 InsertRepresentationChangeForUse(value, use_value, use_index, req);
1801 } 1801 }
1802 if (value->HasNoUses()) { 1802 if (value->HasNoUses()) {
1803 ASSERT(value->IsConstant()); 1803 ASSERT(value->IsConstant());
1804 value->DeleteAndReplaceWith(NULL); 1804 value->DeleteAndReplaceWith(NULL);
1805 } 1805 }
1806
1807 // The only purpose of a HForceRepresentation is to represent the value
1808 // after the (possible) HChange instruction. We make it disappear.
1809 if (value->IsForceRepresentation()) {
1810 value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
1811 }
1806 } 1812 }
1807 1813
1808 1814
1809 void HGraph::InsertRepresentationChanges() { 1815 void HGraph::InsertRepresentationChanges() {
1810 HPhase phase("Insert representation changes", this); 1816 HPhase phase("Insert representation changes", this);
1811 1817
1812 1818
1813 // Compute truncation flag for phis: Initially assume that all 1819 // Compute truncation flag for phis: Initially assume that all
1814 // int32-phis allow truncation and iteratively remove the ones that 1820 // int32-phis allow truncation and iteratively remove the ones that
1815 // are used in an operation that does not allow a truncating 1821 // are used in an operation that does not allow a truncating
(...skipping 2876 matching lines...) Expand 10 before | Expand all | Expand 10 after
4692 materialize_true = NULL; 4698 materialize_true = NULL;
4693 } 4699 }
4694 4700
4695 HBasicBlock* join = 4701 HBasicBlock* join =
4696 CreateJoin(materialize_false, materialize_true, expr->id()); 4702 CreateJoin(materialize_false, materialize_true, expr->id());
4697 set_current_block(join); 4703 set_current_block(join);
4698 if (join != NULL) ast_context()->ReturnValue(Pop()); 4704 if (join != NULL) ast_context()->ReturnValue(Pop());
4699 } 4705 }
4700 4706
4701 4707
4702 HInstruction* HGraphBuilder::BuildIncrement(HValue* value, 4708 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input,
4703 bool increment,
4704 CountOperation* expr) { 4709 CountOperation* expr) {
4705 HConstant* delta = increment 4710 // The input to the count operation is on top of the expression stack.
4706 ? graph_->GetConstant1()
4707 : graph_->GetConstantMinus1();
4708 HInstruction* instr = new(zone()) HAdd(value, delta);
4709 TypeInfo info = oracle()->IncrementType(expr); 4711 TypeInfo info = oracle()->IncrementType(expr);
4710 Representation rep = ToRepresentation(info); 4712 Representation rep = ToRepresentation(info);
4711 if (rep.IsTagged()) { 4713 if (rep.IsTagged()) {
4712 rep = Representation::Integer32(); 4714 rep = Representation::Integer32();
4713 } 4715 }
4716
4717 if (returns_original_input) {
4718 // If we need to return ToNumber(input), we force a representation change.
4719 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep);
4720 AddInstruction(number_input);
4721 Push(number_input);
4722 }
4723
4724 // The addition has no side effects, so we do not need
4725 // to simulate the expression stack after this instruction.
4726 // Any later failures deopt to the load of the input or earlier.
4727 HConstant* delta = (expr->op() == Token::INC)
4728 ? graph_->GetConstant1()
4729 : graph_->GetConstantMinus1();
4730 HInstruction* instr = new(zone()) HAdd(Top(), delta);
4714 TraceRepresentation(expr->op(), info, instr, rep); 4731 TraceRepresentation(expr->op(), info, instr, rep);
4715 instr->AssumeRepresentation(rep); 4732 instr->AssumeRepresentation(rep);
4733 AddInstruction(instr);
4716 return instr; 4734 return instr;
4717 } 4735 }
4718 4736
4719 4737
4720 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { 4738 void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4721 ASSERT(!HasStackOverflow()); 4739 ASSERT(!HasStackOverflow());
4722 ASSERT(current_block() != NULL); 4740 ASSERT(current_block() != NULL);
4723 ASSERT(current_block()->HasPredecessor()); 4741 ASSERT(current_block()->HasPredecessor());
4724 Expression* target = expr->expression(); 4742 Expression* target = expr->expression();
4725 VariableProxy* proxy = target->AsVariableProxy(); 4743 VariableProxy* proxy = target->AsVariableProxy();
4726 Variable* var = proxy->AsVariable(); 4744 Variable* var = proxy->AsVariable();
4727 Property* prop = target->AsProperty(); 4745 Property* prop = target->AsProperty();
4728 ASSERT(var == NULL || prop == NULL); 4746 if (var == NULL && prop == NULL) {
4729 bool inc = expr->op() == Token::INC; 4747 return Bailout("invalid lhs in count operation");
4748 }
4749
4750 // Match the full code generator stack by simulating an extra stack
4751 // element for postfix operations in a non-effect context. The return
4752 // value is ToNumber(input).
4753 bool returns_original_input =
4754 expr->is_postfix() && !ast_context()->IsEffect();
4755 HValue* input = NULL; // The input to the count operation, after ToNumber.
4756 HValue* after = NULL; // The result after incrementing or decrementing.
4730 4757
4731 if (var != NULL) { 4758 if (var != NULL) {
4759 // Argument of the count operation is a variable, not a property.
4760 ASSERT(prop == NULL);
4732 CHECK_ALIVE(VisitForValue(target)); 4761 CHECK_ALIVE(VisitForValue(target));
4733 4762
4734 // Match the full code generator stack by simulating an extra stack 4763 after = BuildIncrement(returns_original_input, expr);
4735 // element for postfix operations in a non-effect context. 4764 input = returns_original_input ? Top() : Pop();
4736 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4737 HValue* before = has_extra ? Top() : Pop();
4738 HInstruction* after = BuildIncrement(before, inc, expr);
4739 AddInstruction(after);
4740 Push(after); 4765 Push(after);
4741 4766
4742 if (var->is_global()) { 4767 if (var->is_global()) {
4743 HandleGlobalVariableAssignment(var, 4768 HandleGlobalVariableAssignment(var,
4744 after, 4769 after,
4745 expr->position(), 4770 expr->position(),
4746 expr->AssignmentId()); 4771 expr->AssignmentId());
4747 } else if (var->IsStackAllocated()) { 4772 } else if (var->IsStackAllocated()) {
4748 Bind(var, after); 4773 Bind(var, after);
4749 } else if (var->IsContextSlot()) { 4774 } else if (var->IsContextSlot()) {
4750 HValue* context = BuildContextChainWalk(var); 4775 HValue* context = BuildContextChainWalk(var);
4751 int index = var->AsSlot()->index(); 4776 int index = var->AsSlot()->index();
4752 HStoreContextSlot* instr = 4777 HStoreContextSlot* instr =
4753 new(zone()) HStoreContextSlot(context, index, after); 4778 new(zone()) HStoreContextSlot(context, index, after);
4754 AddInstruction(instr); 4779 AddInstruction(instr);
4755 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4780 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
4756 } else { 4781 } else {
4757 return Bailout("lookup variable in count operation"); 4782 return Bailout("lookup variable in count operation");
4758 } 4783 }
4759 Drop(has_extra ? 2 : 1);
4760 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4761 4784
4762 } else if (prop != NULL) { 4785 } else {
4786 // Argument of the count operation is a property.
4787 ASSERT(prop != NULL);
4763 prop->RecordTypeFeedback(oracle()); 4788 prop->RecordTypeFeedback(oracle());
4764 4789
4765 if (prop->key()->IsPropertyName()) { 4790 if (prop->key()->IsPropertyName()) {
4766 // Named property. 4791 // Named property.
4767 4792 if (returns_original_input) Push(graph_->GetConstantUndefined());
4768 // Match the full code generator stack by simulating an extra stack
4769 // element for postfix operations in a non-effect context.
4770 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4771 if (has_extra) Push(graph_->GetConstantUndefined());
4772 4793
4773 CHECK_ALIVE(VisitForValue(prop->obj())); 4794 CHECK_ALIVE(VisitForValue(prop->obj()));
4774 HValue* obj = Top(); 4795 HValue* obj = Top();
4775 4796
4776 HInstruction* load = NULL; 4797 HInstruction* load = NULL;
4777 if (prop->IsMonomorphic()) { 4798 if (prop->IsMonomorphic()) {
4778 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4799 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4779 Handle<Map> map = prop->GetReceiverTypes()->first(); 4800 Handle<Map> map = prop->GetReceiverTypes()->first();
4780 load = BuildLoadNamed(obj, prop, map, name); 4801 load = BuildLoadNamed(obj, prop, map, name);
4781 } else { 4802 } else {
4782 load = BuildLoadNamedGeneric(obj, prop); 4803 load = BuildLoadNamedGeneric(obj, prop);
4783 } 4804 }
4784 PushAndAdd(load); 4805 PushAndAdd(load);
4785 if (load->HasSideEffects()) AddSimulate(expr->CountId()); 4806 if (load->HasSideEffects()) AddSimulate(expr->CountId());
4786 4807
4787 HValue* before = Pop(); 4808 after = BuildIncrement(returns_original_input, expr);
4788 // There is no deoptimization to after the increment, so we don't need 4809 input = Pop();
4789 // to simulate the expression stack after this instruction.
4790 HInstruction* after = BuildIncrement(before, inc, expr);
4791 AddInstruction(after);
4792 4810
4793 HInstruction* store = BuildStoreNamed(obj, after, prop); 4811 HInstruction* store = BuildStoreNamed(obj, after, prop);
4794 AddInstruction(store); 4812 AddInstruction(store);
4795 4813
4796 // Overwrite the receiver in the bailout environment with the result 4814 // Overwrite the receiver in the bailout environment with the result
4797 // of the operation, and the placeholder with the original value if 4815 // of the operation, and the placeholder with the original value if
4798 // necessary. 4816 // necessary.
4799 environment()->SetExpressionStackAt(0, after); 4817 environment()->SetExpressionStackAt(0, after);
4800 if (has_extra) environment()->SetExpressionStackAt(1, before); 4818 if (returns_original_input) environment()->SetExpressionStackAt(1, input);
4801 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4819 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4802 Drop(has_extra ? 2 : 1);
4803 4820
4804 ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4821 } else {
4805
4806 } else {
4807 // Keyed property. 4822 // Keyed property.
4808 4823 if (returns_original_input) Push(graph_->GetConstantUndefined());
4809 // Match the full code generator stack by simulate an extra stack element
4810 // for postfix operations in a non-effect context.
4811 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4812 if (has_extra) Push(graph_->GetConstantUndefined());
4813 4824
4814 CHECK_ALIVE(VisitForValue(prop->obj())); 4825 CHECK_ALIVE(VisitForValue(prop->obj()));
4815 CHECK_ALIVE(VisitForValue(prop->key())); 4826 CHECK_ALIVE(VisitForValue(prop->key()));
4816 HValue* obj = environment()->ExpressionStackAt(1); 4827 HValue* obj = environment()->ExpressionStackAt(1);
4817 HValue* key = environment()->ExpressionStackAt(0); 4828 HValue* key = environment()->ExpressionStackAt(0);
4818 4829
4819 HInstruction* load = BuildLoadKeyed(obj, key, prop); 4830 HInstruction* load = BuildLoadKeyed(obj, key, prop);
4820 PushAndAdd(load); 4831 PushAndAdd(load);
4821 if (load->HasSideEffects()) AddSimulate(expr->CountId()); 4832 if (load->HasSideEffects()) AddSimulate(expr->CountId());
4822 4833
4823 HValue* before = Pop(); 4834 after = BuildIncrement(returns_original_input, expr);
4824 // There is no deoptimization to after the increment, so we don't need 4835 input = Pop();
4825 // to simulate the expression stack after this instruction.
4826 HInstruction* after = BuildIncrement(before, inc, expr);
4827 AddInstruction(after);
4828 4836
4829 expr->RecordTypeFeedback(oracle()); 4837 expr->RecordTypeFeedback(oracle());
4830 HInstruction* store = BuildStoreKeyed(obj, key, after, expr); 4838 HInstruction* store = BuildStoreKeyed(obj, key, after, expr);
4831 AddInstruction(store); 4839 AddInstruction(store);
4832 4840
4833 // Drop the key from the bailout environment. Overwrite the receiver 4841 // Drop the key from the bailout environment. Overwrite the receiver
4834 // with the result of the operation, and the placeholder with the 4842 // with the result of the operation, and the placeholder with the
4835 // original value if necessary. 4843 // original value if necessary.
4836 Drop(1); 4844 Drop(1);
4837 environment()->SetExpressionStackAt(0, after); 4845 environment()->SetExpressionStackAt(0, after);
4838 if (has_extra) environment()->SetExpressionStackAt(1, before); 4846 if (returns_original_input) environment()->SetExpressionStackAt(1, input);
4839 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4847 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4840 Drop(has_extra ? 2 : 1); 4848 }
4849 }
4841 4850
4842 ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4851 Drop(returns_original_input ? 2 : 1);
4843 } 4852 ast_context()->ReturnValue(expr->is_postfix() ? input : after);
4844
4845 } else {
4846 return Bailout("invalid lhs in count operation");
4847 }
4848 } 4853 }
4849 4854
4850 4855
4851 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left, 4856 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left,
4852 HValue* right, 4857 HValue* right,
4853 Token::Value op) { 4858 Token::Value op) {
4854 ASSERT(op == Token::EQ || op == Token::EQ_STRICT); 4859 ASSERT(op == Token::EQ || op == Token::EQ_STRICT);
4855 AddInstruction(new(zone()) HCheckNonSmi(left)); 4860 AddInstruction(new(zone()) HCheckNonSmi(left));
4856 AddInstruction(HCheckInstanceType::NewIsSymbol(left)); 4861 AddInstruction(HCheckInstanceType::NewIsSymbol(left));
4857 AddInstruction(new(zone()) HCheckNonSmi(right)); 4862 AddInstruction(new(zone()) HCheckNonSmi(right));
(...skipping 1276 matching lines...) Expand 10 before | Expand all | Expand 10 after
6134 } 6139 }
6135 } 6140 }
6136 6141
6137 #ifdef DEBUG 6142 #ifdef DEBUG
6138 if (graph_ != NULL) graph_->Verify(); 6143 if (graph_ != NULL) graph_->Verify();
6139 if (allocator_ != NULL) allocator_->Verify(); 6144 if (allocator_ != NULL) allocator_->Verify();
6140 #endif 6145 #endif
6141 } 6146 }
6142 6147
6143 } } // namespace v8::internal 6148 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698