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 1766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1777 : constant->CopyToRepresentation(to); | 1777 : constant->CopyToRepresentation(to); |
1778 } | 1778 } |
1779 | 1779 |
1780 if (new_value == NULL) { | 1780 if (new_value == NULL) { |
1781 new_value = | 1781 new_value = |
1782 new(zone()) HChange(value, value->representation(), to, is_truncating); | 1782 new(zone()) HChange(value, value->representation(), to, is_truncating); |
1783 } | 1783 } |
1784 | 1784 |
1785 new_value->InsertBefore(next); | 1785 new_value->InsertBefore(next); |
1786 use_value->SetOperandAt(use_index, new_value); | 1786 use_value->SetOperandAt(use_index, new_value); |
1787 | |
1788 // The only purpose of a HForceRepresentation is to represent the value | |
1789 // after the (possible) HChange instruction. We make it disappear. | |
1790 if (use_value->IsForceRepresentation()) { | |
1791 use_value->DeleteAndReplaceWith(new_value); | |
William Hesse
2011/05/16 16:19:48
We should be able to delete this copy.
fschneider
2011/05/17 11:03:15
Yes, I think you can do it below and you only need
| |
1792 } | |
1787 } | 1793 } |
1788 | 1794 |
1789 | 1795 |
1790 void HGraph::InsertRepresentationChangesForValue(HValue* value) { | 1796 void HGraph::InsertRepresentationChangesForValue(HValue* value) { |
1791 Representation r = value->representation(); | 1797 Representation r = value->representation(); |
1792 if (r.IsNone()) return; | 1798 if (r.IsNone()) return; |
1793 if (value->HasNoUses()) return; | 1799 if (value->HasNoUses()) return; |
1794 | 1800 |
1795 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { | 1801 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { |
1796 HValue* use_value = it.value(); | 1802 HValue* use_value = it.value(); |
1797 int use_index = it.index(); | 1803 int use_index = it.index(); |
1798 Representation req = use_value->RequiredInputRepresentation(use_index); | 1804 Representation req = use_value->RequiredInputRepresentation(use_index); |
1799 if (req.IsNone() || req.Equals(r)) continue; | 1805 if (req.IsNone() || req.Equals(r)) continue; |
1800 InsertRepresentationChangeForUse(value, use_value, use_index, req); | 1806 InsertRepresentationChangeForUse(value, use_value, use_index, req); |
1801 } | 1807 } |
1802 if (value->HasNoUses()) { | 1808 if (value->HasNoUses()) { |
1803 ASSERT(value->IsConstant()); | 1809 ASSERT(value->IsConstant()); |
1804 value->DeleteAndReplaceWith(NULL); | 1810 value->DeleteAndReplaceWith(NULL); |
1805 } | 1811 } |
1812 | |
1813 // The only purpose of a HForceRepresentation is to represent the value | |
1814 // after the (possible) HChange instruction. We make it disappear. | |
1815 if (value->IsForceRepresentation()) { | |
1816 value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value()); | |
1817 } | |
1806 } | 1818 } |
1807 | 1819 |
1808 | 1820 |
1809 void HGraph::InsertRepresentationChanges() { | 1821 void HGraph::InsertRepresentationChanges() { |
1810 HPhase phase("Insert representation changes", this); | 1822 HPhase phase("Insert representation changes", this); |
1811 | 1823 |
1812 | 1824 |
1813 // Compute truncation flag for phis: Initially assume that all | 1825 // Compute truncation flag for phis: Initially assume that all |
1814 // int32-phis allow truncation and iteratively remove the ones that | 1826 // int32-phis allow truncation and iteratively remove the ones that |
1815 // are used in an operation that does not allow a truncating | 1827 // 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; | 4704 materialize_true = NULL; |
4693 } | 4705 } |
4694 | 4706 |
4695 HBasicBlock* join = | 4707 HBasicBlock* join = |
4696 CreateJoin(materialize_false, materialize_true, expr->id()); | 4708 CreateJoin(materialize_false, materialize_true, expr->id()); |
4697 set_current_block(join); | 4709 set_current_block(join); |
4698 if (join != NULL) ast_context()->ReturnValue(Pop()); | 4710 if (join != NULL) ast_context()->ReturnValue(Pop()); |
4699 } | 4711 } |
4700 | 4712 |
4701 | 4713 |
4702 HInstruction* HGraphBuilder::BuildIncrement(HValue* value, | 4714 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, |
4703 bool increment, | |
4704 CountOperation* expr) { | 4715 CountOperation* expr) { |
4705 HConstant* delta = increment | 4716 // 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); | 4717 TypeInfo info = oracle()->IncrementType(expr); |
4710 Representation rep = ToRepresentation(info); | 4718 Representation rep = ToRepresentation(info); |
4711 if (rep.IsTagged()) { | 4719 if (rep.IsTagged()) { |
4712 rep = Representation::Integer32(); | 4720 rep = Representation::Integer32(); |
4713 } | 4721 } |
4722 | |
4723 if (returns_original_input) { | |
4724 // If we need to return ToNumber(input), we force a representation change. | |
fschneider
2011/05/17 11:03:15
maybe explain why:
// to have get a HValue for th
| |
4725 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); | |
4726 AddInstruction(number_input); | |
4727 Push(number_input); | |
4728 } | |
4729 | |
4730 // The addition has no side effects, so we do not need | |
4731 // to simulate the expression stack after this instruction. | |
4732 // Any later failures deopt to the load of the input or earlier. | |
4733 HConstant* delta = (expr->op() == Token::INC) | |
4734 ? graph_->GetConstant1() | |
4735 : graph_->GetConstantMinus1(); | |
4736 HInstruction* instr = new(zone()) HAdd(Top(), delta); | |
4714 TraceRepresentation(expr->op(), info, instr, rep); | 4737 TraceRepresentation(expr->op(), info, instr, rep); |
4715 instr->AssumeRepresentation(rep); | 4738 instr->AssumeRepresentation(rep); |
4739 AddInstruction(instr); | |
4716 return instr; | 4740 return instr; |
4717 } | 4741 } |
4718 | 4742 |
4719 | 4743 |
4720 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { | 4744 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
4721 ASSERT(!HasStackOverflow()); | 4745 ASSERT(!HasStackOverflow()); |
4722 ASSERT(current_block() != NULL); | 4746 ASSERT(current_block() != NULL); |
4723 ASSERT(current_block()->HasPredecessor()); | 4747 ASSERT(current_block()->HasPredecessor()); |
4724 Expression* target = expr->expression(); | 4748 Expression* target = expr->expression(); |
4725 VariableProxy* proxy = target->AsVariableProxy(); | 4749 VariableProxy* proxy = target->AsVariableProxy(); |
4726 Variable* var = proxy->AsVariable(); | 4750 Variable* var = proxy->AsVariable(); |
4727 Property* prop = target->AsProperty(); | 4751 Property* prop = target->AsProperty(); |
4728 ASSERT(var == NULL || prop == NULL); | 4752 if (var == NULL && prop == NULL) { |
4729 bool inc = expr->op() == Token::INC; | 4753 return Bailout("invalid lhs in count operation"); |
4754 } | |
4755 | |
4756 // Match the full code generator stack by simulating an extra stack | |
4757 // element for postfix operations in a non-effect context. The return | |
4758 // value is ToNumber(input). | |
4759 bool returns_original_input = | |
4760 expr->is_postfix() && !ast_context()->IsEffect(); | |
4761 HValue* input = NULL; // The input to the count operation, after ToNumber. | |
fschneider
2011/05/17 11:03:15
just say ToNumber(input)?
| |
4762 HValue* after = NULL; // The result after incrementing or decrementing. | |
4730 | 4763 |
4731 if (var != NULL) { | 4764 if (var != NULL) { |
4765 // Argument of the count operation is a variable, not a property. | |
4766 ASSERT(prop == NULL); | |
4732 CHECK_ALIVE(VisitForValue(target)); | 4767 CHECK_ALIVE(VisitForValue(target)); |
4733 | 4768 |
4734 // Match the full code generator stack by simulating an extra stack | 4769 after = BuildIncrement(returns_original_input, expr); |
4735 // element for postfix operations in a non-effect context. | 4770 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); | 4771 Push(after); |
4741 | 4772 |
4742 if (var->is_global()) { | 4773 if (var->is_global()) { |
4743 HandleGlobalVariableAssignment(var, | 4774 HandleGlobalVariableAssignment(var, |
4744 after, | 4775 after, |
4745 expr->position(), | 4776 expr->position(), |
4746 expr->AssignmentId()); | 4777 expr->AssignmentId()); |
4747 } else if (var->IsStackAllocated()) { | 4778 } else if (var->IsStackAllocated()) { |
4748 Bind(var, after); | 4779 Bind(var, after); |
4749 } else if (var->IsContextSlot()) { | 4780 } else if (var->IsContextSlot()) { |
4750 HValue* context = BuildContextChainWalk(var); | 4781 HValue* context = BuildContextChainWalk(var); |
4751 int index = var->AsSlot()->index(); | 4782 int index = var->AsSlot()->index(); |
4752 HStoreContextSlot* instr = | 4783 HStoreContextSlot* instr = |
4753 new(zone()) HStoreContextSlot(context, index, after); | 4784 new(zone()) HStoreContextSlot(context, index, after); |
4754 AddInstruction(instr); | 4785 AddInstruction(instr); |
4755 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4786 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
4756 } else { | 4787 } else { |
4757 return Bailout("lookup variable in count operation"); | 4788 return Bailout("lookup variable in count operation"); |
4758 } | 4789 } |
4759 Drop(has_extra ? 2 : 1); | |
4760 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | |
4761 | 4790 |
4762 } else if (prop != NULL) { | 4791 } else { |
4792 // Argument of the count operation is a property. | |
4793 ASSERT(prop != NULL); | |
4763 prop->RecordTypeFeedback(oracle()); | 4794 prop->RecordTypeFeedback(oracle()); |
4764 | 4795 |
4765 if (prop->key()->IsPropertyName()) { | 4796 if (prop->key()->IsPropertyName()) { |
4766 // Named property. | 4797 // Named property. |
4767 | 4798 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 | 4799 |
4773 CHECK_ALIVE(VisitForValue(prop->obj())); | 4800 CHECK_ALIVE(VisitForValue(prop->obj())); |
4774 HValue* obj = Top(); | 4801 HValue* obj = Top(); |
4775 | 4802 |
4776 HInstruction* load = NULL; | 4803 HInstruction* load = NULL; |
4777 if (prop->IsMonomorphic()) { | 4804 if (prop->IsMonomorphic()) { |
4778 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4805 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
4779 Handle<Map> map = prop->GetReceiverTypes()->first(); | 4806 Handle<Map> map = prop->GetReceiverTypes()->first(); |
4780 load = BuildLoadNamed(obj, prop, map, name); | 4807 load = BuildLoadNamed(obj, prop, map, name); |
4781 } else { | 4808 } else { |
4782 load = BuildLoadNamedGeneric(obj, prop); | 4809 load = BuildLoadNamedGeneric(obj, prop); |
4783 } | 4810 } |
4784 PushAndAdd(load); | 4811 PushAndAdd(load); |
4785 if (load->HasSideEffects()) AddSimulate(expr->CountId()); | 4812 if (load->HasSideEffects()) AddSimulate(expr->CountId()); |
4786 | 4813 |
4787 HValue* before = Pop(); | 4814 after = BuildIncrement(returns_original_input, expr); |
4788 // There is no deoptimization to after the increment, so we don't need | 4815 input = Pop(); |
4789 // to simulate the expression stack after this instruction. | |
4790 HInstruction* after = BuildIncrement(before, inc, expr); | |
4791 AddInstruction(after); | |
4792 | 4816 |
4793 HInstruction* store = BuildStoreNamed(obj, after, prop); | 4817 HInstruction* store = BuildStoreNamed(obj, after, prop); |
4794 AddInstruction(store); | 4818 AddInstruction(store); |
4795 | 4819 |
4796 // Overwrite the receiver in the bailout environment with the result | 4820 // Overwrite the receiver in the bailout environment with the result |
4797 // of the operation, and the placeholder with the original value if | 4821 // of the operation, and the placeholder with the original value if |
4798 // necessary. | 4822 // necessary. |
4799 environment()->SetExpressionStackAt(0, after); | 4823 environment()->SetExpressionStackAt(0, after); |
4800 if (has_extra) environment()->SetExpressionStackAt(1, before); | 4824 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
4801 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4825 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
4802 Drop(has_extra ? 2 : 1); | |
4803 | 4826 |
4804 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | 4827 } else { |
4805 | |
4806 } else { | |
4807 // Keyed property. | 4828 // Keyed property. |
4808 | 4829 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 | 4830 |
4814 CHECK_ALIVE(VisitForValue(prop->obj())); | 4831 CHECK_ALIVE(VisitForValue(prop->obj())); |
4815 CHECK_ALIVE(VisitForValue(prop->key())); | 4832 CHECK_ALIVE(VisitForValue(prop->key())); |
4816 HValue* obj = environment()->ExpressionStackAt(1); | 4833 HValue* obj = environment()->ExpressionStackAt(1); |
4817 HValue* key = environment()->ExpressionStackAt(0); | 4834 HValue* key = environment()->ExpressionStackAt(0); |
4818 | 4835 |
4819 HInstruction* load = BuildLoadKeyed(obj, key, prop); | 4836 HInstruction* load = BuildLoadKeyed(obj, key, prop); |
4820 PushAndAdd(load); | 4837 PushAndAdd(load); |
4821 if (load->HasSideEffects()) AddSimulate(expr->CountId()); | 4838 if (load->HasSideEffects()) AddSimulate(expr->CountId()); |
4822 | 4839 |
4823 HValue* before = Pop(); | 4840 after = BuildIncrement(returns_original_input, expr); |
4824 // There is no deoptimization to after the increment, so we don't need | 4841 input = Pop(); |
4825 // to simulate the expression stack after this instruction. | |
4826 HInstruction* after = BuildIncrement(before, inc, expr); | |
4827 AddInstruction(after); | |
4828 | 4842 |
4829 expr->RecordTypeFeedback(oracle()); | 4843 expr->RecordTypeFeedback(oracle()); |
4830 HInstruction* store = BuildStoreKeyed(obj, key, after, expr); | 4844 HInstruction* store = BuildStoreKeyed(obj, key, after, expr); |
4831 AddInstruction(store); | 4845 AddInstruction(store); |
4832 | 4846 |
4833 // Drop the key from the bailout environment. Overwrite the receiver | 4847 // Drop the key from the bailout environment. Overwrite the receiver |
4834 // with the result of the operation, and the placeholder with the | 4848 // with the result of the operation, and the placeholder with the |
4835 // original value if necessary. | 4849 // original value if necessary. |
4836 Drop(1); | 4850 Drop(1); |
4837 environment()->SetExpressionStackAt(0, after); | 4851 environment()->SetExpressionStackAt(0, after); |
4838 if (has_extra) environment()->SetExpressionStackAt(1, before); | 4852 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
4839 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4853 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
4840 Drop(has_extra ? 2 : 1); | 4854 } |
4855 } | |
4841 | 4856 |
4842 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | 4857 Drop(returns_original_input ? 2 : 1); |
4843 } | 4858 ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
4844 | |
4845 } else { | |
4846 return Bailout("invalid lhs in count operation"); | |
4847 } | |
4848 } | 4859 } |
4849 | 4860 |
4850 | 4861 |
4851 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left, | 4862 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left, |
4852 HValue* right, | 4863 HValue* right, |
4853 Token::Value op) { | 4864 Token::Value op) { |
4854 ASSERT(op == Token::EQ || op == Token::EQ_STRICT); | 4865 ASSERT(op == Token::EQ || op == Token::EQ_STRICT); |
4855 AddInstruction(new(zone()) HCheckNonSmi(left)); | 4866 AddInstruction(new(zone()) HCheckNonSmi(left)); |
4856 AddInstruction(HCheckInstanceType::NewIsSymbol(left)); | 4867 AddInstruction(HCheckInstanceType::NewIsSymbol(left)); |
4857 AddInstruction(new(zone()) HCheckNonSmi(right)); | 4868 AddInstruction(new(zone()) HCheckNonSmi(right)); |
(...skipping 1276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6134 } | 6145 } |
6135 } | 6146 } |
6136 | 6147 |
6137 #ifdef DEBUG | 6148 #ifdef DEBUG |
6138 if (graph_ != NULL) graph_->Verify(); | 6149 if (graph_ != NULL) graph_->Verify(); |
6139 if (allocator_ != NULL) allocator_->Verify(); | 6150 if (allocator_ != NULL) allocator_->Verify(); |
6140 #endif | 6151 #endif |
6141 } | 6152 } |
6142 | 6153 |
6143 } } // namespace v8::internal | 6154 } } // namespace v8::internal |
OLD | NEW |