| 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 |