OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |