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