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

Side by Side Diff: src/compiler/js-native-context-specialization.cc

Issue 2431563002: [turbofan] Track multiple maps for LoadElimination. (Closed)
Patch Set: REBASE. Address comment. Created 3 years, 11 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
« no previous file with comments | « src/compiler/js-inlining.cc ('k') | src/compiler/load-elimination.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/js-native-context-specialization.h" 5 #include "src/compiler/js-native-context-specialization.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/compilation-dependencies.h" 9 #include "src/compilation-dependencies.h"
10 #include "src/compiler/access-builder.h" 10 #include "src/compiler/access-builder.h"
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 636
637 // Check for the monomorphic case. 637 // Check for the monomorphic case.
638 if (access_infos.size() == 1) { 638 if (access_infos.size() == 1) {
639 ElementAccessInfo access_info = access_infos.front(); 639 ElementAccessInfo access_info = access_infos.front();
640 640
641 // Perform possible elements kind transitions. 641 // Perform possible elements kind transitions.
642 for (auto transition : access_info.transitions()) { 642 for (auto transition : access_info.transitions()) {
643 Handle<Map> const transition_source = transition.first; 643 Handle<Map> const transition_source = transition.first;
644 Handle<Map> const transition_target = transition.second; 644 Handle<Map> const transition_target = transition.second;
645 effect = graph()->NewNode( 645 effect = graph()->NewNode(
646 simplified()->TransitionElementsKind( 646 simplified()->TransitionElementsKind(ElementsTransition(
647 IsSimpleMapChangeTransition(transition_source->elements_kind(), 647 IsSimpleMapChangeTransition(transition_source->elements_kind(),
648 transition_target->elements_kind()) 648 transition_target->elements_kind())
649 ? ElementsTransition::kFastTransition 649 ? ElementsTransition::kFastTransition
650 : ElementsTransition::kSlowTransition), 650 : ElementsTransition::kSlowTransition,
651 receiver, jsgraph()->HeapConstant(transition_source), 651 transition_source, transition_target)),
652 jsgraph()->HeapConstant(transition_target), effect, control); 652 receiver, effect, control);
653 } 653 }
654 654
655 // TODO(turbofan): The effect/control linearization will not find a 655 // TODO(turbofan): The effect/control linearization will not find a
656 // FrameState after the StoreField or Call that is generated for the 656 // FrameState after the StoreField or Call that is generated for the
657 // elements kind transition above. This is because those operators 657 // elements kind transition above. This is because those operators
658 // don't have the kNoWrite flag on it, even though they are not 658 // don't have the kNoWrite flag on it, even though they are not
659 // observable by JavaScript. 659 // observable by JavaScript.
660 effect = graph()->NewNode(common()->Checkpoint(), frame_state, effect, 660 effect = graph()->NewNode(common()->Checkpoint(), frame_state, effect,
661 control); 661 control);
662 662
(...skipping 24 matching lines...) Expand all
687 Node* this_index = index; 687 Node* this_index = index;
688 Node* this_effect = effect; 688 Node* this_effect = effect;
689 Node* this_control = fallthrough_control; 689 Node* this_control = fallthrough_control;
690 690
691 // Perform possible elements kind transitions. 691 // Perform possible elements kind transitions.
692 for (auto transition : access_info.transitions()) { 692 for (auto transition : access_info.transitions()) {
693 Handle<Map> const transition_source = transition.first; 693 Handle<Map> const transition_source = transition.first;
694 Handle<Map> const transition_target = transition.second; 694 Handle<Map> const transition_target = transition.second;
695 this_effect = graph()->NewNode( 695 this_effect = graph()->NewNode(
696 simplified()->TransitionElementsKind( 696 simplified()->TransitionElementsKind(
697 IsSimpleMapChangeTransition( 697 ElementsTransition(IsSimpleMapChangeTransition(
698 transition_source->elements_kind(), 698 transition_source->elements_kind(),
699 transition_target->elements_kind()) 699 transition_target->elements_kind())
700 ? ElementsTransition::kFastTransition 700 ? ElementsTransition::kFastTransition
701 : ElementsTransition::kSlowTransition), 701 : ElementsTransition::kSlowTransition,
702 receiver, jsgraph()->HeapConstant(transition_source), 702 transition_source, transition_target)),
703 jsgraph()->HeapConstant(transition_target), this_effect, 703 receiver, this_effect, this_control);
704 this_control);
705 } 704 }
706 705
707 // Load the {receiver} map. 706 // Load the {receiver} map.
708 Node* receiver_map = this_effect = 707 Node* receiver_map = this_effect =
709 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), 708 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
710 receiver, this_effect, this_control); 709 receiver, this_effect, this_control);
711 710
712 // Perform map check(s) on {receiver}. 711 // Perform map check(s) on {receiver}.
713 MapList const& receiver_maps = access_info.receiver_maps(); 712 MapList const& receiver_maps = access_info.receiver_maps();
714 if (j == access_infos.size() - 1) { 713 if (j == access_infos.size() - 1) {
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 effect, control); 1171 effect, control);
1173 field_access.write_barrier_kind = kNoWriteBarrier; 1172 field_access.write_barrier_kind = kNoWriteBarrier;
1174 break; 1173 break;
1175 } 1174 }
1176 case MachineRepresentation::kTaggedPointer: { 1175 case MachineRepresentation::kTaggedPointer: {
1177 // Ensure that {value} is a HeapObject. 1176 // Ensure that {value} is a HeapObject.
1178 value = BuildCheckHeapObject(value, &effect, control); 1177 value = BuildCheckHeapObject(value, &effect, control);
1179 Handle<Map> field_map; 1178 Handle<Map> field_map;
1180 if (access_info.field_map().ToHandle(&field_map)) { 1179 if (access_info.field_map().ToHandle(&field_map)) {
1181 // Emit a map check for the value. 1180 // Emit a map check for the value.
1182 effect = graph()->NewNode(simplified()->CheckMaps(1), value, 1181 effect = graph()->NewNode(
1183 jsgraph()->HeapConstant(field_map), 1182 simplified()->CheckMaps(ZoneHandleSet<Map>(field_map)), value,
1184 effect, control); 1183 effect, control);
1185 } 1184 }
1186 field_access.write_barrier_kind = kPointerWriteBarrier; 1185 field_access.write_barrier_kind = kPointerWriteBarrier;
1187 break; 1186 break;
1188 } 1187 }
1189 case MachineRepresentation::kTagged: 1188 case MachineRepresentation::kTagged:
1190 break; 1189 break;
1191 case MachineRepresentation::kNone: 1190 case MachineRepresentation::kNone:
1192 case MachineRepresentation::kBit: 1191 case MachineRepresentation::kBit:
1193 case MachineRepresentation::kWord8: 1192 case MachineRepresentation::kWord8:
1194 case MachineRepresentation::kWord16: 1193 case MachineRepresentation::kWord16:
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 } else { 1410 } else {
1412 // Load the elements for the {receiver}. 1411 // Load the elements for the {receiver}.
1413 Node* elements = effect = graph()->NewNode( 1412 Node* elements = effect = graph()->NewNode(
1414 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, 1413 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
1415 effect, control); 1414 effect, control);
1416 1415
1417 // Don't try to store to a copy-on-write backing store. 1416 // Don't try to store to a copy-on-write backing store.
1418 if (access_mode == AccessMode::kStore && 1417 if (access_mode == AccessMode::kStore &&
1419 IsFastSmiOrObjectElementsKind(elements_kind) && 1418 IsFastSmiOrObjectElementsKind(elements_kind) &&
1420 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { 1419 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
1421 effect = 1420 effect = graph()->NewNode(simplified()->CheckMaps(ZoneHandleSet<Map>(
1422 graph()->NewNode(simplified()->CheckMaps(1), elements, 1421 factory()->fixed_array_map())),
1423 jsgraph()->FixedArrayMapConstant(), effect, control); 1422 elements, effect, control);
1424 } 1423 }
1425 1424
1426 // Check if the {receiver} is a JSArray. 1425 // Check if the {receiver} is a JSArray.
1427 bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps); 1426 bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps);
1428 1427
1429 // Load the length of the {receiver}. 1428 // Load the length of the {receiver}.
1430 Node* length = effect = 1429 Node* length = effect =
1431 receiver_is_jsarray 1430 receiver_is_jsarray
1432 ? graph()->NewNode( 1431 ? graph()->NewNode(
1433 simplified()->LoadField( 1432 simplified()->LoadField(
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1633 } 1632 }
1634 default: { 1633 default: {
1635 return *effect = graph()->NewNode(simplified()->CheckHeapObject(), 1634 return *effect = graph()->NewNode(simplified()->CheckHeapObject(),
1636 receiver, *effect, control); 1635 receiver, *effect, control);
1637 } 1636 }
1638 } 1637 }
1639 } 1638 }
1640 1639
1641 Node* JSNativeContextSpecialization::BuildCheckMaps( 1640 Node* JSNativeContextSpecialization::BuildCheckMaps(
1642 Node* receiver, Node* effect, Node* control, 1641 Node* receiver, Node* effect, Node* control,
1643 std::vector<Handle<Map>> const& maps) { 1642 std::vector<Handle<Map>> const& receiver_maps) {
1644 HeapObjectMatcher m(receiver); 1643 HeapObjectMatcher m(receiver);
1645 if (m.HasValue()) { 1644 if (m.HasValue()) {
1646 Handle<Map> receiver_map(m.Value()->map(), isolate()); 1645 Handle<Map> receiver_map(m.Value()->map(), isolate());
1647 if (receiver_map->is_stable()) { 1646 if (receiver_map->is_stable()) {
1648 for (Handle<Map> map : maps) { 1647 for (Handle<Map> map : receiver_maps) {
1649 if (map.is_identical_to(receiver_map)) { 1648 if (map.is_identical_to(receiver_map)) {
1650 dependencies()->AssumeMapStable(receiver_map); 1649 dependencies()->AssumeMapStable(receiver_map);
1651 return effect; 1650 return effect;
1652 } 1651 }
1653 } 1652 }
1654 } 1653 }
1655 } 1654 }
1656 int const map_input_count = static_cast<int>(maps.size()); 1655 ZoneHandleSet<Map> maps;
1657 int const input_count = 1 + map_input_count + 1 + 1; 1656 for (Handle<Map> map : receiver_maps) {
1658 Node** inputs = zone()->NewArray<Node*>(input_count); 1657 maps.insert(map, graph()->zone());
1659 inputs[0] = receiver;
1660 for (int i = 0; i < map_input_count; ++i) {
1661 inputs[1 + i] = jsgraph()->HeapConstant(maps[i]);
1662 } 1658 }
1663 inputs[input_count - 2] = effect; 1659 return graph()->NewNode(simplified()->CheckMaps(maps), receiver, effect,
1664 inputs[input_count - 1] = control; 1660 control);
1665 return graph()->NewNode(simplified()->CheckMaps(map_input_count), input_count,
1666 inputs);
1667 } 1661 }
1668 1662
1669 void JSNativeContextSpecialization::AssumePrototypesStable( 1663 void JSNativeContextSpecialization::AssumePrototypesStable(
1670 std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) { 1664 std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) {
1671 // Determine actual holder and perform prototype chain checks. 1665 // Determine actual holder and perform prototype chain checks.
1672 for (auto map : receiver_maps) { 1666 for (auto map : receiver_maps) {
1673 // Perform the implicit ToObject for primitives here. 1667 // Perform the implicit ToObject for primitives here.
1674 // Implemented according to ES6 section 7.3.2 GetV (V, P). 1668 // Implemented according to ES6 section 7.3.2 GetV (V, P).
1675 Handle<JSFunction> constructor; 1669 Handle<JSFunction> constructor;
1676 if (Map::GetConstructorFunction(map, native_context()) 1670 if (Map::GetConstructorFunction(map, native_context())
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1823 return jsgraph()->javascript(); 1817 return jsgraph()->javascript();
1824 } 1818 }
1825 1819
1826 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 1820 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
1827 return jsgraph()->simplified(); 1821 return jsgraph()->simplified();
1828 } 1822 }
1829 1823
1830 } // namespace compiler 1824 } // namespace compiler
1831 } // namespace internal 1825 } // namespace internal
1832 } // namespace v8 1826 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-inlining.cc ('k') | src/compiler/load-elimination.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698