| 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 2235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2246 HStackCheckEliminator sce(graph()); | 2246 HStackCheckEliminator sce(graph()); |
| 2247 sce.Process(); | 2247 sce.Process(); |
| 2248 | 2248 |
| 2249 // Perform common subexpression elimination and loop-invariant code motion. | 2249 // Perform common subexpression elimination and loop-invariant code motion. |
| 2250 if (FLAG_use_gvn) { | 2250 if (FLAG_use_gvn) { |
| 2251 HPhase phase("Global value numbering", graph()); | 2251 HPhase phase("Global value numbering", graph()); |
| 2252 HGlobalValueNumberer gvn(graph(), info()); | 2252 HGlobalValueNumberer gvn(graph(), info()); |
| 2253 gvn.Analyze(); | 2253 gvn.Analyze(); |
| 2254 } | 2254 } |
| 2255 | 2255 |
| 2256 // Replace the results of check instructions with the original value, if the |
| 2257 // result is used. This is safe now, since we don't do code motion after this |
| 2258 // point. It enables better register allocation since the value produced by |
| 2259 // check instructions is really a copy of the original value. |
| 2260 graph()->ReplaceCheckedValues(); |
| 2261 |
| 2256 return graph(); | 2262 return graph(); |
| 2257 } | 2263 } |
| 2258 | 2264 |
| 2259 | 2265 |
| 2266 void HGraph::ReplaceCheckedValues() { |
| 2267 HPhase phase("Replace checked values", this); |
| 2268 for (int i = 0; i < blocks()->length(); ++i) { |
| 2269 HInstruction* instr = blocks()->at(i)->first(); |
| 2270 while (instr != NULL) { |
| 2271 if (instr->IsBoundsCheck()) { |
| 2272 // Replace all uses of the checked value with the original input. |
| 2273 ASSERT(instr->UseCount() > 0); |
| 2274 instr->ReplaceAllUsesWith(HBoundsCheck::cast(instr)->index()); |
| 2275 } |
| 2276 instr = instr->next(); |
| 2277 } |
| 2278 } |
| 2279 } |
| 2280 |
| 2281 |
| 2260 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 2282 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 2261 ASSERT(current_block() != NULL); | 2283 ASSERT(current_block() != NULL); |
| 2262 current_block()->AddInstruction(instr); | 2284 current_block()->AddInstruction(instr); |
| 2263 return instr; | 2285 return instr; |
| 2264 } | 2286 } |
| 2265 | 2287 |
| 2266 | 2288 |
| 2267 void HGraphBuilder::AddSimulate(int id) { | 2289 void HGraphBuilder::AddSimulate(int id) { |
| 2268 ASSERT(current_block() != NULL); | 2290 ASSERT(current_block() != NULL); |
| 2269 current_block()->AddSimulate(id); | 2291 current_block()->AddSimulate(id); |
| (...skipping 1416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3686 HValue* key, | 3708 HValue* key, |
| 3687 Property* expr) { | 3709 Property* expr) { |
| 3688 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); | 3710 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); |
| 3689 AddInstruction(new(zone()) HCheckNonSmi(object)); | 3711 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3690 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3712 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 3691 ASSERT(map->has_fast_elements()); | 3713 ASSERT(map->has_fast_elements()); |
| 3692 AddInstruction(new(zone()) HCheckMap(object, map)); | 3714 AddInstruction(new(zone()) HCheckMap(object, map)); |
| 3693 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); | 3715 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); |
| 3694 HLoadElements* elements = new(zone()) HLoadElements(object); | 3716 HLoadElements* elements = new(zone()) HLoadElements(object); |
| 3695 HInstruction* length = NULL; | 3717 HInstruction* length = NULL; |
| 3718 HInstruction* checked_key = NULL; |
| 3696 if (is_array) { | 3719 if (is_array) { |
| 3697 length = AddInstruction(new(zone()) HJSArrayLength(object)); | 3720 length = AddInstruction(new(zone()) HJSArrayLength(object)); |
| 3698 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3721 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3699 AddInstruction(elements); | 3722 AddInstruction(elements); |
| 3700 } else { | 3723 } else { |
| 3701 AddInstruction(elements); | 3724 AddInstruction(elements); |
| 3702 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 3725 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
| 3703 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3726 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3704 } | 3727 } |
| 3705 return new(zone()) HLoadKeyedFastElement(elements, key); | 3728 return new(zone()) HLoadKeyedFastElement(elements, checked_key); |
| 3706 } | 3729 } |
| 3707 | 3730 |
| 3708 | 3731 |
| 3709 HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement( | 3732 HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement( |
| 3710 HValue* object, | 3733 HValue* object, |
| 3711 HValue* key, | 3734 HValue* key, |
| 3712 Property* expr) { | 3735 Property* expr) { |
| 3713 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); | 3736 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); |
| 3714 AddInstruction(new(zone()) HCheckNonSmi(object)); | 3737 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3715 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3738 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 3716 ASSERT(!map->has_fast_elements()); | 3739 ASSERT(!map->has_fast_elements()); |
| 3717 ASSERT(map->has_external_array_elements()); | 3740 ASSERT(map->has_external_array_elements()); |
| 3718 AddInstruction(new(zone()) HCheckMap(object, map)); | 3741 AddInstruction(new(zone()) HCheckMap(object, map)); |
| 3719 HLoadElements* elements = new(zone()) HLoadElements(object); | 3742 HLoadElements* elements = new(zone()) HLoadElements(object); |
| 3720 AddInstruction(elements); | 3743 AddInstruction(elements); |
| 3721 HInstruction* length = new(zone()) HExternalArrayLength(elements); | 3744 HInstruction* length = new(zone()) HExternalArrayLength(elements); |
| 3722 AddInstruction(length); | 3745 AddInstruction(length); |
| 3723 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3746 HInstruction* checked_key = |
| 3747 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3724 HLoadExternalArrayPointer* external_elements = | 3748 HLoadExternalArrayPointer* external_elements = |
| 3725 new(zone()) HLoadExternalArrayPointer(elements); | 3749 new(zone()) HLoadExternalArrayPointer(elements); |
| 3726 AddInstruction(external_elements); | 3750 AddInstruction(external_elements); |
| 3727 HLoadKeyedSpecializedArrayElement* pixel_array_value = | 3751 HLoadKeyedSpecializedArrayElement* pixel_array_value = |
| 3728 new(zone()) HLoadKeyedSpecializedArrayElement( | 3752 new(zone()) HLoadKeyedSpecializedArrayElement( |
| 3729 external_elements, key, expr->external_array_type()); | 3753 external_elements, checked_key, expr->external_array_type()); |
| 3730 return pixel_array_value; | 3754 return pixel_array_value; |
| 3731 } | 3755 } |
| 3732 | 3756 |
| 3733 | 3757 |
| 3734 HInstruction* HGraphBuilder::BuildLoadKeyed(HValue* obj, | 3758 HInstruction* HGraphBuilder::BuildLoadKeyed(HValue* obj, |
| 3735 HValue* key, | 3759 HValue* key, |
| 3736 Property* prop) { | 3760 Property* prop) { |
| 3737 if (prop->IsMonomorphic()) { | 3761 if (prop->IsMonomorphic()) { |
| 3738 Handle<Map> receiver_type(prop->GetMonomorphicReceiverType()); | 3762 Handle<Map> receiver_type(prop->GetMonomorphicReceiverType()); |
| 3739 // An object has either fast elements or pixel array elements, but never | 3763 // An object has either fast elements or pixel array elements, but never |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3774 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 3798 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
| 3775 AddInstruction(new(zone()) HCheckMap( | 3799 AddInstruction(new(zone()) HCheckMap( |
| 3776 elements, isolate()->factory()->fixed_array_map())); | 3800 elements, isolate()->factory()->fixed_array_map())); |
| 3777 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); | 3801 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); |
| 3778 HInstruction* length = NULL; | 3802 HInstruction* length = NULL; |
| 3779 if (is_array) { | 3803 if (is_array) { |
| 3780 length = AddInstruction(new(zone()) HJSArrayLength(object)); | 3804 length = AddInstruction(new(zone()) HJSArrayLength(object)); |
| 3781 } else { | 3805 } else { |
| 3782 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 3806 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
| 3783 } | 3807 } |
| 3784 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3808 HInstruction* checked_key = |
| 3785 return new(zone()) HStoreKeyedFastElement(elements, key, val); | 3809 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3810 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); |
| 3786 } | 3811 } |
| 3787 | 3812 |
| 3788 | 3813 |
| 3789 HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement( | 3814 HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement( |
| 3790 HValue* object, | 3815 HValue* object, |
| 3791 HValue* key, | 3816 HValue* key, |
| 3792 HValue* val, | 3817 HValue* val, |
| 3793 Expression* expr) { | 3818 Expression* expr) { |
| 3794 ASSERT(expr->IsMonomorphic()); | 3819 ASSERT(expr->IsMonomorphic()); |
| 3795 AddInstruction(new(zone()) HCheckNonSmi(object)); | 3820 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3796 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3821 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 3797 ASSERT(!map->has_fast_elements()); | 3822 ASSERT(!map->has_fast_elements()); |
| 3798 ASSERT(map->has_external_array_elements()); | 3823 ASSERT(map->has_external_array_elements()); |
| 3799 AddInstruction(new(zone()) HCheckMap(object, map)); | 3824 AddInstruction(new(zone()) HCheckMap(object, map)); |
| 3800 HLoadElements* elements = new(zone()) HLoadElements(object); | 3825 HLoadElements* elements = new(zone()) HLoadElements(object); |
| 3801 AddInstruction(elements); | 3826 AddInstruction(elements); |
| 3802 HInstruction* length = AddInstruction( | 3827 HInstruction* length = AddInstruction( |
| 3803 new(zone()) HExternalArrayLength(elements)); | 3828 new(zone()) HExternalArrayLength(elements)); |
| 3804 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3829 HInstruction* checked_key = |
| 3830 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3805 HLoadExternalArrayPointer* external_elements = | 3831 HLoadExternalArrayPointer* external_elements = |
| 3806 new(zone()) HLoadExternalArrayPointer(elements); | 3832 new(zone()) HLoadExternalArrayPointer(elements); |
| 3807 AddInstruction(external_elements); | 3833 AddInstruction(external_elements); |
| 3808 if (expr->external_array_type() == kExternalPixelArray) { | 3834 if (expr->external_array_type() == kExternalPixelArray) { |
| 3809 HClampToUint8* clamp = new(zone()) HClampToUint8(val); | 3835 HClampToUint8* clamp = new(zone()) HClampToUint8(val); |
| 3810 AddInstruction(clamp); | 3836 AddInstruction(clamp); |
| 3811 val = clamp; | 3837 val = clamp; |
| 3812 } | 3838 } |
| 3813 return new(zone()) HStoreKeyedSpecializedArrayElement( | 3839 return new(zone()) HStoreKeyedSpecializedArrayElement( |
| 3814 external_elements, | 3840 external_elements, |
| 3815 key, | 3841 checked_key, |
| 3816 val, | 3842 val, |
| 3817 expr->external_array_type()); | 3843 expr->external_array_type()); |
| 3818 } | 3844 } |
| 3819 | 3845 |
| 3820 | 3846 |
| 3821 HInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object, | 3847 HInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object, |
| 3822 HValue* key, | 3848 HValue* key, |
| 3823 HValue* value, | 3849 HValue* value, |
| 3824 Expression* expr) { | 3850 Expression* expr) { |
| 3825 if (expr->IsMonomorphic()) { | 3851 if (expr->IsMonomorphic()) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3856 result = new(zone()) HArgumentsLength(elements); | 3882 result = new(zone()) HArgumentsLength(elements); |
| 3857 } else { | 3883 } else { |
| 3858 Push(graph()->GetArgumentsObject()); | 3884 Push(graph()->GetArgumentsObject()); |
| 3859 VisitForValue(expr->key()); | 3885 VisitForValue(expr->key()); |
| 3860 if (HasStackOverflow() || current_block() == NULL) return true; | 3886 if (HasStackOverflow() || current_block() == NULL) return true; |
| 3861 HValue* key = Pop(); | 3887 HValue* key = Pop(); |
| 3862 Drop(1); // Arguments object. | 3888 Drop(1); // Arguments object. |
| 3863 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 3889 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| 3864 HInstruction* length = AddInstruction( | 3890 HInstruction* length = AddInstruction( |
| 3865 new(zone()) HArgumentsLength(elements)); | 3891 new(zone()) HArgumentsLength(elements)); |
| 3866 AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3892 HInstruction* checked_key = |
| 3867 result = new(zone()) HAccessArgumentsAt(elements, length, key); | 3893 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3894 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
| 3868 } | 3895 } |
| 3869 ast_context()->ReturnInstruction(result, expr->id()); | 3896 ast_context()->ReturnInstruction(result, expr->id()); |
| 3870 return true; | 3897 return true; |
| 3871 } | 3898 } |
| 3872 | 3899 |
| 3873 | 3900 |
| 3874 void HGraphBuilder::VisitProperty(Property* expr) { | 3901 void HGraphBuilder::VisitProperty(Property* expr) { |
| 3875 ASSERT(!HasStackOverflow()); | 3902 ASSERT(!HasStackOverflow()); |
| 3876 ASSERT(current_block() != NULL); | 3903 ASSERT(current_block() != NULL); |
| 3877 ASSERT(current_block()->HasPredecessor()); | 3904 ASSERT(current_block()->HasPredecessor()); |
| (...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4947 return new(zone()) HCompareSymbolEq(left, right, op); | 4974 return new(zone()) HCompareSymbolEq(left, right, op); |
| 4948 } | 4975 } |
| 4949 | 4976 |
| 4950 | 4977 |
| 4951 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, | 4978 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, |
| 4952 HValue* index) { | 4979 HValue* index) { |
| 4953 AddInstruction(new(zone()) HCheckNonSmi(string)); | 4980 AddInstruction(new(zone()) HCheckNonSmi(string)); |
| 4954 AddInstruction(HCheckInstanceType::NewIsString(string)); | 4981 AddInstruction(HCheckInstanceType::NewIsString(string)); |
| 4955 HStringLength* length = new(zone()) HStringLength(string); | 4982 HStringLength* length = new(zone()) HStringLength(string); |
| 4956 AddInstruction(length); | 4983 AddInstruction(length); |
| 4957 AddInstruction(new(zone()) HBoundsCheck(index, length)); | 4984 HInstruction* checked_index = |
| 4958 return new(zone()) HStringCharCodeAt(string, index); | 4985 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
| 4986 return new(zone()) HStringCharCodeAt(string, checked_index); |
| 4959 } | 4987 } |
| 4960 | 4988 |
| 4961 | 4989 |
| 4962 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, | 4990 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
| 4963 HValue* left, | 4991 HValue* left, |
| 4964 HValue* right) { | 4992 HValue* right) { |
| 4965 TypeInfo info = oracle()->BinaryType(expr); | 4993 TypeInfo info = oracle()->BinaryType(expr); |
| 4966 HInstruction* instr = BuildBinaryOperation(expr->op(), left, right, info); | 4994 HInstruction* instr = BuildBinaryOperation(expr->op(), left, right, info); |
| 4967 // If we hit an uninitialized binary op stub we will get type info | 4995 // If we hit an uninitialized binary op stub we will get type info |
| 4968 // for a smi operation. If one of the operands is a constant string | 4996 // for a smi operation. If one of the operands is a constant string |
| (...skipping 1261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6230 } | 6258 } |
| 6231 } | 6259 } |
| 6232 | 6260 |
| 6233 #ifdef DEBUG | 6261 #ifdef DEBUG |
| 6234 if (graph_ != NULL) graph_->Verify(); | 6262 if (graph_ != NULL) graph_->Verify(); |
| 6235 if (allocator_ != NULL) allocator_->Verify(); | 6263 if (allocator_ != NULL) allocator_->Verify(); |
| 6236 #endif | 6264 #endif |
| 6237 } | 6265 } |
| 6238 | 6266 |
| 6239 } } // namespace v8::internal | 6267 } } // namespace v8::internal |
| OLD | NEW |