Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: src/hydrogen.cc

Issue 10209027: Implement tracking and optimizations of packed arrays. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: New upload Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 1666 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 bool hoisted = false; 1677 bool hoisted = false;
1678 if (instr->CheckFlag(HValue::kUseGVN)) { 1678 if (instr->CheckFlag(HValue::kUseGVN)) {
1679 TraceGVN("Checking instruction %d (%s) %s. Loop %s\n", 1679 TraceGVN("Checking instruction %d (%s) %s. Loop %s\n",
1680 instr->id(), 1680 instr->id(),
1681 instr->Mnemonic(), 1681 instr->Mnemonic(),
1682 *GetGVNFlagsString(instr->gvn_flags()), 1682 *GetGVNFlagsString(instr->gvn_flags()),
1683 *GetGVNFlagsString(loop_kills)); 1683 *GetGVNFlagsString(loop_kills));
1684 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); 1684 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
1685 if (instr->IsTransitionElementsKind()) { 1685 if (instr->IsTransitionElementsKind()) {
1686 // It's possible to hoist transitions out of a loop as long as the 1686 // It's possible to hoist transitions out of a loop as long as the
1687 // hoisting wouldn't move the transition past a DependsOn of one of it's 1687 // hoisting wouldn't move the transition past a DependsOn on anything it
1688 // changes or any instructions that might change an objects map or 1688 // changes.
1689 // elements contents.
1690 GVNFlagSet changes = instr->ChangesFlags();
1691 GVNFlagSet hoist_depends_blockers = 1689 GVNFlagSet hoist_depends_blockers =
1692 HValue::ConvertChangesToDependsFlags(changes); 1690 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags());
1691
1693 // In addition to not hoisting transitions above other instructions that 1692 // In addition to not hoisting transitions above other instructions that
1694 // change dependencies that the transition changes, it must not be 1693 // change dependencies that the transition changes, it must not be
1695 // hoisted above map changes and stores to an elements backing store 1694 // hoisted above element pointer changes, elements kind changes, or
1696 // that the transition might change. 1695 // changes to array contents that need to be made before the transition
1697 GVNFlagSet hoist_change_blockers = changes; 1696 // converts the elements buffer.
1698 hoist_change_blockers.Add(kChangesMaps); 1697 GVNFlagSet hoist_change_blockers;
1698 hoist_change_blockers.Add(kChangesElementsKind);
1699 HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr); 1699 HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr);
1700 if (trans->original_map()->has_fast_double_elements()) { 1700 if (trans->original_map()->has_fast_double_elements()) {
1701 hoist_change_blockers.Add(kChangesElementsPointer);
1701 hoist_change_blockers.Add(kChangesDoubleArrayElements); 1702 hoist_change_blockers.Add(kChangesDoubleArrayElements);
1702 } 1703 }
1703 if (trans->transitioned_map()->has_fast_double_elements()) { 1704 if (trans->transitioned_map()->has_fast_double_elements()) {
1705 hoist_change_blockers.Add(kChangesElementsPointer);
1704 hoist_change_blockers.Add(kChangesArrayElements); 1706 hoist_change_blockers.Add(kChangesArrayElements);
1705 } 1707 }
1706 TraceGVN("Checking dependencies on HTransitionElementsKind %d (%s) " 1708 TraceGVN("Checking dependencies on HTransitionElementsKind %d (%s) "
1707 "hoist blockers: %s %s; " 1709 "hoist blockers: %s %s; "
1708 "first-time accumulated: %s %s\n", 1710 "first-time accumulated: %s %s\n",
1709 instr->id(), 1711 instr->id(),
1710 instr->Mnemonic(), 1712 instr->Mnemonic(),
1711 *GetGVNFlagsString(hoist_depends_blockers), 1713 *GetGVNFlagsString(hoist_depends_blockers),
1712 *GetGVNFlagsString(hoist_change_blockers), 1714 *GetGVNFlagsString(hoist_change_blockers),
1713 *GetGVNFlagsString(*first_time_depends), 1715 *GetGVNFlagsString(*first_time_depends),
1714 *GetGVNFlagsString(*first_time_changes)); 1716 *GetGVNFlagsString(*first_time_changes));
1717
1715 // It's possible to hoist transition from the current loop loop only if 1718 // It's possible to hoist transition from the current loop loop only if
1716 // they dominate all of the successor blocks in the same loop and there 1719 // they dominate all of the successor blocks in the same loop and there
1717 // are not any instructions that have Changes/DependsOn that intervene 1720 // are not any instructions that have Changes/DependsOn that intervene
1718 // between it and the beginning of the loop header. 1721 // between it and the beginning of the loop header.
1719 bool in_nested_loop = block != loop_header && 1722 bool in_nested_loop = block != loop_header &&
1720 ((block->parent_loop_header() != loop_header) || 1723 ((block->parent_loop_header() != loop_header) ||
1721 block->IsLoopHeader()); 1724 block->IsLoopHeader());
1722 can_hoist = !in_nested_loop && 1725 can_hoist = !in_nested_loop &&
1723 block->IsLoopSuccessorDominator() && 1726 block->IsLoopSuccessorDominator() &&
1724 !first_time_depends->ContainsAnyOf(hoist_depends_blockers) && 1727 !first_time_depends->ContainsAnyOf(hoist_depends_blockers) &&
(...skipping 1820 matching lines...) Expand 10 before | Expand all | Expand 10 after
3545 3548
3546 set_current_block(loop_successor); 3549 set_current_block(loop_successor);
3547 Drop(5); 3550 Drop(5);
3548 3551
3549 set_current_block(loop_body); 3552 set_current_block(loop_body);
3550 3553
3551 HValue* key = AddInstruction( 3554 HValue* key = AddInstruction(
3552 new(zone()) HLoadKeyedFastElement( 3555 new(zone()) HLoadKeyedFastElement(
3553 environment()->ExpressionStackAt(2), // Enum cache. 3556 environment()->ExpressionStackAt(2), // Enum cache.
3554 environment()->ExpressionStackAt(0), // Iteration index. 3557 environment()->ExpressionStackAt(0), // Iteration index.
3555 HLoadKeyedFastElement::OMIT_HOLE_CHECK)); 3558 OMIT_HOLE_CHECK));
3556 3559
3557 // Check if the expected map still matches that of the enumerable. 3560 // Check if the expected map still matches that of the enumerable.
3558 // If not just deoptimize. 3561 // If not just deoptimize.
3559 AddInstruction(new(zone()) HCheckMapValue( 3562 AddInstruction(new(zone()) HCheckMapValue(
3560 environment()->ExpressionStackAt(4), 3563 environment()->ExpressionStackAt(4),
3561 environment()->ExpressionStackAt(3))); 3564 environment()->ExpressionStackAt(3)));
3562 3565
3563 Bind(each_var, key); 3566 Bind(each_var, key);
3564 3567
3565 BreakAndContinueInfo break_info(stmt, 5); 3568 BreakAndContinueInfo break_info(stmt, 5);
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
3836 int* max_properties, 3839 int* max_properties,
3837 int* total_size) { 3840 int* total_size) {
3838 ASSERT(max_depth >= 0 && *max_properties >= 0); 3841 ASSERT(max_depth >= 0 && *max_properties >= 0);
3839 if (max_depth == 0) return false; 3842 if (max_depth == 0) return false;
3840 3843
3841 Handle<FixedArrayBase> elements(boilerplate->elements()); 3844 Handle<FixedArrayBase> elements(boilerplate->elements());
3842 if (elements->length() > 0 && 3845 if (elements->length() > 0 &&
3843 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { 3846 elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) {
3844 if (boilerplate->HasFastDoubleElements()) { 3847 if (boilerplate->HasFastDoubleElements()) {
3845 *total_size += FixedDoubleArray::SizeFor(elements->length()); 3848 *total_size += FixedDoubleArray::SizeFor(elements->length());
3846 } else if (boilerplate->HasFastElements()) { 3849 } else if (boilerplate->HasFastObjectElements()) {
3847 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); 3850 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
3848 int length = elements->length(); 3851 int length = elements->length();
3849 for (int i = 0; i < length; i++) { 3852 for (int i = 0; i < length; i++) {
3850 if ((*max_properties)-- == 0) return false; 3853 if ((*max_properties)-- == 0) return false;
3851 Handle<Object> value(fast_elements->get(i)); 3854 Handle<Object> value(fast_elements->get(i));
3852 if (value->IsJSObject()) { 3855 if (value->IsJSObject()) {
3853 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 3856 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
3854 if (!IsFastLiteral(value_object, 3857 if (!IsFastLiteral(value_object,
3855 max_depth - 1, 3858 max_depth - 1,
3856 max_properties, 3859 max_properties,
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
4043 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); 4046 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
4044 4047
4045 elements = new(zone()) HLoadElements(literal); 4048 elements = new(zone()) HLoadElements(literal);
4046 AddInstruction(elements); 4049 AddInstruction(elements);
4047 4050
4048 HValue* key = AddInstruction( 4051 HValue* key = AddInstruction(
4049 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), 4052 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
4050 Representation::Integer32())); 4053 Representation::Integer32()));
4051 4054
4052 switch (boilerplate_elements_kind) { 4055 switch (boilerplate_elements_kind) {
4053 case FAST_SMI_ONLY_ELEMENTS: 4056 case FAST_SMI_ELEMENTS:
4057 case FAST_HOLEY_SMI_ELEMENTS:
4054 // Smi-only arrays need a smi check. 4058 // Smi-only arrays need a smi check.
4055 AddInstruction(new(zone()) HCheckSmi(value)); 4059 AddInstruction(new(zone()) HCheckSmi(value));
4056 // Fall through. 4060 // Fall through.
4057 case FAST_ELEMENTS: 4061 case FAST_ELEMENTS:
4062 case FAST_HOLEY_ELEMENTS:
4058 AddInstruction(new(zone()) HStoreKeyedFastElement( 4063 AddInstruction(new(zone()) HStoreKeyedFastElement(
4059 elements, 4064 elements,
4060 key, 4065 key,
4061 value, 4066 value,
4062 boilerplate_elements_kind)); 4067 boilerplate_elements_kind));
4063 break; 4068 break;
4064 case FAST_DOUBLE_ELEMENTS: 4069 case FAST_DOUBLE_ELEMENTS:
4070 case FAST_HOLEY_DOUBLE_ELEMENTS:
4065 AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements, 4071 AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements,
4066 key, 4072 key,
4067 value)); 4073 value));
4068 break; 4074 break;
4069 default: 4075 default:
4070 UNREACHABLE(); 4076 UNREACHABLE();
4071 break; 4077 break;
4072 } 4078 }
4073 4079
4074 AddSimulate(expr->GetIdForElement(i)); 4080 AddSimulate(expr->GetIdForElement(i));
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
4812 val, 4818 val,
4813 Representation::Integer32(), 4819 Representation::Integer32(),
4814 true, // Truncate to int32. 4820 true, // Truncate to int32.
4815 false)); // Don't deoptimize undefined (irrelevant here). 4821 false)); // Don't deoptimize undefined (irrelevant here).
4816 } 4822 }
4817 break; 4823 break;
4818 } 4824 }
4819 case EXTERNAL_FLOAT_ELEMENTS: 4825 case EXTERNAL_FLOAT_ELEMENTS:
4820 case EXTERNAL_DOUBLE_ELEMENTS: 4826 case EXTERNAL_DOUBLE_ELEMENTS:
4821 break; 4827 break;
4822 case FAST_SMI_ONLY_ELEMENTS: 4828 case FAST_SMI_ELEMENTS:
4823 case FAST_ELEMENTS: 4829 case FAST_ELEMENTS:
4824 case FAST_DOUBLE_ELEMENTS: 4830 case FAST_DOUBLE_ELEMENTS:
4831 case FAST_HOLEY_SMI_ELEMENTS:
4832 case FAST_HOLEY_ELEMENTS:
4833 case FAST_HOLEY_DOUBLE_ELEMENTS:
4825 case DICTIONARY_ELEMENTS: 4834 case DICTIONARY_ELEMENTS:
4826 case NON_STRICT_ARGUMENTS_ELEMENTS: 4835 case NON_STRICT_ARGUMENTS_ELEMENTS:
4827 UNREACHABLE(); 4836 UNREACHABLE();
4828 break; 4837 break;
4829 } 4838 }
4830 return new(zone()) HStoreKeyedSpecializedArrayElement( 4839 return new(zone()) HStoreKeyedSpecializedArrayElement(
4831 external_elements, checked_key, val, elements_kind); 4840 external_elements, checked_key, val, elements_kind);
4832 } else { 4841 } else {
4833 ASSERT(val == NULL); 4842 ASSERT(val == NULL);
4834 return new(zone()) HLoadKeyedSpecializedArrayElement( 4843 return new(zone()) HLoadKeyedSpecializedArrayElement(
4835 external_elements, checked_key, elements_kind); 4844 external_elements, checked_key, elements_kind);
4836 } 4845 }
4837 } 4846 }
4838 4847
4839 4848
4840 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, 4849 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
4841 HValue* checked_key, 4850 HValue* checked_key,
4842 HValue* val, 4851 HValue* val,
4843 ElementsKind elements_kind, 4852 ElementsKind elements_kind,
4844 bool is_store) { 4853 bool is_store) {
4845 if (is_store) { 4854 if (is_store) {
4846 ASSERT(val != NULL); 4855 ASSERT(val != NULL);
4847 switch (elements_kind) { 4856 switch (elements_kind) {
4848 case FAST_DOUBLE_ELEMENTS: 4857 case FAST_DOUBLE_ELEMENTS:
4858 case FAST_HOLEY_DOUBLE_ELEMENTS:
4849 return new(zone()) HStoreKeyedFastDoubleElement( 4859 return new(zone()) HStoreKeyedFastDoubleElement(
4850 elements, checked_key, val); 4860 elements, checked_key, val);
4851 case FAST_SMI_ONLY_ELEMENTS: 4861 case FAST_SMI_ELEMENTS:
4862 case FAST_HOLEY_SMI_ELEMENTS:
4852 // Smi-only arrays need a smi check. 4863 // Smi-only arrays need a smi check.
4853 AddInstruction(new(zone()) HCheckSmi(val)); 4864 AddInstruction(new(zone()) HCheckSmi(val));
4854 // Fall through. 4865 // Fall through.
4855 case FAST_ELEMENTS: 4866 case FAST_ELEMENTS:
4867 case FAST_HOLEY_ELEMENTS:
4856 return new(zone()) HStoreKeyedFastElement( 4868 return new(zone()) HStoreKeyedFastElement(
4857 elements, checked_key, val, elements_kind); 4869 elements, checked_key, val, elements_kind);
4858 default: 4870 default:
4859 UNREACHABLE(); 4871 UNREACHABLE();
4860 return NULL; 4872 return NULL;
4861 } 4873 }
4862 } 4874 }
4863 // It's an element load (!is_store). 4875 // It's an element load (!is_store).
4864 if (elements_kind == FAST_DOUBLE_ELEMENTS) { 4876 HoleCheckMode mode = IsFastPackedElementsKind(elements_kind) ?
4865 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); 4877 OMIT_HOLE_CHECK :
4866 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS. 4878 PERFORM_HOLE_CHECK;
4867 return new(zone()) HLoadKeyedFastElement(elements, checked_key); 4879 if (IsFastDoubleElementsKind(elements_kind)) {
4880 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key, mode);
4881 } else { // Smi or Object elements.
4882 return new(zone()) HLoadKeyedFastElement(elements, checked_key, mode);
4868 } 4883 }
4869 } 4884 }
4870 4885
4871 4886
4872 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, 4887 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
4873 HValue* key, 4888 HValue* key,
4874 HValue* val, 4889 HValue* val,
4890 HValue* dependency,
4875 Handle<Map> map, 4891 Handle<Map> map,
4876 bool is_store) { 4892 bool is_store) {
4877 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMaps(object, map)); 4893 HInstruction* mapcheck = AddInstruction(new(zone())
4878 bool fast_smi_only_elements = map->has_fast_smi_only_elements(); 4894 HCheckMaps(object, map, dependency));
4879 bool fast_elements = map->has_fast_elements(); 4895 // No GVNFlag dependency is necessary for ElementsKind if there is an explicit
4896 // dependency on a HElementsTransition instruction. The flag can also be
4897 // removed if map to check has FAST_HOLEY_ELEMENTS, since there can be no
4898 // further ElementsKind transitions. Finally, it can be removed for stores for
4899 // FAST_ELEMENTS, since a transition to HOLEY elements won't change the
4900 // generated store code.
4901 if (dependency ||
4902 (map->elements_kind() == FAST_HOLEY_ELEMENTS) ||
4903 (map->elements_kind() == FAST_ELEMENTS && is_store)) {
4904 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
4905 }
4906 bool fast_smi_only_elements = map->has_fast_smi_elements();
4907 bool fast_elements = map->has_fast_object_elements();
4880 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 4908 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
4881 if (is_store && (fast_elements || fast_smi_only_elements)) { 4909 if (is_store && (fast_elements || fast_smi_only_elements)) {
4882 AddInstruction(new(zone()) HCheckMaps( 4910 HCheckMaps* check_cow_map = new(zone()) HCheckMaps(
4883 elements, isolate()->factory()->fixed_array_map())); 4911 elements, isolate()->factory()->fixed_array_map());
4912 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
4913 AddInstruction(check_cow_map);
4884 } 4914 }
4885 HInstruction* length = NULL; 4915 HInstruction* length = NULL;
4886 HInstruction* checked_key = NULL; 4916 HInstruction* checked_key = NULL;
4887 if (map->has_external_array_elements()) { 4917 if (map->has_external_array_elements()) {
4888 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 4918 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
4889 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4919 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4890 HLoadExternalArrayPointer* external_elements = 4920 HLoadExternalArrayPointer* external_elements =
4891 new(zone()) HLoadExternalArrayPointer(elements); 4921 new(zone()) HLoadExternalArrayPointer(elements);
4892 AddInstruction(external_elements); 4922 AddInstruction(external_elements);
4893 return BuildExternalArrayElementAccess(external_elements, checked_key, 4923 return BuildExternalArrayElementAccess(external_elements, checked_key,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
4926 type_todo[i] = false; 4956 type_todo[i] = false;
4927 } 4957 }
4928 4958
4929 // Elements_kind transition support. 4959 // Elements_kind transition support.
4930 MapHandleList transition_target(maps->length()); 4960 MapHandleList transition_target(maps->length());
4931 // Collect possible transition targets. 4961 // Collect possible transition targets.
4932 MapHandleList possible_transitioned_maps(maps->length()); 4962 MapHandleList possible_transitioned_maps(maps->length());
4933 for (int i = 0; i < maps->length(); ++i) { 4963 for (int i = 0; i < maps->length(); ++i) {
4934 Handle<Map> map = maps->at(i); 4964 Handle<Map> map = maps->at(i);
4935 ElementsKind elements_kind = map->elements_kind(); 4965 ElementsKind elements_kind = map->elements_kind();
4936 if (elements_kind == FAST_DOUBLE_ELEMENTS || 4966 if (IsFastElementsKind(elements_kind) &&
4937 elements_kind == FAST_ELEMENTS) { 4967 elements_kind != GetInitialFastElementsKind()) {
4938 possible_transitioned_maps.Add(map); 4968 possible_transitioned_maps.Add(map);
4939 } 4969 }
4940 } 4970 }
4941 // Get transition target for each map (NULL == no transition). 4971 // Get transition target for each map (NULL == no transition).
4942 for (int i = 0; i < maps->length(); ++i) { 4972 for (int i = 0; i < maps->length(); ++i) {
4943 Handle<Map> map = maps->at(i); 4973 Handle<Map> map = maps->at(i);
4944 Handle<Map> transitioned_map = 4974 Handle<Map> transitioned_map =
4945 map->FindTransitionedMap(&possible_transitioned_maps); 4975 map->FindTransitionedMap(&possible_transitioned_maps);
4946 transition_target.Add(transitioned_map); 4976 transition_target.Add(transitioned_map);
4947 } 4977 }
4948 4978
4949 int num_untransitionable_maps = 0; 4979 int num_untransitionable_maps = 0;
4950 Handle<Map> untransitionable_map; 4980 Handle<Map> untransitionable_map;
4981 HTransitionElementsKind* transition = NULL;
4951 for (int i = 0; i < maps->length(); ++i) { 4982 for (int i = 0; i < maps->length(); ++i) {
4952 Handle<Map> map = maps->at(i); 4983 Handle<Map> map = maps->at(i);
4953 ASSERT(map->IsMap()); 4984 ASSERT(map->IsMap());
4954 if (!transition_target.at(i).is_null()) { 4985 if (!transition_target.at(i).is_null()) {
4955 AddInstruction(new(zone()) HTransitionElementsKind( 4986 ASSERT(Map::IsValidElementsTransition(
4956 object, map, transition_target.at(i))); 4987 map->elements_kind(),
4988 transition_target.at(i)->elements_kind()));
4989 transition = new(zone()) HTransitionElementsKind(
4990 object, map, transition_target.at(i));
4991 AddInstruction(transition);
4957 } else { 4992 } else {
4958 type_todo[map->elements_kind()] = true; 4993 type_todo[map->elements_kind()] = true;
4959 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { 4994 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
4960 todo_external_array = true; 4995 todo_external_array = true;
4961 } 4996 }
4962 num_untransitionable_maps++; 4997 num_untransitionable_maps++;
4963 untransitionable_map = map; 4998 untransitionable_map = map;
4964 } 4999 }
4965 } 5000 }
4966 5001
4967 // If only one map is left after transitioning, handle this case 5002 // If only one map is left after transitioning, handle this case
4968 // monomorphically. 5003 // monomorphically.
4969 if (num_untransitionable_maps == 1) { 5004 if (num_untransitionable_maps == 1) {
4970 HInstruction* instr = NULL; 5005 HInstruction* instr = NULL;
4971 if (untransitionable_map->has_slow_elements_kind()) { 5006 if (untransitionable_map->has_slow_elements_kind()) {
4972 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 5007 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
4973 : BuildLoadKeyedGeneric(object, key)); 5008 : BuildLoadKeyedGeneric(object, key));
4974 } else { 5009 } else {
4975 instr = AddInstruction(BuildMonomorphicElementAccess( 5010 instr = AddInstruction(BuildMonomorphicElementAccess(
4976 object, key, val, untransitionable_map, is_store)); 5011 object, key, val, transition, untransitionable_map, is_store));
4977 } 5012 }
4978 *has_side_effects |= instr->HasObservableSideEffects(); 5013 *has_side_effects |= instr->HasObservableSideEffects();
4979 instr->set_position(position); 5014 instr->set_position(position);
4980 return is_store ? NULL : instr; 5015 return is_store ? NULL : instr;
4981 } 5016 }
4982 5017
4983 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); 5018 AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
4984 HBasicBlock* join = graph()->CreateBasicBlock(); 5019 HBasicBlock* join = graph()->CreateBasicBlock();
4985 5020
4986 HInstruction* elements_kind_instr = 5021 HInstruction* elements_kind_instr =
4987 AddInstruction(new(zone()) HElementsKind(object)); 5022 AddInstruction(new(zone()) HElementsKind(object));
4988 HCompareConstantEqAndBranch* elements_kind_branch = NULL; 5023 HCompareConstantEqAndBranch* elements_kind_branch = NULL;
4989 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 5024 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
4990 HLoadExternalArrayPointer* external_elements = NULL; 5025 HLoadExternalArrayPointer* external_elements = NULL;
4991 HInstruction* checked_key = NULL; 5026 HInstruction* checked_key = NULL;
4992 5027
4993 // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS, 5028 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds
4994 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external 5029 // are handled before external arrays.
4995 // arrays. 5030 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4996 STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5031 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4997 STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4998 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5032 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4999 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5033 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
5000 5034
5001 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; 5035 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND;
5002 elements_kind <= LAST_ELEMENTS_KIND; 5036 elements_kind <= LAST_ELEMENTS_KIND;
5003 elements_kind = ElementsKind(elements_kind + 1)) { 5037 elements_kind = ElementsKind(elements_kind + 1)) {
5004 // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS, 5038 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some
5005 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code 5039 // code that's executed for all external array cases.
5006 // that's executed for all external array cases.
5007 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == 5040 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
5008 LAST_ELEMENTS_KIND); 5041 LAST_ELEMENTS_KIND);
5009 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND 5042 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
5010 && todo_external_array) { 5043 && todo_external_array) {
5011 HInstruction* length = 5044 HInstruction* length =
5012 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 5045 AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
5013 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 5046 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
5014 external_elements = new(zone()) HLoadExternalArrayPointer(elements); 5047 external_elements = new(zone()) HLoadExternalArrayPointer(elements);
5015 AddInstruction(external_elements); 5048 AddInstruction(external_elements);
5016 } 5049 }
5017 if (type_todo[elements_kind]) { 5050 if (type_todo[elements_kind]) {
5018 HBasicBlock* if_true = graph()->CreateBasicBlock(); 5051 HBasicBlock* if_true = graph()->CreateBasicBlock();
5019 HBasicBlock* if_false = graph()->CreateBasicBlock(); 5052 HBasicBlock* if_false = graph()->CreateBasicBlock();
5020 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( 5053 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch(
5021 elements_kind_instr, elements_kind, Token::EQ_STRICT); 5054 elements_kind_instr, elements_kind, Token::EQ_STRICT);
5022 elements_kind_branch->SetSuccessorAt(0, if_true); 5055 elements_kind_branch->SetSuccessorAt(0, if_true);
5023 elements_kind_branch->SetSuccessorAt(1, if_false); 5056 elements_kind_branch->SetSuccessorAt(1, if_false);
5024 current_block()->Finish(elements_kind_branch); 5057 current_block()->Finish(elements_kind_branch);
5025 5058
5026 set_current_block(if_true); 5059 set_current_block(if_true);
5027 HInstruction* access; 5060 HInstruction* access;
5028 if (elements_kind == FAST_SMI_ONLY_ELEMENTS || 5061 if (IsFastElementsKind(elements_kind)) {
5029 elements_kind == FAST_ELEMENTS || 5062 if (is_store && !IsFastDoubleElementsKind(elements_kind)) {
5030 elements_kind == FAST_DOUBLE_ELEMENTS) {
5031 if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) {
5032 AddInstruction(new(zone()) HCheckMaps( 5063 AddInstruction(new(zone()) HCheckMaps(
5033 elements, isolate()->factory()->fixed_array_map(), 5064 elements, isolate()->factory()->fixed_array_map(),
5034 elements_kind_branch)); 5065 elements_kind_branch));
5035 } 5066 }
5036 // TODO(jkummerow): The need for these two blocks could be avoided 5067 // TODO(jkummerow): The need for these two blocks could be avoided
5037 // in one of two ways: 5068 // in one of two ways:
5038 // (1) Introduce ElementsKinds for JSArrays that are distinct from 5069 // (1) Introduce ElementsKinds for JSArrays that are distinct from
5039 // those for fast objects. 5070 // those for fast objects.
5040 // (2) Put the common instructions into a third "join" block. This 5071 // (2) Put the common instructions into a third "join" block. This
5041 // requires additional AST IDs that we can deopt to from inside 5072 // requires additional AST IDs that we can deopt to from inside
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
5108 bool* has_side_effects) { 5139 bool* has_side_effects) {
5109 ASSERT(!expr->IsPropertyName()); 5140 ASSERT(!expr->IsPropertyName());
5110 HInstruction* instr = NULL; 5141 HInstruction* instr = NULL;
5111 if (expr->IsMonomorphic()) { 5142 if (expr->IsMonomorphic()) {
5112 Handle<Map> map = expr->GetMonomorphicReceiverType(); 5143 Handle<Map> map = expr->GetMonomorphicReceiverType();
5113 if (map->has_slow_elements_kind()) { 5144 if (map->has_slow_elements_kind()) {
5114 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 5145 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
5115 : BuildLoadKeyedGeneric(obj, key); 5146 : BuildLoadKeyedGeneric(obj, key);
5116 } else { 5147 } else {
5117 AddInstruction(new(zone()) HCheckNonSmi(obj)); 5148 AddInstruction(new(zone()) HCheckNonSmi(obj));
5118 instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store); 5149 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store);
5119 } 5150 }
5120 } else if (expr->GetReceiverTypes() != NULL && 5151 } else if (expr->GetReceiverTypes() != NULL &&
5121 !expr->GetReceiverTypes()->is_empty()) { 5152 !expr->GetReceiverTypes()->is_empty()) {
5122 return HandlePolymorphicElementAccess( 5153 return HandlePolymorphicElementAccess(
5123 obj, key, val, expr, ast_id, position, is_store, has_side_effects); 5154 obj, key, val, expr, ast_id, position, is_store, has_side_effects);
5124 } else { 5155 } else {
5125 if (is_store) { 5156 if (is_store) {
5126 instr = BuildStoreKeyedGeneric(obj, key, val); 5157 instr = BuildStoreKeyedGeneric(obj, key, val);
5127 } else { 5158 } else {
5128 instr = BuildLoadKeyedGeneric(obj, key); 5159 instr = BuildLoadKeyedGeneric(obj, key);
(...skipping 3332 matching lines...) Expand 10 before | Expand all | Expand 10 after
8461 } 8492 }
8462 } 8493 }
8463 8494
8464 #ifdef DEBUG 8495 #ifdef DEBUG
8465 if (graph_ != NULL) graph_->Verify(false); // No full verify. 8496 if (graph_ != NULL) graph_->Verify(false); // No full verify.
8466 if (allocator_ != NULL) allocator_->Verify(); 8497 if (allocator_ != NULL) allocator_->Verify();
8467 #endif 8498 #endif
8468 } 8499 }
8469 8500
8470 } } // namespace v8::internal 8501 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | src/objects.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698