OLD | NEW |
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/compilation-dependencies.h" |
6 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
7 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
8 #include "src/compiler/js-typed-lowering.h" | 9 #include "src/compiler/js-typed-lowering.h" |
9 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
10 #include "src/compiler/node-matchers.h" | 11 #include "src/compiler/node-matchers.h" |
11 #include "src/compiler/node-properties.h" | 12 #include "src/compiler/node-properties.h" |
12 #include "src/compiler/operator-properties.h" | 13 #include "src/compiler/operator-properties.h" |
13 #include "src/compiler/state-values-utils.h" | 14 #include "src/compiler/state-values-utils.h" |
14 #include "src/types.h" | 15 #include "src/types.h" |
15 | 16 |
16 namespace v8 { | 17 namespace v8 { |
17 namespace internal { | 18 namespace internal { |
18 namespace compiler { | 19 namespace compiler { |
19 | 20 |
20 // TODO(turbofan): js-typed-lowering improvements possible | 21 // TODO(turbofan): js-typed-lowering improvements possible |
21 // - immediately put in type bounds for all new nodes | 22 // - immediately put in type bounds for all new nodes |
22 // - relax effects from generic but not-side-effecting operations | 23 // - relax effects from generic but not-side-effecting operations |
23 | 24 |
24 | 25 |
25 JSTypedLowering::JSTypedLowering(Editor* editor, JSGraph* jsgraph, Zone* zone) | 26 JSTypedLowering::JSTypedLowering(Editor* editor, |
26 : AdvancedReducer(editor), jsgraph_(jsgraph) { | 27 CompilationDependencies* dependencies, |
| 28 Flags flags, JSGraph* jsgraph, Zone* zone) |
| 29 : AdvancedReducer(editor), |
| 30 dependencies_(dependencies), |
| 31 flags_(flags), |
| 32 jsgraph_(jsgraph) { |
27 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { | 33 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { |
28 double min = kMinInt / (1 << k); | 34 double min = kMinInt / (1 << k); |
29 double max = kMaxInt / (1 << k); | 35 double max = kMaxInt / (1 << k); |
30 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); | 36 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); |
31 } | 37 } |
32 } | 38 } |
33 | 39 |
34 | 40 |
35 // A helper class to construct inline allocations on the simplified operator | 41 // A helper class to construct inline allocations on the simplified operator |
36 // level. This keeps track of the effect chain for initial stores on a newly | 42 // level. This keeps track of the effect chain for initial stores on a newly |
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 node->TrimInputCount(6); | 1058 node->TrimInputCount(6); |
1053 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access)); | 1059 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access)); |
1054 return Changed(node); | 1060 return Changed(node); |
1055 } | 1061 } |
1056 } | 1062 } |
1057 } | 1063 } |
1058 return NoChange(); | 1064 return NoChange(); |
1059 } | 1065 } |
1060 | 1066 |
1061 | 1067 |
| 1068 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) { |
| 1069 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); |
| 1070 |
| 1071 // If deoptimization is disabled, we cannot optimize. |
| 1072 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| 1073 |
| 1074 JSBinopReduction r(this, node); |
| 1075 Node* effect = r.effect(); |
| 1076 Node* control = r.control(); |
| 1077 |
| 1078 if (r.right_type()->IsConstant() && |
| 1079 r.right_type()->AsConstant()->Value()->IsJSFunction()) { |
| 1080 Handle<JSFunction> function = |
| 1081 Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value()); |
| 1082 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
| 1083 if (!function->map()->has_non_instance_prototype()) { |
| 1084 JSFunction::EnsureHasInitialMap(function); |
| 1085 DCHECK(function->has_initial_map()); |
| 1086 Handle<Map> initial_map(function->initial_map(), isolate()); |
| 1087 this->dependencies()->AssumeInitialMapCantChange(initial_map); |
| 1088 Node* prototype = |
| 1089 jsgraph()->Constant(handle(initial_map->prototype(), isolate())); |
| 1090 |
| 1091 Node* if_is_smi = nullptr; |
| 1092 Node* e_is_smi = nullptr; |
| 1093 // If the left hand side is an object, no smi check is needed. |
| 1094 if (r.left_type()->Maybe(Type::TaggedSigned())) { |
| 1095 Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left()); |
| 1096 Node* branch_is_smi = graph()->NewNode( |
| 1097 common()->Branch(BranchHint::kFalse), is_smi, control); |
| 1098 if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi); |
| 1099 e_is_smi = effect; |
| 1100 control = graph()->NewNode(common()->IfFalse(), branch_is_smi); |
| 1101 } |
| 1102 |
| 1103 Node* object_map = effect = |
| 1104 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 1105 r.left(), effect, control); |
| 1106 |
| 1107 // Loop through the {object}s prototype chain looking for the {prototype}. |
| 1108 Node* loop = control = |
| 1109 graph()->NewNode(common()->Loop(2), control, control); |
| 1110 |
| 1111 Node* loop_effect = effect = |
| 1112 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop); |
| 1113 |
| 1114 Node* loop_object_map = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), |
| 1115 object_map, r.left(), loop); |
| 1116 |
| 1117 |
| 1118 Node* object_prototype = effect = graph()->NewNode( |
| 1119 simplified()->LoadField(AccessBuilder::ForMapPrototype()), |
| 1120 loop_object_map, loop_effect, control); |
| 1121 |
| 1122 // Check if object prototype is equal to function prototype. |
| 1123 Node* eq_proto = |
| 1124 graph()->NewNode(simplified()->ReferenceEqual(r.right_type()), |
| 1125 object_prototype, prototype); |
| 1126 Node* branch_eq_proto = graph()->NewNode( |
| 1127 common()->Branch(BranchHint::kFalse), eq_proto, control); |
| 1128 Node* if_eq_proto = graph()->NewNode(common()->IfTrue(), branch_eq_proto); |
| 1129 Node* e_eq_proto = effect; |
| 1130 |
| 1131 control = graph()->NewNode(common()->IfFalse(), branch_eq_proto); |
| 1132 |
| 1133 // If not, check if object prototype is the null prototype. |
| 1134 Node* null_proto = |
| 1135 graph()->NewNode(simplified()->ReferenceEqual(r.right_type()), |
| 1136 object_prototype, jsgraph()->NullConstant()); |
| 1137 Node* branch_null_proto = graph()->NewNode( |
| 1138 common()->Branch(BranchHint::kFalse), null_proto, control); |
| 1139 Node* if_null_proto = |
| 1140 graph()->NewNode(common()->IfTrue(), branch_null_proto); |
| 1141 Node* e_null_proto = effect; |
| 1142 |
| 1143 control = graph()->NewNode(common()->IfFalse(), branch_null_proto); |
| 1144 Node* load_object_map = effect = |
| 1145 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 1146 object_prototype, effect, control); |
| 1147 // Close the loop. |
| 1148 loop_effect->ReplaceInput(1, effect); |
| 1149 loop_object_map->ReplaceInput(1, load_object_map); |
| 1150 loop->ReplaceInput(1, control); |
| 1151 |
| 1152 control = |
| 1153 graph()->NewNode(common()->Merge(2), if_eq_proto, if_null_proto); |
| 1154 effect = graph()->NewNode(common()->EffectPhi(2), e_eq_proto, |
| 1155 e_null_proto, control); |
| 1156 |
| 1157 |
| 1158 Node* result = graph()->NewNode(common()->Phi(kTypeBool, 2), |
| 1159 jsgraph()->TrueConstant(), |
| 1160 jsgraph()->FalseConstant(), control); |
| 1161 |
| 1162 if (if_is_smi != nullptr) { |
| 1163 DCHECK(e_is_smi != nullptr); |
| 1164 control = graph()->NewNode(common()->Merge(2), if_is_smi, control); |
| 1165 effect = |
| 1166 graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control); |
| 1167 result = graph()->NewNode(common()->Phi(kTypeBool, 2), |
| 1168 jsgraph()->FalseConstant(), result, control); |
| 1169 } |
| 1170 ReplaceWithValue(node, result, effect, control); |
| 1171 return Changed(result); |
| 1172 } |
| 1173 } |
| 1174 |
| 1175 return NoChange(); |
| 1176 } |
| 1177 |
| 1178 |
1062 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { | 1179 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { |
1063 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); | 1180 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); |
1064 ContextAccess const& access = ContextAccessOf(node->op()); | 1181 ContextAccess const& access = ContextAccessOf(node->op()); |
1065 Node* const effect = NodeProperties::GetEffectInput(node); | 1182 Node* const effect = NodeProperties::GetEffectInput(node); |
1066 Node* const control = graph()->start(); | 1183 Node* const control = graph()->start(); |
1067 for (size_t i = 0; i < access.depth(); ++i) { | 1184 for (size_t i = 0; i < access.depth(); ++i) { |
1068 node->ReplaceInput( | 1185 node->ReplaceInput( |
1069 0, graph()->NewNode( | 1186 0, graph()->NewNode( |
1070 simplified()->LoadField( | 1187 simplified()->LoadField( |
1071 AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)), | 1188 AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)), |
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2021 case IrOpcode::kJSToString: | 2138 case IrOpcode::kJSToString: |
2022 return ReduceJSToString(node); | 2139 return ReduceJSToString(node); |
2023 case IrOpcode::kJSToObject: | 2140 case IrOpcode::kJSToObject: |
2024 return ReduceJSToObject(node); | 2141 return ReduceJSToObject(node); |
2025 case IrOpcode::kJSLoadNamed: | 2142 case IrOpcode::kJSLoadNamed: |
2026 return ReduceJSLoadNamed(node); | 2143 return ReduceJSLoadNamed(node); |
2027 case IrOpcode::kJSLoadProperty: | 2144 case IrOpcode::kJSLoadProperty: |
2028 return ReduceJSLoadProperty(node); | 2145 return ReduceJSLoadProperty(node); |
2029 case IrOpcode::kJSStoreProperty: | 2146 case IrOpcode::kJSStoreProperty: |
2030 return ReduceJSStoreProperty(node); | 2147 return ReduceJSStoreProperty(node); |
| 2148 case IrOpcode::kJSInstanceOf: |
| 2149 return ReduceJSInstanceOf(node); |
2031 case IrOpcode::kJSLoadContext: | 2150 case IrOpcode::kJSLoadContext: |
2032 return ReduceJSLoadContext(node); | 2151 return ReduceJSLoadContext(node); |
2033 case IrOpcode::kJSStoreContext: | 2152 case IrOpcode::kJSStoreContext: |
2034 return ReduceJSStoreContext(node); | 2153 return ReduceJSStoreContext(node); |
2035 case IrOpcode::kJSConvertReceiver: | 2154 case IrOpcode::kJSConvertReceiver: |
2036 return ReduceJSConvertReceiver(node); | 2155 return ReduceJSConvertReceiver(node); |
2037 case IrOpcode::kJSCreateArguments: | 2156 case IrOpcode::kJSCreateArguments: |
2038 return ReduceJSCreateArguments(node); | 2157 return ReduceJSCreateArguments(node); |
2039 case IrOpcode::kJSCreateClosure: | 2158 case IrOpcode::kJSCreateClosure: |
2040 return ReduceJSCreateClosure(node); | 2159 return ReduceJSCreateClosure(node); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2168 | 2287 |
2169 SimplifiedOperatorBuilder* JSTypedLowering::simplified() const { | 2288 SimplifiedOperatorBuilder* JSTypedLowering::simplified() const { |
2170 return jsgraph()->simplified(); | 2289 return jsgraph()->simplified(); |
2171 } | 2290 } |
2172 | 2291 |
2173 | 2292 |
2174 MachineOperatorBuilder* JSTypedLowering::machine() const { | 2293 MachineOperatorBuilder* JSTypedLowering::machine() const { |
2175 return jsgraph()->machine(); | 2294 return jsgraph()->machine(); |
2176 } | 2295 } |
2177 | 2296 |
| 2297 |
| 2298 CompilationDependencies* JSTypedLowering::dependencies() const { |
| 2299 return dependencies_; |
| 2300 } |
| 2301 |
2178 } // namespace compiler | 2302 } // namespace compiler |
2179 } // namespace internal | 2303 } // namespace internal |
2180 } // namespace v8 | 2304 } // namespace v8 |
OLD | NEW |