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