OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 5731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5742 } | 5742 } |
5743 } | 5743 } |
5744 | 5744 |
5745 | 5745 |
5746 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, | 5746 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, |
5747 HValue* key, | 5747 HValue* key, |
5748 HValue* val, | 5748 HValue* val, |
5749 HValue* dependency, | 5749 HValue* dependency, |
5750 Handle<Map> map, | 5750 Handle<Map> map, |
5751 bool is_store) { | 5751 bool is_store) { |
5752 HInstruction* mapcheck = | 5752 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, |
5753 AddInstruction(new(zone()) HCheckMaps(object, map, zone(), dependency)); | 5753 zone(), dependency); |
5754 AddInstruction(mapcheck); | |
5755 if (dependency) { | |
5756 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | |
5757 } | |
5758 return BuildUncheckedMonomorphicElementAccess(object, key, val, | |
5759 mapcheck, map, is_store); | |
5760 } | |
5761 | |
5762 | |
5763 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | |
5764 HValue* object, | |
5765 HValue* key, | |
5766 HValue* val, | |
5767 HCheckMaps* mapcheck, | |
5768 Handle<Map> map, | |
5769 bool is_store) { | |
5754 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 5770 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
5755 // on a HElementsTransition instruction. The flag can also be removed if the | 5771 // on a HElementsTransition instruction. The flag can also be removed if the |
5756 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 5772 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
5757 // ElementsKind transitions. Finally, the dependency can be removed for stores | 5773 // ElementsKind transitions. Finally, the dependency can be removed for stores |
5758 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 5774 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
5759 // generated store code. | 5775 // generated store code. |
5760 if (dependency || | 5776 if ((map->elements_kind() == FAST_HOLEY_ELEMENTS) || |
5761 (map->elements_kind() == FAST_HOLEY_ELEMENTS) || | |
5762 (map->elements_kind() == FAST_ELEMENTS && is_store)) { | 5777 (map->elements_kind() == FAST_ELEMENTS && is_store)) { |
5763 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 5778 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
5764 } | 5779 } |
5765 bool fast_smi_only_elements = map->has_fast_smi_elements(); | 5780 bool fast_smi_only_elements = map->has_fast_smi_elements(); |
5766 bool fast_elements = map->has_fast_object_elements(); | 5781 bool fast_elements = map->has_fast_object_elements(); |
5767 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 5782 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
5768 if (is_store && (fast_elements || fast_smi_only_elements)) { | 5783 if (is_store && (fast_elements || fast_smi_only_elements)) { |
5769 HCheckMaps* check_cow_map = new(zone()) HCheckMaps( | 5784 HCheckMaps* check_cow_map = new(zone()) HCheckMaps( |
5770 elements, isolate()->factory()->fixed_array_map(), zone()); | 5785 elements, isolate()->factory()->fixed_array_map(), zone()); |
5771 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 5786 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
(...skipping 18 matching lines...) Expand all Loading... | |
5790 HType::Smi())); | 5805 HType::Smi())); |
5791 } else { | 5806 } else { |
5792 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 5807 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
5793 } | 5808 } |
5794 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 5809 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
5795 return BuildFastElementAccess(elements, checked_key, val, | 5810 return BuildFastElementAccess(elements, checked_key, val, |
5796 map->elements_kind(), is_store); | 5811 map->elements_kind(), is_store); |
5797 } | 5812 } |
5798 | 5813 |
5799 | 5814 |
5815 HInstruction* HGraphBuilder::TryBuildConsolidatedElementLoad( | |
5816 HValue* object, | |
5817 HValue* key, | |
5818 HValue* val, | |
5819 SmallMapList* maps) { | |
5820 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | |
5821 // double), always use the "worst case" code without a transition. This is | |
5822 // much faster than transitioning the elements to the worst case, trading a | |
5823 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. | |
5824 bool has_double_maps = false; | |
5825 bool has_smi_or_object_maps = false; | |
5826 bool has_js_array_access = false; | |
5827 bool has_non_js_array_access = false; | |
5828 Handle<Map> most_general_consolidated_map; | |
5829 for (int i = 0; i < maps->length(); ++i) { | |
5830 Handle<Map> map = maps->at(i); | |
5831 // Don't allow mixing of JSArrays with JSObjects. | |
5832 if (map->instance_type() == JS_ARRAY_TYPE) { | |
5833 if (has_non_js_array_access) return NULL; | |
5834 has_js_array_access = true; | |
5835 } else if (has_js_array_access) { | |
5836 return NULL; | |
5837 } else { | |
5838 has_non_js_array_access = true; | |
5839 } | |
5840 // Don't allow mixed, incompatible elements kinds. | |
5841 if (map->has_fast_double_elements()) { | |
5842 if (has_smi_or_object_maps) return NULL; | |
5843 has_double_maps = true; | |
5844 } else if (map->has_fast_smi_or_object_elements()) { | |
5845 if (has_double_maps) return NULL; | |
5846 has_smi_or_object_maps = true; | |
5847 } else { | |
5848 return NULL; | |
5849 } | |
5850 // Remember the most general elements kind, the code for its load will | |
5851 // properly handle all of the more specific cases. | |
5852 if ((i == 0) || IsMoreGeneralElementsKindTransition( | |
5853 most_general_consolidated_map->elements_kind(), | |
5854 map->elements_kind())) { | |
5855 most_general_consolidated_map = map; | |
5856 } | |
5857 } | |
5858 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | |
5859 | |
5860 HCheckMaps* check_maps = | |
5861 new(zone()) HCheckMaps(object, maps, zone()); | |
Jakob Kummerow
2012/06/29 18:42:41
nit: fits on one line
danno
2012/07/02 11:07:14
Done.
| |
5862 AddInstruction(check_maps); | |
5863 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | |
5864 object, key, val, | |
5865 check_maps, most_general_consolidated_map, false); | |
Jakob Kummerow
2012/06/29 18:42:41
nit: fits on the same line as "object, key, val".
danno
2012/07/02 11:07:14
Done.
| |
5866 return instr; | |
5867 } | |
5868 | |
5869 | |
5800 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, | 5870 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
5801 HValue* key, | 5871 HValue* key, |
5802 HValue* val, | 5872 HValue* val, |
5803 Expression* prop, | 5873 Expression* prop, |
5804 int ast_id, | 5874 int ast_id, |
5805 int position, | 5875 int position, |
5806 bool is_store, | 5876 bool is_store, |
5807 bool* has_side_effects) { | 5877 bool* has_side_effects) { |
5808 *has_side_effects = false; | 5878 *has_side_effects = false; |
5809 AddInstruction(new(zone()) HCheckNonSmi(object)); | 5879 AddInstruction(new(zone()) HCheckNonSmi(object)); |
5810 SmallMapList* maps = prop->GetReceiverTypes(); | 5880 SmallMapList* maps = prop->GetReceiverTypes(); |
5811 bool todo_external_array = false; | 5881 bool todo_external_array = false; |
5812 | 5882 |
5883 if (!is_store) { | |
5884 HInstruction* consolidated_load = | |
5885 TryBuildConsolidatedElementLoad(object, key, val, maps); | |
5886 if (consolidated_load != NULL) { | |
5887 AddInstruction(consolidated_load); | |
5888 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | |
5889 consolidated_load->set_position(position); | |
5890 return consolidated_load; | |
5891 } | |
5892 } | |
5893 | |
5813 static const int kNumElementTypes = kElementsKindCount; | 5894 static const int kNumElementTypes = kElementsKindCount; |
5814 bool type_todo[kNumElementTypes]; | 5895 bool type_todo[kNumElementTypes]; |
5815 for (int i = 0; i < kNumElementTypes; ++i) { | 5896 for (int i = 0; i < kNumElementTypes; ++i) { |
5816 type_todo[i] = false; | 5897 type_todo[i] = false; |
5817 } | 5898 } |
5818 | 5899 |
5819 // Elements_kind transition support. | 5900 // Elements_kind transition support. |
5820 MapHandleList transition_target(maps->length()); | 5901 MapHandleList transition_target(maps->length()); |
5821 // Collect possible transition targets. | 5902 // Collect possible transition targets. |
5822 MapHandleList possible_transitioned_maps(maps->length()); | 5903 MapHandleList possible_transitioned_maps(maps->length()); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5858 untransitionable_map = map; | 5939 untransitionable_map = map; |
5859 } | 5940 } |
5860 } | 5941 } |
5861 | 5942 |
5862 // If only one map is left after transitioning, handle this case | 5943 // If only one map is left after transitioning, handle this case |
5863 // monomorphically. | 5944 // monomorphically. |
5864 if (num_untransitionable_maps == 1) { | 5945 if (num_untransitionable_maps == 1) { |
5865 HInstruction* instr = NULL; | 5946 HInstruction* instr = NULL; |
5866 if (untransitionable_map->has_slow_elements_kind()) { | 5947 if (untransitionable_map->has_slow_elements_kind()) { |
5867 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 5948 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) |
5868 : BuildLoadKeyedGeneric(object, key)); | 5949 : BuildLoadKeyedGeneric(object, key)); |
Jakob Kummerow
2012/06/29 18:42:41
nit: why this change?
danno
2012/07/02 11:07:14
Done.
| |
5869 } else { | 5950 } else { |
5870 instr = AddInstruction(BuildMonomorphicElementAccess( | 5951 instr = AddInstruction(BuildMonomorphicElementAccess( |
5871 object, key, val, transition, untransitionable_map, is_store)); | 5952 object, key, val, transition, untransitionable_map, is_store)); |
5872 } | 5953 } |
5873 *has_side_effects |= instr->HasObservableSideEffects(); | 5954 *has_side_effects |= instr->HasObservableSideEffects(); |
5874 instr->set_position(position); | 5955 instr->set_position(position); |
5875 return is_store ? NULL : instr; | 5956 return is_store ? NULL : instr; |
5876 } | 5957 } |
5877 | 5958 |
5878 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); | 5959 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); |
(...skipping 3561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9440 } | 9521 } |
9441 } | 9522 } |
9442 | 9523 |
9443 #ifdef DEBUG | 9524 #ifdef DEBUG |
9444 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9525 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
9445 if (allocator_ != NULL) allocator_->Verify(); | 9526 if (allocator_ != NULL) allocator_->Verify(); |
9446 #endif | 9527 #endif |
9447 } | 9528 } |
9448 | 9529 |
9449 } } // namespace v8::internal | 9530 } } // namespace v8::internal |
OLD | NEW |