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

Side by Side Diff: src/compiler/js-typed-lowering.cc

Issue 1431543002: [turbofan] Optimize inlining and direct function calls. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add unittest. Created 5 years, 1 month 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-typed-lowering.h ('k') | test/unittests/compiler/js-typed-lowering-unittest.cc » ('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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/code-factory.h" 5 #include "src/code-factory.h"
6 #include "src/compiler/access-builder.h" 6 #include "src/compiler/access-builder.h"
7 #include "src/compiler/js-graph.h" 7 #include "src/compiler/js-graph.h"
8 #include "src/compiler/js-typed-lowering.h" 8 #include "src/compiler/js-typed-lowering.h"
9 #include "src/compiler/linkage.h" 9 #include "src/compiler/linkage.h"
10 #include "src/compiler/node-matchers.h" 10 #include "src/compiler/node-matchers.h"
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 Node* const input = node->InputAt(0); 837 Node* const input = node->InputAt(0);
838 Reduction reduction = ReduceJSToStringInput(input); 838 Reduction reduction = ReduceJSToStringInput(input);
839 if (reduction.Changed()) { 839 if (reduction.Changed()) {
840 ReplaceWithValue(node, reduction.replacement()); 840 ReplaceWithValue(node, reduction.replacement());
841 return reduction; 841 return reduction;
842 } 842 }
843 return NoChange(); 843 return NoChange();
844 } 844 }
845 845
846 846
847 Reduction JSTypedLowering::ReduceJSToObject(Node* node) {
848 DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
849 Node* receiver = NodeProperties::GetValueInput(node, 0);
850 Type* receiver_type = NodeProperties::GetType(receiver);
851 Node* context = NodeProperties::GetContextInput(node);
852 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
853 Node* effect = NodeProperties::GetEffectInput(node);
854 Node* control = NodeProperties::GetControlInput(node);
855 if (!receiver_type->Is(Type::Receiver())) {
856 // TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks.
857 if (receiver_type->Maybe(Type::NullOrUndefined()) &&
858 NodeProperties::IsExceptionalCall(node)) {
859 // ToObject throws for null or undefined inputs.
860 return NoChange();
861 }
862
863 // Check whether {receiver} is a Smi.
864 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
865 Node* branch0 =
866 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
867 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
868 Node* etrue0 = effect;
869
870 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
871 Node* efalse0 = effect;
872
873 // Determine the instance type of {receiver}.
874 Node* receiver_map = efalse0 =
875 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
876 receiver, efalse0, if_false0);
877 Node* receiver_instance_type = efalse0 = graph()->NewNode(
878 simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
879 receiver_map, efalse0, if_false0);
880
881 // Check whether {receiver} is a spec object.
882 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
883 Node* check1 =
884 graph()->NewNode(machine()->Uint32LessThanOrEqual(),
885 jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE),
886 receiver_instance_type);
887 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
888 check1, if_false0);
889 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
890 Node* etrue1 = efalse0;
891
892 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
893 Node* efalse1 = efalse0;
894
895 // Convert {receiver} using the ToObjectStub.
896 Node* if_convert =
897 graph()->NewNode(common()->Merge(2), if_true0, if_false1);
898 Node* econvert =
899 graph()->NewNode(common()->EffectPhi(2), etrue0, efalse1, if_convert);
900 Node* rconvert;
901 {
902 Callable callable = CodeFactory::ToObject(isolate());
903 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
904 isolate(), graph()->zone(), callable.descriptor(), 0,
905 CallDescriptor::kNeedsFrameState, node->op()->properties());
906 rconvert = econvert = graph()->NewNode(
907 common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
908 receiver, context, frame_state, econvert, if_convert);
909 }
910
911 // The {receiver} is already a spec object.
912 Node* if_done = if_true1;
913 Node* edone = etrue1;
914 Node* rdone = receiver;
915
916 control = graph()->NewNode(common()->Merge(2), if_convert, if_done);
917 effect = graph()->NewNode(common()->EffectPhi(2), econvert, edone, control);
918 receiver = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), rconvert,
919 rdone, control);
920 }
921 ReplaceWithValue(node, receiver, effect, control);
922 return Changed(receiver);
923 }
924
925
847 Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) { 926 Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
848 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); 927 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
849 Node* receiver = NodeProperties::GetValueInput(node, 0); 928 Node* receiver = NodeProperties::GetValueInput(node, 0);
850 Type* receiver_type = NodeProperties::GetType(receiver); 929 Type* receiver_type = NodeProperties::GetType(receiver);
851 Node* effect = NodeProperties::GetEffectInput(node); 930 Node* effect = NodeProperties::GetEffectInput(node);
852 Node* control = NodeProperties::GetControlInput(node); 931 Node* control = NodeProperties::GetControlInput(node);
853 Handle<Name> name = NamedAccessOf(node->op()).name(); 932 Handle<Name> name = NamedAccessOf(node->op()).name();
854 // Optimize "length" property of strings. 933 // Optimize "length" property of strings.
855 if (name.is_identical_to(factory()->length_string()) && 934 if (name.is_identical_to(factory()->length_string()) &&
856 receiver_type->Is(Type::String())) { 935 receiver_type->Is(Type::String())) {
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1174 graph()->NewNode(simplified()->LoadField( 1253 graph()->NewNode(simplified()->LoadField(
1175 AccessBuilder::ForGlobalObjectGlobalProxy()), 1254 AccessBuilder::ForGlobalObjectGlobalProxy()),
1176 global_object, effect, control); 1255 global_object, effect, control);
1177 } 1256 }
1178 } else if (!receiver_type->Maybe(Type::NullOrUndefined()) || 1257 } else if (!receiver_type->Maybe(Type::NullOrUndefined()) ||
1179 mode == ConvertReceiverMode::kNotNullOrUndefined) { 1258 mode == ConvertReceiverMode::kNotNullOrUndefined) {
1180 receiver = effect = 1259 receiver = effect =
1181 graph()->NewNode(javascript()->ToObject(), receiver, context, 1260 graph()->NewNode(javascript()->ToObject(), receiver, context,
1182 frame_state, effect, control); 1261 frame_state, effect, control);
1183 } else { 1262 } else {
1184 return NoChange(); 1263 // Check {receiver} for undefined.
1264 Node* check0 =
1265 graph()->NewNode(simplified()->ReferenceEqual(receiver_type),
1266 receiver, jsgraph()->UndefinedConstant());
1267 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1268 check0, control);
1269 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1270 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1271
1272 // Check {receiver} for null.
1273 Node* check1 =
1274 graph()->NewNode(simplified()->ReferenceEqual(receiver_type),
1275 receiver, jsgraph()->NullConstant());
1276 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1277 check1, if_false0);
1278 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1279 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1280
1281 // Convert {receiver} using ToObject.
1282 Node* if_convert = if_false1;
1283 Node* econvert = effect;
1284 Node* rconvert;
1285 {
1286 rconvert = econvert =
1287 graph()->NewNode(javascript()->ToObject(), receiver, context,
1288 frame_state, econvert, if_convert);
1289 }
1290
1291 // Replace {receiver} with global proxy of {context}.
1292 Node* if_global =
1293 graph()->NewNode(common()->Merge(2), if_true0, if_true1);
1294 Node* eglobal = effect;
1295 Node* rglobal;
1296 {
1297 if (context_type->IsConstant()) {
1298 Handle<JSObject> global_proxy(
1299 Handle<Context>::cast(context_type->AsConstant()->Value())
1300 ->global_proxy(),
1301 isolate());
1302 rglobal = jsgraph()->Constant(global_proxy);
1303 } else {
1304 Node* global_object = eglobal = graph()->NewNode(
1305 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true),
1306 context, context, eglobal);
1307 rglobal = eglobal =
1308 graph()->NewNode(simplified()->LoadField(
1309 AccessBuilder::ForGlobalObjectGlobalProxy()),
1310 global_object, eglobal, if_global);
1311 }
1312 }
1313
1314 control = graph()->NewNode(common()->Merge(2), if_convert, if_global);
1315 effect =
1316 graph()->NewNode(common()->EffectPhi(2), econvert, eglobal, control);
1317 receiver = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), rconvert,
1318 rglobal, control);
1185 } 1319 }
1186 } 1320 }
1187 ReplaceWithValue(node, receiver, effect, control); 1321 ReplaceWithValue(node, receiver, effect, control);
1188 return Changed(receiver); 1322 return Changed(receiver);
1189 } 1323 }
1190 1324
1191 1325
1192 namespace { 1326 namespace {
1193 1327
1194 // Retrieves the frame state holding actual argument values. 1328 // Retrieves the frame state holding actual argument values.
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1547 } 1681 }
1548 1682
1549 return NoChange(); 1683 return NoChange();
1550 } 1684 }
1551 1685
1552 1686
1553 Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) { 1687 Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
1554 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); 1688 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
1555 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); 1689 CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
1556 int const arity = static_cast<int>(p.arity() - 2); 1690 int const arity = static_cast<int>(p.arity() - 2);
1691 ConvertReceiverMode const convert_mode = p.convert_mode();
1557 Node* target = NodeProperties::GetValueInput(node, 0); 1692 Node* target = NodeProperties::GetValueInput(node, 0);
1558 Type* target_type = NodeProperties::GetType(target); 1693 Type* target_type = NodeProperties::GetType(target);
1559 Node* receiver = NodeProperties::GetValueInput(node, 1); 1694 Node* receiver = NodeProperties::GetValueInput(node, 1);
1560 Type* receiver_type = NodeProperties::GetType(receiver); 1695 Type* receiver_type = NodeProperties::GetType(receiver);
1696 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
1697 Node* effect = NodeProperties::GetEffectInput(node);
1698 Node* control = NodeProperties::GetControlInput(node);
1561 1699
1562 // Check if {target} is a known JSFunction. 1700 // Check if {target} is a known JSFunction.
1563 if (target_type->IsConstant() && 1701 if (target_type->IsConstant() &&
1564 target_type->AsConstant()->Value()->IsJSFunction()) { 1702 target_type->AsConstant()->Value()->IsJSFunction()) {
1565 Handle<JSFunction> function = 1703 Handle<JSFunction> function =
1566 Handle<JSFunction>::cast(target_type->AsConstant()->Value()); 1704 Handle<JSFunction>::cast(target_type->AsConstant()->Value());
1567 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); 1705 Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1568 if (shared->internal_formal_parameter_count() == arity) { 1706 if (shared->internal_formal_parameter_count() == arity) {
1569 // Check if we need to wrap the {receiver}.
1570 if (is_sloppy(shared->language_mode()) && !shared->native()) {
1571 if (receiver_type->Is(Type::NullOrUndefined())) {
1572 // Change {receiver} to global proxy of {function}.
1573 receiver =
1574 jsgraph()->Constant(handle(function->global_proxy(), isolate()));
1575 } else if (!receiver_type->Is(Type::Receiver())) {
1576 // TODO(bmeurer): Add support for wrapping abitrary receivers.
1577 return NoChange();
1578 }
1579 NodeProperties::ReplaceValueInput(node, receiver, 1);
1580 }
1581
1582 // Grab the context from the {function}. 1707 // Grab the context from the {function}.
1583 Node* context = 1708 Node* context =
1584 jsgraph()->Constant(handle(function->context(), isolate())); 1709 jsgraph()->Constant(handle(function->context(), isolate()));
1585 NodeProperties::ReplaceContextInput(node, context); 1710 NodeProperties::ReplaceContextInput(node, context);
1711
1712 // Check if we need to convert the {receiver}.
1713 if (is_sloppy(shared->language_mode()) && !shared->native() &&
1714 !receiver_type->Is(Type::Receiver())) {
1715 receiver = effect =
1716 graph()->NewNode(javascript()->ConvertReceiver(convert_mode),
1717 receiver, context, frame_state, effect, control);
1718 NodeProperties::ReplaceEffectInput(node, effect);
1719 NodeProperties::ReplaceValueInput(node, receiver, 1);
1720 }
1721
1722 // Remove the eager bailout frame state.
1723 NodeProperties::RemoveFrameStateInput(node, 1);
1724
1725 // Patch {node} to a direct call.
1586 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; 1726 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1587 if (p.AllowTailCalls()) { 1727 if (p.AllowTailCalls()) flags |= CallDescriptor::kSupportsTailCalls;
1588 flags |= CallDescriptor::kSupportsTailCalls;
1589 }
1590 NodeProperties::RemoveFrameStateInput(node, 1);
1591 NodeProperties::ChangeOp(node, 1728 NodeProperties::ChangeOp(node,
1592 common()->Call(Linkage::GetJSCallDescriptor( 1729 common()->Call(Linkage::GetJSCallDescriptor(
1593 graph()->zone(), false, 1 + arity, flags))); 1730 graph()->zone(), false, 1 + arity, flags)));
1594 return Changed(node); 1731 return Changed(node);
1595 } 1732 }
1596 } 1733 }
1597 1734
1598 return NoChange(); 1735 return NoChange();
1599 } 1736 }
1600 1737
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
1936 case IrOpcode::kJSModulus: 2073 case IrOpcode::kJSModulus:
1937 return ReduceJSModulus(node); 2074 return ReduceJSModulus(node);
1938 case IrOpcode::kJSUnaryNot: 2075 case IrOpcode::kJSUnaryNot:
1939 return ReduceJSUnaryNot(node); 2076 return ReduceJSUnaryNot(node);
1940 case IrOpcode::kJSToBoolean: 2077 case IrOpcode::kJSToBoolean:
1941 return ReduceJSToBoolean(node); 2078 return ReduceJSToBoolean(node);
1942 case IrOpcode::kJSToNumber: 2079 case IrOpcode::kJSToNumber:
1943 return ReduceJSToNumber(node); 2080 return ReduceJSToNumber(node);
1944 case IrOpcode::kJSToString: 2081 case IrOpcode::kJSToString:
1945 return ReduceJSToString(node); 2082 return ReduceJSToString(node);
2083 case IrOpcode::kJSToObject:
2084 return ReduceJSToObject(node);
1946 case IrOpcode::kJSLoadNamed: 2085 case IrOpcode::kJSLoadNamed:
1947 return ReduceJSLoadNamed(node); 2086 return ReduceJSLoadNamed(node);
1948 case IrOpcode::kJSLoadProperty: 2087 case IrOpcode::kJSLoadProperty:
1949 return ReduceJSLoadProperty(node); 2088 return ReduceJSLoadProperty(node);
1950 case IrOpcode::kJSStoreProperty: 2089 case IrOpcode::kJSStoreProperty:
1951 return ReduceJSStoreProperty(node); 2090 return ReduceJSStoreProperty(node);
1952 case IrOpcode::kJSLoadContext: 2091 case IrOpcode::kJSLoadContext:
1953 return ReduceJSLoadContext(node); 2092 return ReduceJSLoadContext(node);
1954 case IrOpcode::kJSStoreContext: 2093 case IrOpcode::kJSStoreContext:
1955 return ReduceJSStoreContext(node); 2094 return ReduceJSStoreContext(node);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
2096 } 2235 }
2097 2236
2098 2237
2099 MachineOperatorBuilder* JSTypedLowering::machine() const { 2238 MachineOperatorBuilder* JSTypedLowering::machine() const {
2100 return jsgraph()->machine(); 2239 return jsgraph()->machine();
2101 } 2240 }
2102 2241
2103 } // namespace compiler 2242 } // namespace compiler
2104 } // namespace internal 2243 } // namespace internal
2105 } // namespace v8 2244 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | test/unittests/compiler/js-typed-lowering-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698