Chromium Code Reviews| 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 |