Chromium Code Reviews| 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 |