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

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

Issue 2902533003: [turbofan] Add support for inlining accessors into try-blocks. (Closed)
Patch Set: Address feedback. Created 3 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
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 727 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 738
739 // Compute property access infos for the receiver maps. 739 // Compute property access infos for the receiver maps.
740 AccessInfoFactory access_info_factory(dependencies(), native_context(), 740 AccessInfoFactory access_info_factory(dependencies(), native_context(),
741 graph()->zone()); 741 graph()->zone());
742 ZoneVector<PropertyAccessInfo> access_infos(zone()); 742 ZoneVector<PropertyAccessInfo> access_infos(zone());
743 if (!access_info_factory.ComputePropertyAccessInfos( 743 if (!access_info_factory.ComputePropertyAccessInfos(
744 receiver_maps, name, access_mode, &access_infos)) { 744 receiver_maps, name, access_mode, &access_infos)) {
745 return NoChange(); 745 return NoChange();
746 } 746 }
747 747
748 // TODO(turbofan): Add support for inlining into try blocks.
749 bool is_exceptional = NodeProperties::IsExceptionalCall(node);
750 for (const auto& access_info : access_infos) {
751 if (access_info.IsAccessorConstant()) {
752 // Accessor in try-blocks are not supported yet.
753 if (is_exceptional || !(flags() & kAccessorInliningEnabled)) {
754 return NoChange();
755 }
756 }
757 }
758
759 // Nothing to do if we have no non-deprecated maps. 748 // Nothing to do if we have no non-deprecated maps.
760 if (access_infos.empty()) { 749 if (access_infos.empty()) {
761 return ReduceSoftDeoptimize( 750 return ReduceSoftDeoptimize(
762 node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); 751 node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
763 } 752 }
764 753
765 // Ensure that {index} matches the specified {name} (if {index} is given). 754 // Ensure that {index} matches the specified {name} (if {index} is given).
766 if (index != nullptr) { 755 if (index != nullptr) {
767 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), index, 756 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), index,
768 jsgraph()->HeapConstant(name)); 757 jsgraph()->HeapConstant(name));
769 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); 758 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control);
770 } 759 }
771 760
761 // Collect call nodes to rewire exception edges.
762 ZoneVector<Node*> if_exception_nodes(zone());
763 ZoneVector<Node*>* if_exceptions = nullptr;
764 Node* if_exception = nullptr;
765 if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
766 if_exceptions = &if_exception_nodes;
767 }
768
772 // Check for the monomorphic cases. 769 // Check for the monomorphic cases.
773 if (access_infos.size() == 1) { 770 if (access_infos.size() == 1) {
774 PropertyAccessInfo access_info = access_infos.front(); 771 PropertyAccessInfo access_info = access_infos.front();
775 if (HasOnlyStringMaps(access_info.receiver_maps())) { 772 if (HasOnlyStringMaps(access_info.receiver_maps())) {
776 // Monormorphic string access (ignoring the fact that there are multiple 773 // Monormorphic string access (ignoring the fact that there are multiple
777 // String maps). 774 // String maps).
778 receiver = effect = graph()->NewNode(simplified()->CheckString(), 775 receiver = effect = graph()->NewNode(simplified()->CheckString(),
779 receiver, effect, control); 776 receiver, effect, control);
780 } else if (HasOnlyNumberMaps(access_info.receiver_maps())) { 777 } else if (HasOnlyNumberMaps(access_info.receiver_maps())) {
781 // Monomorphic number access (we also deal with Smis here). 778 // Monomorphic number access (we also deal with Smis here).
782 receiver = effect = graph()->NewNode(simplified()->CheckNumber(), 779 receiver = effect = graph()->NewNode(simplified()->CheckNumber(),
783 receiver, effect, control); 780 receiver, effect, control);
784 } else { 781 } else {
785 // Monomorphic property access. 782 // Monomorphic property access.
786 receiver = BuildCheckHeapObject(receiver, &effect, control); 783 receiver = BuildCheckHeapObject(receiver, &effect, control);
787 effect = BuildCheckMaps(receiver, effect, control, 784 effect = BuildCheckMaps(receiver, effect, control,
788 access_info.receiver_maps()); 785 access_info.receiver_maps());
789 } 786 }
790 787
791 // Generate the actual property access. 788 // Generate the actual property access.
792 ValueEffectControl continuation = BuildPropertyAccess( 789 ValueEffectControl continuation = BuildPropertyAccess(
793 receiver, value, context, frame_state, effect, control, name, 790 receiver, value, context, frame_state, effect, control, name,
794 access_info, access_mode, language_mode); 791 if_exceptions, access_info, access_mode, language_mode);
795 value = continuation.value(); 792 value = continuation.value();
796 effect = continuation.effect(); 793 effect = continuation.effect();
797 control = continuation.control(); 794 control = continuation.control();
798 } else { 795 } else {
799 // The final states for every polymorphic branch. We join them with 796 // The final states for every polymorphic branch. We join them with
800 // Merge+Phi+EffectPhi at the bottom. 797 // Merge+Phi+EffectPhi at the bottom.
801 ZoneVector<Node*> values(zone()); 798 ZoneVector<Node*> values(zone());
802 ZoneVector<Node*> effects(zone()); 799 ZoneVector<Node*> effects(zone());
803 ZoneVector<Node*> controls(zone()); 800 ZoneVector<Node*> controls(zone());
804 801
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 graph()->NewNode(common()->Merge(this_control_count), 884 graph()->NewNode(common()->Merge(this_control_count),
888 this_control_count, &this_controls.front()); 885 this_control_count, &this_controls.front());
889 this_effects.push_back(this_control); 886 this_effects.push_back(this_control);
890 this_effect = 887 this_effect =
891 graph()->NewNode(common()->EffectPhi(this_control_count), 888 graph()->NewNode(common()->EffectPhi(this_control_count),
892 this_control_count + 1, &this_effects.front()); 889 this_control_count + 1, &this_effects.front());
893 } 890 }
894 } 891 }
895 892
896 // Generate the actual property access. 893 // Generate the actual property access.
897 ValueEffectControl continuation = BuildPropertyAccess( 894 ValueEffectControl continuation =
898 this_receiver, this_value, context, frame_state, this_effect, 895 BuildPropertyAccess(this_receiver, this_value, context, frame_state,
899 this_control, name, access_info, access_mode, language_mode); 896 this_effect, this_control, name, if_exceptions,
897 access_info, access_mode, language_mode);
900 values.push_back(continuation.value()); 898 values.push_back(continuation.value());
901 effects.push_back(continuation.effect()); 899 effects.push_back(continuation.effect());
902 controls.push_back(continuation.control()); 900 controls.push_back(continuation.control());
903 } 901 }
904 902
905 DCHECK_NULL(fallthrough_control); 903 DCHECK_NULL(fallthrough_control);
906 904
907 // Generate the final merge point for all (polymorphic) branches. 905 // Generate the final merge point for all (polymorphic) branches.
908 int const control_count = static_cast<int>(controls.size()); 906 int const control_count = static_cast<int>(controls.size());
909 if (control_count == 0) { 907 if (control_count == 0) {
910 value = effect = control = jsgraph()->Dead(); 908 value = effect = control = jsgraph()->Dead();
911 } else if (control_count == 1) { 909 } else if (control_count == 1) {
912 value = values.front(); 910 value = values.front();
913 effect = effects.front(); 911 effect = effects.front();
914 control = controls.front(); 912 control = controls.front();
915 } else { 913 } else {
916 control = graph()->NewNode(common()->Merge(control_count), control_count, 914 control = graph()->NewNode(common()->Merge(control_count), control_count,
917 &controls.front()); 915 &controls.front());
918 values.push_back(control); 916 values.push_back(control);
919 value = graph()->NewNode( 917 value = graph()->NewNode(
920 common()->Phi(MachineRepresentation::kTagged, control_count), 918 common()->Phi(MachineRepresentation::kTagged, control_count),
921 control_count + 1, &values.front()); 919 control_count + 1, &values.front());
922 effects.push_back(control); 920 effects.push_back(control);
923 effect = graph()->NewNode(common()->EffectPhi(control_count), 921 effect = graph()->NewNode(common()->EffectPhi(control_count),
924 control_count + 1, &effects.front()); 922 control_count + 1, &effects.front());
925 } 923 }
926 } 924 }
925
926 // Properly rewire IfException edges if {node} is inside a try-block.
927 if (!if_exception_nodes.empty()) {
928 DCHECK_NOT_NULL(if_exception);
929 DCHECK_EQ(if_exceptions, &if_exception_nodes);
930 int const if_exception_count = static_cast<int>(if_exceptions->size());
931 Node* merge = graph()->NewNode(common()->Merge(if_exception_count),
932 if_exception_count, &if_exceptions->front());
933 if_exceptions->push_back(merge);
934 Node* ephi =
935 graph()->NewNode(common()->EffectPhi(if_exception_count),
936 if_exception_count + 1, &if_exceptions->front());
937 Node* phi = graph()->NewNode(
938 common()->Phi(MachineRepresentation::kTagged, if_exception_count),
939 if_exception_count + 1, &if_exceptions->front());
940 ReplaceWithValue(if_exception, phi, ephi, merge);
941 }
942
927 ReplaceWithValue(node, value, effect, control); 943 ReplaceWithValue(node, value, effect, control);
928 return Replace(value); 944 return Replace(value);
929 } 945 }
930 946
931 Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( 947 Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus(
932 Node* node, Node* value, FeedbackNexus const& nexus, Handle<Name> name, 948 Node* node, Node* value, FeedbackNexus const& nexus, Handle<Name> name,
933 AccessMode access_mode, LanguageMode language_mode) { 949 AccessMode access_mode, LanguageMode language_mode) {
934 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || 950 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
935 node->opcode() == IrOpcode::kJSStoreNamed || 951 node->opcode() == IrOpcode::kJSStoreNamed ||
936 node->opcode() == IrOpcode::kJSStoreNamedOwn); 952 node->opcode() == IrOpcode::kJSStoreNamedOwn);
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after
1446 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); 1462 KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
1447 1463
1448 // Try to lower the keyed access based on the {nexus}. 1464 // Try to lower the keyed access based on the {nexus}.
1449 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, 1465 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
1450 p.language_mode(), store_mode); 1466 p.language_mode(), store_mode);
1451 } 1467 }
1452 1468
1453 JSNativeContextSpecialization::ValueEffectControl 1469 JSNativeContextSpecialization::ValueEffectControl
1454 JSNativeContextSpecialization::BuildPropertyAccess( 1470 JSNativeContextSpecialization::BuildPropertyAccess(
1455 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect, 1471 Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
1456 Node* control, Handle<Name> name, PropertyAccessInfo const& access_info, 1472 Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
1457 AccessMode access_mode, LanguageMode language_mode) { 1473 PropertyAccessInfo const& access_info, AccessMode access_mode,
1474 LanguageMode language_mode) {
1458 // Determine actual holder and perform prototype chain checks. 1475 // Determine actual holder and perform prototype chain checks.
1459 Handle<JSObject> holder; 1476 Handle<JSObject> holder;
1460 if (access_info.holder().ToHandle(&holder)) { 1477 if (access_info.holder().ToHandle(&holder)) {
1461 DCHECK_NE(AccessMode::kStoreInLiteral, access_mode); 1478 DCHECK_NE(AccessMode::kStoreInLiteral, access_mode);
1462 AssumePrototypesStable(access_info.receiver_maps(), holder); 1479 AssumePrototypesStable(access_info.receiver_maps(), holder);
1463 } 1480 }
1464 1481
1465 // Generate the actual property access. 1482 // Generate the actual property access.
1466 if (access_info.IsNotFound()) { 1483 if (access_info.IsNotFound()) {
1467 DCHECK_EQ(AccessMode::kLoad, access_mode); 1484 DCHECK_EQ(AccessMode::kLoad, access_mode);
1468 value = jsgraph()->UndefinedConstant(); 1485 value = jsgraph()->UndefinedConstant();
1469 } else if (access_info.IsDataConstant()) { 1486 } else if (access_info.IsDataConstant()) {
1470 DCHECK(!FLAG_track_constant_fields); 1487 DCHECK(!FLAG_track_constant_fields);
1471 Node* constant_value = jsgraph()->Constant(access_info.constant()); 1488 Node* constant_value = jsgraph()->Constant(access_info.constant());
1472 if (access_mode == AccessMode::kStore) { 1489 if (access_mode == AccessMode::kStore) {
1473 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), value, 1490 Node* check = graph()->NewNode(simplified()->ReferenceEqual(), value,
1474 constant_value); 1491 constant_value);
1475 effect = 1492 effect =
1476 graph()->NewNode(simplified()->CheckIf(), check, effect, control); 1493 graph()->NewNode(simplified()->CheckIf(), check, effect, control);
1477 } 1494 }
1478 value = constant_value; 1495 value = constant_value;
1479 } else if (access_info.IsAccessorConstant()) { 1496 } else if (access_info.IsAccessorConstant()) {
1480 // TODO(bmeurer): Properly rewire the IfException edge here if there's any.
1481 Node* target = jsgraph()->Constant(access_info.constant()); 1497 Node* target = jsgraph()->Constant(access_info.constant());
1482 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); 1498 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
1483 Handle<SharedFunctionInfo> shared_info = 1499 Handle<SharedFunctionInfo> shared_info =
1484 frame_info.shared_info().ToHandleChecked(); 1500 frame_info.shared_info().ToHandleChecked();
1485 switch (access_mode) { 1501 switch (access_mode) {
1486 case AccessMode::kLoad: { 1502 case AccessMode::kLoad: {
1487 // We need a FrameState for the getter stub to restore the correct 1503 // We need a FrameState for the getter stub to restore the correct
1488 // context before returning to fullcodegen. 1504 // context before returning to fullcodegen.
1489 FrameStateFunctionInfo const* frame_info0 = 1505 FrameStateFunctionInfo const* frame_info0 =
1490 common()->CreateFrameStateFunctionInfo(FrameStateType::kGetterStub, 1506 common()->CreateFrameStateFunctionInfo(FrameStateType::kGetterStub,
(...skipping 20 matching lines...) Expand all
1511 DCHECK(!function_template_info->call_code()->IsUndefined(isolate())); 1527 DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
1512 ValueEffectControl value_effect_control = InlineApiCall( 1528 ValueEffectControl value_effect_control = InlineApiCall(
1513 receiver, context, target, frame_state0, nullptr, effect, control, 1529 receiver, context, target, frame_state0, nullptr, effect, control,
1514 shared_info, function_template_info); 1530 shared_info, function_template_info);
1515 value = value_effect_control.value(); 1531 value = value_effect_control.value();
1516 effect = value_effect_control.effect(); 1532 effect = value_effect_control.effect();
1517 control = value_effect_control.control(); 1533 control = value_effect_control.control();
1518 } 1534 }
1519 break; 1535 break;
1520 } 1536 }
1521 case AccessMode::kStoreInLiteral:
1522 case AccessMode::kStore: { 1537 case AccessMode::kStore: {
1523 // We need a FrameState for the setter stub to restore the correct 1538 // We need a FrameState for the setter stub to restore the correct
1524 // context and return the appropriate value to fullcodegen. 1539 // context and return the appropriate value to fullcodegen.
1525 FrameStateFunctionInfo const* frame_info0 = 1540 FrameStateFunctionInfo const* frame_info0 =
1526 common()->CreateFrameStateFunctionInfo(FrameStateType::kSetterStub, 1541 common()->CreateFrameStateFunctionInfo(FrameStateType::kSetterStub,
1527 2, 0, shared_info); 1542 2, 0, shared_info);
1528 Node* frame_state0 = graph()->NewNode( 1543 Node* frame_state0 = graph()->NewNode(
1529 common()->FrameState(BailoutId::None(), 1544 common()->FrameState(BailoutId::None(),
1530 OutputFrameStateCombine::Ignore(), 1545 OutputFrameStateCombine::Ignore(),
1531 frame_info0), 1546 frame_info0),
(...skipping 15 matching lines...) Expand all
1547 DCHECK(!function_template_info->call_code()->IsUndefined(isolate())); 1562 DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
1548 ValueEffectControl value_effect_control = InlineApiCall( 1563 ValueEffectControl value_effect_control = InlineApiCall(
1549 receiver, context, target, frame_state0, value, effect, control, 1564 receiver, context, target, frame_state0, value, effect, control,
1550 shared_info, function_template_info); 1565 shared_info, function_template_info);
1551 value = value_effect_control.value(); 1566 value = value_effect_control.value();
1552 effect = value_effect_control.effect(); 1567 effect = value_effect_control.effect();
1553 control = value_effect_control.control(); 1568 control = value_effect_control.control();
1554 } 1569 }
1555 break; 1570 break;
1556 } 1571 }
1572 case AccessMode::kStoreInLiteral: {
1573 UNREACHABLE();
1574 break;
1575 }
1576 }
1577 // Remember to rewire the IfException edge if this is inside a try-block.
1578 if (if_exceptions != nullptr) {
1579 // Create the appropriate IfException/IfSuccess projections.
1580 Node* const if_exception =
1581 graph()->NewNode(common()->IfException(), control, effect);
1582 Node* const if_success = graph()->NewNode(common()->IfSuccess(), control);
1583 if_exceptions->push_back(if_exception);
1584 control = if_success;
1557 } 1585 }
1558 } else { 1586 } else {
1559 DCHECK(access_info.IsDataField() || access_info.IsDataConstantField()); 1587 DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
1560 FieldIndex const field_index = access_info.field_index(); 1588 FieldIndex const field_index = access_info.field_index();
1561 Type* const field_type = access_info.field_type(); 1589 Type* const field_type = access_info.field_type();
1562 MachineRepresentation const field_representation = 1590 MachineRepresentation const field_representation =
1563 access_info.field_representation(); 1591 access_info.field_representation();
1564 if (access_mode == AccessMode::kLoad) { 1592 if (access_mode == AccessMode::kLoad) {
1565 if (access_info.holder().ToHandle(&holder)) { 1593 if (access_info.holder().ToHandle(&holder)) {
1566 receiver = jsgraph()->Constant(holder); 1594 receiver = jsgraph()->Constant(holder);
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
1866 jsgraph()->HeapConstant(cached_name)); 1894 jsgraph()->HeapConstant(cached_name));
1867 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); 1895 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control);
1868 1896
1869 Node* value = NodeProperties::GetValueInput(node, 2); 1897 Node* value = NodeProperties::GetValueInput(node, 2);
1870 Node* context = NodeProperties::GetContextInput(node); 1898 Node* context = NodeProperties::GetContextInput(node);
1871 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node); 1899 Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node);
1872 1900
1873 // Generate the actual property access. 1901 // Generate the actual property access.
1874 ValueEffectControl continuation = BuildPropertyAccess( 1902 ValueEffectControl continuation = BuildPropertyAccess(
1875 receiver, value, context, frame_state_lazy, effect, control, cached_name, 1903 receiver, value, context, frame_state_lazy, effect, control, cached_name,
1876 access_info, AccessMode::kStoreInLiteral, LanguageMode::SLOPPY); 1904 nullptr, access_info, AccessMode::kStoreInLiteral, LanguageMode::SLOPPY);
1877 value = continuation.value(); 1905 value = continuation.value();
1878 effect = continuation.effect(); 1906 effect = continuation.effect();
1879 control = continuation.control(); 1907 control = continuation.control();
1880 1908
1881 ReplaceWithValue(node, value, effect, control); 1909 ReplaceWithValue(node, value, effect, control);
1882 return Replace(value); 1910 return Replace(value);
1883 } 1911 }
1884 1912
1885 namespace { 1913 namespace {
1886 1914
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
2569 return jsgraph()->javascript(); 2597 return jsgraph()->javascript();
2570 } 2598 }
2571 2599
2572 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { 2600 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
2573 return jsgraph()->simplified(); 2601 return jsgraph()->simplified();
2574 } 2602 }
2575 2603
2576 } // namespace compiler 2604 } // namespace compiler
2577 } // namespace internal 2605 } // namespace internal
2578 } // namespace v8 2606 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | test/mjsunit/compiler/inline-accessors.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698