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 1902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3718 ASSERT(map->has_external_array_elements()); | 3724 ASSERT(map->has_external_array_elements()); |
3719 AddInstruction(new(zone()) HCheckMap(object, map)); | 3725 AddInstruction(new(zone()) HCheckMap(object, map)); |
3720 HLoadElements* elements = new(zone()) HLoadElements(object); | 3726 HLoadElements* elements = new(zone()) HLoadElements(object); |
3721 AddInstruction(elements); | 3727 AddInstruction(elements); |
3722 HInstruction* length = AddInstruction( | 3728 HInstruction* length = AddInstruction( |
3723 new(zone()) HExternalArrayLength(elements)); | 3729 new(zone()) HExternalArrayLength(elements)); |
3724 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3730 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3725 HLoadExternalArrayPointer* external_elements = | 3731 HLoadExternalArrayPointer* external_elements = |
3726 new(zone()) HLoadExternalArrayPointer(elements); | 3732 new(zone()) HLoadExternalArrayPointer(elements); |
3727 AddInstruction(external_elements); | 3733 AddInstruction(external_elements); |
| 3734 if (expr->external_array_type() == kExternalPixelArray) { |
| 3735 HClampToUint8* clamp = new(zone()) HClampToUint8(val); |
| 3736 AddInstruction(clamp); |
| 3737 val = clamp; |
| 3738 } |
3728 return new(zone()) HStoreKeyedSpecializedArrayElement( | 3739 return new(zone()) HStoreKeyedSpecializedArrayElement( |
3729 external_elements, | 3740 external_elements, |
3730 key, | 3741 key, |
3731 val, | 3742 val, |
3732 expr->external_array_type()); | 3743 expr->external_array_type()); |
3733 } | 3744 } |
3734 | 3745 |
3735 | 3746 |
3736 HInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object, | 3747 HInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object, |
3737 HValue* key, | 3748 HValue* key, |
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4687 materialize_true = NULL; | 4698 materialize_true = NULL; |
4688 } | 4699 } |
4689 | 4700 |
4690 HBasicBlock* join = | 4701 HBasicBlock* join = |
4691 CreateJoin(materialize_false, materialize_true, expr->id()); | 4702 CreateJoin(materialize_false, materialize_true, expr->id()); |
4692 set_current_block(join); | 4703 set_current_block(join); |
4693 if (join != NULL) ast_context()->ReturnValue(Pop()); | 4704 if (join != NULL) ast_context()->ReturnValue(Pop()); |
4694 } | 4705 } |
4695 | 4706 |
4696 | 4707 |
4697 HInstruction* HGraphBuilder::BuildIncrement(HValue* value, | 4708 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, |
4698 bool increment, | |
4699 CountOperation* expr) { | 4709 CountOperation* expr) { |
4700 HConstant* delta = increment | 4710 // The input to the count operation is on top of the expression stack. |
4701 ? graph_->GetConstant1() | |
4702 : graph_->GetConstantMinus1(); | |
4703 HInstruction* instr = new(zone()) HAdd(value, delta); | |
4704 TypeInfo info = oracle()->IncrementType(expr); | 4711 TypeInfo info = oracle()->IncrementType(expr); |
4705 Representation rep = ToRepresentation(info); | 4712 Representation rep = ToRepresentation(info); |
4706 if (rep.IsTagged()) { | 4713 if (rep.IsTagged()) { |
4707 rep = Representation::Integer32(); | 4714 rep = Representation::Integer32(); |
4708 } | 4715 } |
| 4716 |
| 4717 if (returns_original_input) { |
| 4718 // We need an explicit HValue representing ToNumber(input). The |
| 4719 // actual HChange instruction we need is (sometimes) added in a later |
| 4720 // phase, so it is not available now to be used as an input to HAdd and |
| 4721 // as the return value. |
| 4722 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); |
| 4723 AddInstruction(number_input); |
| 4724 Push(number_input); |
| 4725 } |
| 4726 |
| 4727 // The addition has no side effects, so we do not need |
| 4728 // to simulate the expression stack after this instruction. |
| 4729 // Any later failures deopt to the load of the input or earlier. |
| 4730 HConstant* delta = (expr->op() == Token::INC) |
| 4731 ? graph_->GetConstant1() |
| 4732 : graph_->GetConstantMinus1(); |
| 4733 HInstruction* instr = new(zone()) HAdd(Top(), delta); |
4709 TraceRepresentation(expr->op(), info, instr, rep); | 4734 TraceRepresentation(expr->op(), info, instr, rep); |
4710 instr->AssumeRepresentation(rep); | 4735 instr->AssumeRepresentation(rep); |
| 4736 AddInstruction(instr); |
4711 return instr; | 4737 return instr; |
4712 } | 4738 } |
4713 | 4739 |
4714 | 4740 |
4715 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { | 4741 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
4716 ASSERT(!HasStackOverflow()); | 4742 ASSERT(!HasStackOverflow()); |
4717 ASSERT(current_block() != NULL); | 4743 ASSERT(current_block() != NULL); |
4718 ASSERT(current_block()->HasPredecessor()); | 4744 ASSERT(current_block()->HasPredecessor()); |
4719 Expression* target = expr->expression(); | 4745 Expression* target = expr->expression(); |
4720 VariableProxy* proxy = target->AsVariableProxy(); | 4746 VariableProxy* proxy = target->AsVariableProxy(); |
4721 Variable* var = proxy->AsVariable(); | 4747 Variable* var = proxy->AsVariable(); |
4722 Property* prop = target->AsProperty(); | 4748 Property* prop = target->AsProperty(); |
4723 ASSERT(var == NULL || prop == NULL); | 4749 if (var == NULL && prop == NULL) { |
4724 bool inc = expr->op() == Token::INC; | 4750 return Bailout("invalid lhs in count operation"); |
| 4751 } |
| 4752 |
| 4753 // Match the full code generator stack by simulating an extra stack |
| 4754 // element for postfix operations in a non-effect context. The return |
| 4755 // value is ToNumber(input). |
| 4756 bool returns_original_input = |
| 4757 expr->is_postfix() && !ast_context()->IsEffect(); |
| 4758 HValue* input = NULL; // ToNumber(original_input). |
| 4759 HValue* after = NULL; // The result after incrementing or decrementing. |
4725 | 4760 |
4726 if (var != NULL) { | 4761 if (var != NULL) { |
| 4762 // Argument of the count operation is a variable, not a property. |
| 4763 ASSERT(prop == NULL); |
4727 CHECK_ALIVE(VisitForValue(target)); | 4764 CHECK_ALIVE(VisitForValue(target)); |
4728 | 4765 |
4729 // Match the full code generator stack by simulating an extra stack | 4766 after = BuildIncrement(returns_original_input, expr); |
4730 // element for postfix operations in a non-effect context. | 4767 input = returns_original_input ? Top() : Pop(); |
4731 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | |
4732 HValue* before = has_extra ? Top() : Pop(); | |
4733 HInstruction* after = BuildIncrement(before, inc, expr); | |
4734 AddInstruction(after); | |
4735 Push(after); | 4768 Push(after); |
4736 | 4769 |
4737 if (var->is_global()) { | 4770 if (var->is_global()) { |
4738 HandleGlobalVariableAssignment(var, | 4771 HandleGlobalVariableAssignment(var, |
4739 after, | 4772 after, |
4740 expr->position(), | 4773 expr->position(), |
4741 expr->AssignmentId()); | 4774 expr->AssignmentId()); |
4742 } else if (var->IsStackAllocated()) { | 4775 } else if (var->IsStackAllocated()) { |
4743 Bind(var, after); | 4776 Bind(var, after); |
4744 } else if (var->IsContextSlot()) { | 4777 } else if (var->IsContextSlot()) { |
4745 HValue* context = BuildContextChainWalk(var); | 4778 HValue* context = BuildContextChainWalk(var); |
4746 int index = var->AsSlot()->index(); | 4779 int index = var->AsSlot()->index(); |
4747 HStoreContextSlot* instr = | 4780 HStoreContextSlot* instr = |
4748 new(zone()) HStoreContextSlot(context, index, after); | 4781 new(zone()) HStoreContextSlot(context, index, after); |
4749 AddInstruction(instr); | 4782 AddInstruction(instr); |
4750 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4783 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
4751 } else { | 4784 } else { |
4752 return Bailout("lookup variable in count operation"); | 4785 return Bailout("lookup variable in count operation"); |
4753 } | 4786 } |
4754 Drop(has_extra ? 2 : 1); | |
4755 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | |
4756 | 4787 |
4757 } else if (prop != NULL) { | 4788 } else { |
| 4789 // Argument of the count operation is a property. |
| 4790 ASSERT(prop != NULL); |
4758 prop->RecordTypeFeedback(oracle()); | 4791 prop->RecordTypeFeedback(oracle()); |
4759 | 4792 |
4760 if (prop->key()->IsPropertyName()) { | 4793 if (prop->key()->IsPropertyName()) { |
4761 // Named property. | 4794 // Named property. |
4762 | 4795 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
4763 // Match the full code generator stack by simulating an extra stack | |
4764 // element for postfix operations in a non-effect context. | |
4765 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | |
4766 if (has_extra) Push(graph_->GetConstantUndefined()); | |
4767 | 4796 |
4768 CHECK_ALIVE(VisitForValue(prop->obj())); | 4797 CHECK_ALIVE(VisitForValue(prop->obj())); |
4769 HValue* obj = Top(); | 4798 HValue* obj = Top(); |
4770 | 4799 |
4771 HInstruction* load = NULL; | 4800 HInstruction* load = NULL; |
4772 if (prop->IsMonomorphic()) { | 4801 if (prop->IsMonomorphic()) { |
4773 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4802 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
4774 Handle<Map> map = prop->GetReceiverTypes()->first(); | 4803 Handle<Map> map = prop->GetReceiverTypes()->first(); |
4775 load = BuildLoadNamed(obj, prop, map, name); | 4804 load = BuildLoadNamed(obj, prop, map, name); |
4776 } else { | 4805 } else { |
4777 load = BuildLoadNamedGeneric(obj, prop); | 4806 load = BuildLoadNamedGeneric(obj, prop); |
4778 } | 4807 } |
4779 PushAndAdd(load); | 4808 PushAndAdd(load); |
4780 if (load->HasSideEffects()) AddSimulate(expr->CountId()); | 4809 if (load->HasSideEffects()) AddSimulate(expr->CountId()); |
4781 | 4810 |
4782 HValue* before = Pop(); | 4811 after = BuildIncrement(returns_original_input, expr); |
4783 // There is no deoptimization to after the increment, so we don't need | 4812 input = Pop(); |
4784 // to simulate the expression stack after this instruction. | |
4785 HInstruction* after = BuildIncrement(before, inc, expr); | |
4786 AddInstruction(after); | |
4787 | 4813 |
4788 HInstruction* store = BuildStoreNamed(obj, after, prop); | 4814 HInstruction* store = BuildStoreNamed(obj, after, prop); |
4789 AddInstruction(store); | 4815 AddInstruction(store); |
4790 | 4816 |
4791 // Overwrite the receiver in the bailout environment with the result | 4817 // Overwrite the receiver in the bailout environment with the result |
4792 // of the operation, and the placeholder with the original value if | 4818 // of the operation, and the placeholder with the original value if |
4793 // necessary. | 4819 // necessary. |
4794 environment()->SetExpressionStackAt(0, after); | 4820 environment()->SetExpressionStackAt(0, after); |
4795 if (has_extra) environment()->SetExpressionStackAt(1, before); | 4821 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
4796 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4822 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
4797 Drop(has_extra ? 2 : 1); | |
4798 | |
4799 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | |
4800 | 4823 |
4801 } else { | 4824 } else { |
4802 // Keyed property. | 4825 // Keyed property. |
4803 | 4826 if (returns_original_input) Push(graph_->GetConstantUndefined()); |
4804 // Match the full code generator stack by simulate an extra stack element | |
4805 // for postfix operations in a non-effect context. | |
4806 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | |
4807 if (has_extra) Push(graph_->GetConstantUndefined()); | |
4808 | 4827 |
4809 CHECK_ALIVE(VisitForValue(prop->obj())); | 4828 CHECK_ALIVE(VisitForValue(prop->obj())); |
4810 CHECK_ALIVE(VisitForValue(prop->key())); | 4829 CHECK_ALIVE(VisitForValue(prop->key())); |
4811 HValue* obj = environment()->ExpressionStackAt(1); | 4830 HValue* obj = environment()->ExpressionStackAt(1); |
4812 HValue* key = environment()->ExpressionStackAt(0); | 4831 HValue* key = environment()->ExpressionStackAt(0); |
4813 | 4832 |
4814 HInstruction* load = BuildLoadKeyed(obj, key, prop); | 4833 HInstruction* load = BuildLoadKeyed(obj, key, prop); |
4815 PushAndAdd(load); | 4834 PushAndAdd(load); |
4816 if (load->HasSideEffects()) AddSimulate(expr->CountId()); | 4835 if (load->HasSideEffects()) AddSimulate(expr->CountId()); |
4817 | 4836 |
4818 HValue* before = Pop(); | 4837 after = BuildIncrement(returns_original_input, expr); |
4819 // There is no deoptimization to after the increment, so we don't need | 4838 input = Pop(); |
4820 // to simulate the expression stack after this instruction. | |
4821 HInstruction* after = BuildIncrement(before, inc, expr); | |
4822 AddInstruction(after); | |
4823 | 4839 |
4824 expr->RecordTypeFeedback(oracle()); | 4840 expr->RecordTypeFeedback(oracle()); |
4825 HInstruction* store = BuildStoreKeyed(obj, key, after, expr); | 4841 HInstruction* store = BuildStoreKeyed(obj, key, after, expr); |
4826 AddInstruction(store); | 4842 AddInstruction(store); |
4827 | 4843 |
4828 // Drop the key from the bailout environment. Overwrite the receiver | 4844 // Drop the key from the bailout environment. Overwrite the receiver |
4829 // with the result of the operation, and the placeholder with the | 4845 // with the result of the operation, and the placeholder with the |
4830 // original value if necessary. | 4846 // original value if necessary. |
4831 Drop(1); | 4847 Drop(1); |
4832 environment()->SetExpressionStackAt(0, after); | 4848 environment()->SetExpressionStackAt(0, after); |
4833 if (has_extra) environment()->SetExpressionStackAt(1, before); | 4849 if (returns_original_input) environment()->SetExpressionStackAt(1, input); |
4834 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4850 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
4835 Drop(has_extra ? 2 : 1); | 4851 } |
| 4852 } |
4836 | 4853 |
4837 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | 4854 Drop(returns_original_input ? 2 : 1); |
4838 } | 4855 ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
4839 | |
4840 } else { | |
4841 return Bailout("invalid lhs in count operation"); | |
4842 } | |
4843 } | 4856 } |
4844 | 4857 |
4845 | 4858 |
4846 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left, | 4859 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left, |
4847 HValue* right, | 4860 HValue* right, |
4848 Token::Value op) { | 4861 Token::Value op) { |
4849 ASSERT(op == Token::EQ || op == Token::EQ_STRICT); | 4862 ASSERT(op == Token::EQ || op == Token::EQ_STRICT); |
4850 AddInstruction(new(zone()) HCheckNonSmi(left)); | 4863 AddInstruction(new(zone()) HCheckNonSmi(left)); |
4851 AddInstruction(HCheckInstanceType::NewIsSymbol(left)); | 4864 AddInstruction(HCheckInstanceType::NewIsSymbol(left)); |
4852 AddInstruction(new(zone()) HCheckNonSmi(right)); | 4865 AddInstruction(new(zone()) HCheckNonSmi(right)); |
(...skipping 1276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6129 } | 6142 } |
6130 } | 6143 } |
6131 | 6144 |
6132 #ifdef DEBUG | 6145 #ifdef DEBUG |
6133 if (graph_ != NULL) graph_->Verify(); | 6146 if (graph_ != NULL) graph_->Verify(); |
6134 if (allocator_ != NULL) allocator_->Verify(); | 6147 if (allocator_ != NULL) allocator_->Verify(); |
6135 #endif | 6148 #endif |
6136 } | 6149 } |
6137 | 6150 |
6138 } } // namespace v8::internal | 6151 } } // namespace v8::internal |
OLD | NEW |