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/compiler/access-builder.h" | 5 #include "src/compiler/access-builder.h" |
| 6 #include "src/compiler/graph-inl.h" | 6 #include "src/compiler/graph-inl.h" |
| 7 #include "src/compiler/js-builtin-reducer.h" | 7 #include "src/compiler/js-builtin-reducer.h" |
| 8 #include "src/compiler/js-typed-lowering.h" | 8 #include "src/compiler/js-typed-lowering.h" |
| 9 #include "src/compiler/node-aux-data-inl.h" | 9 #include "src/compiler/node-aux-data-inl.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 void SwapInputs() { | 107 void SwapInputs() { |
| 108 Node* l = left(); | 108 Node* l = left(); |
| 109 Node* r = right(); | 109 Node* r = right(); |
| 110 node_->ReplaceInput(0, r); | 110 node_->ReplaceInput(0, r); |
| 111 node_->ReplaceInput(1, l); | 111 node_->ReplaceInput(1, l); |
| 112 std::swap(left_type_, right_type_); | 112 std::swap(left_type_, right_type_); |
| 113 } | 113 } |
| 114 | 114 |
| 115 // Remove all effect and control inputs and outputs to this node and change | 115 // Remove all effect and control inputs and outputs to this node and change |
| 116 // to the pure operator {op}, possibly inserting a boolean inversion. | 116 // to the pure operator {op}, possibly inserting a boolean inversion. |
| 117 Reduction ChangeToPureOperator(const Operator* op, bool invert = false) { | 117 Reduction ChangeToPureOperator(const Operator* op, bool invert = false, |
| 118 Type* type = Type::Any()) { | |
| 118 DCHECK_EQ(0, op->EffectInputCount()); | 119 DCHECK_EQ(0, op->EffectInputCount()); |
| 119 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); | 120 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
| 120 DCHECK_EQ(0, op->ControlInputCount()); | 121 DCHECK_EQ(0, op->ControlInputCount()); |
| 121 DCHECK_EQ(2, op->ValueInputCount()); | 122 DCHECK_EQ(2, op->ValueInputCount()); |
| 122 | 123 |
| 123 // Remove the effects from the node, if any, and update its effect usages. | 124 // Remove the effects from the node, if any, and update its effect usages. |
| 124 if (node_->op()->EffectInputCount() > 0) { | 125 if (node_->op()->EffectInputCount() > 0) { |
| 125 RelaxEffects(node_); | 126 RelaxEffects(node_); |
| 126 } | 127 } |
| 127 // Remove the inputs corresponding to context, effect, and control. | 128 // Remove the inputs corresponding to context, effect, and control. |
| 128 NodeProperties::RemoveNonValueInputs(node_); | 129 NodeProperties::RemoveNonValueInputs(node_); |
| 129 // Finally, update the operator to the new one. | 130 // Finally, update the operator to the new one. |
| 130 node_->set_op(op); | 131 node_->set_op(op); |
| 131 | 132 |
| 133 // TODO(jarin): Narrow the type after patching the operator. | |
|
Jarin
2014/12/04 10:43:01
This is not really a big fat TODO. Could you write
Benedikt Meurer
2014/12/04 11:19:01
Done.
| |
| 134 Bounds const bounds = NodeProperties::GetBounds(node_); | |
| 135 NodeProperties::SetBounds(node_, Bounds::NarrowUpper(bounds, type, zone())); | |
| 136 | |
| 132 if (invert) { | 137 if (invert) { |
| 133 // Insert an boolean not to invert the value. | 138 // Insert an boolean not to invert the value. |
| 134 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); | 139 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); |
| 135 node_->ReplaceUses(value); | 140 node_->ReplaceUses(value); |
| 136 // Note: ReplaceUses() smashes all uses, so smash it back here. | 141 // Note: ReplaceUses() smashes all uses, so smash it back here. |
| 137 value->ReplaceInput(0, node_); | 142 value->ReplaceInput(0, node_); |
| 138 return lowering_->ReplaceWith(value); | 143 return lowering_->ReplaceWith(value); |
| 139 } | 144 } |
| 140 return lowering_->Changed(node_); | 145 return lowering_->Changed(node_); |
| 141 } | 146 } |
|
Jarin
2014/12/04 10:43:01
Insert an empty line here?
Benedikt Meurer
2014/12/04 11:19:01
Done.
| |
| 147 Reduction ChangeToPureOperator(const Operator* op, Type* type) { | |
| 148 return ChangeToPureOperator(op, false, type); | |
| 149 } | |
| 142 | 150 |
| 143 bool OneInputIs(Type* t) { return left_type_->Is(t) || right_type_->Is(t); } | 151 bool OneInputIs(Type* t) { return left_type_->Is(t) || right_type_->Is(t); } |
| 144 | 152 |
| 145 bool BothInputsAre(Type* t) { | 153 bool BothInputsAre(Type* t) { |
| 146 return left_type_->Is(t) && right_type_->Is(t); | 154 return left_type_->Is(t) && right_type_->Is(t); |
| 147 } | 155 } |
| 148 | 156 |
| 149 bool OneInputCannotBe(Type* t) { | 157 bool OneInputCannotBe(Type* t) { |
| 150 return !left_type_->Maybe(t) || !right_type_->Maybe(t); | 158 return !left_type_->Maybe(t) || !right_type_->Maybe(t); |
| 151 } | 159 } |
| 152 | 160 |
| 153 bool NeitherInputCanBe(Type* t) { | 161 bool NeitherInputCanBe(Type* t) { |
| 154 return !left_type_->Maybe(t) && !right_type_->Maybe(t); | 162 return !left_type_->Maybe(t) && !right_type_->Maybe(t); |
| 155 } | 163 } |
| 156 | 164 |
| 157 Node* effect() { return NodeProperties::GetEffectInput(node_); } | 165 Node* effect() { return NodeProperties::GetEffectInput(node_); } |
| 158 Node* control() { return NodeProperties::GetControlInput(node_); } | 166 Node* control() { return NodeProperties::GetControlInput(node_); } |
| 159 Node* context() { return NodeProperties::GetContextInput(node_); } | 167 Node* context() { return NodeProperties::GetContextInput(node_); } |
| 160 Node* left() { return NodeProperties::GetValueInput(node_, 0); } | 168 Node* left() { return NodeProperties::GetValueInput(node_, 0); } |
| 161 Node* right() { return NodeProperties::GetValueInput(node_, 1); } | 169 Node* right() { return NodeProperties::GetValueInput(node_, 1); } |
| 162 Type* left_type() { return left_type_; } | 170 Type* left_type() { return left_type_; } |
| 163 Type* right_type() { return right_type_; } | 171 Type* right_type() { return right_type_; } |
| 164 | 172 |
| 165 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); } | 173 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); } |
| 166 Graph* graph() { return lowering_->graph(); } | 174 Graph* graph() const { return lowering_->graph(); } |
| 167 JSGraph* jsgraph() { return lowering_->jsgraph(); } | 175 JSGraph* jsgraph() { return lowering_->jsgraph(); } |
| 168 JSOperatorBuilder* javascript() { return lowering_->javascript(); } | 176 JSOperatorBuilder* javascript() { return lowering_->javascript(); } |
| 169 MachineOperatorBuilder* machine() { return lowering_->machine(); } | 177 MachineOperatorBuilder* machine() { return lowering_->machine(); } |
| 178 Zone* zone() const { return graph()->zone(); } | |
| 170 | 179 |
| 171 private: | 180 private: |
| 172 JSTypedLowering* lowering_; // The containing lowering instance. | 181 JSTypedLowering* lowering_; // The containing lowering instance. |
| 173 Node* node_; // The original node. | 182 Node* node_; // The original node. |
| 174 Type* left_type_; // Cache of the left input's type. | 183 Type* left_type_; // Cache of the left input's type. |
| 175 Type* right_type_; // Cache of the right input's type. | 184 Type* right_type_; // Cache of the right input's type. |
| 176 | 185 |
| 177 Node* ConvertToString(Node* node) { | 186 Node* ConvertToString(Node* node) { |
| 178 // Avoid introducing too many eager ToString() operations. | 187 // Avoid introducing too many eager ToString() operations. |
| 179 Reduction reduced = lowering_->ReduceJSToStringInput(node); | 188 Reduction reduced = lowering_->ReduceJSToStringInput(node); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 void update_effect(Node* effect) { | 220 void update_effect(Node* effect) { |
| 212 NodeProperties::ReplaceEffectInput(node_, effect); | 221 NodeProperties::ReplaceEffectInput(node_, effect); |
| 213 } | 222 } |
| 214 }; | 223 }; |
| 215 | 224 |
| 216 | 225 |
| 217 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 226 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
| 218 JSBinopReduction r(this, node); | 227 JSBinopReduction r(this, node); |
| 219 if (r.BothInputsAre(Type::Number())) { | 228 if (r.BothInputsAre(Type::Number())) { |
| 220 // JSAdd(x:number, y:number) => NumberAdd(x, y) | 229 // JSAdd(x:number, y:number) => NumberAdd(x, y) |
| 221 return r.ChangeToPureOperator(simplified()->NumberAdd()); | 230 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
| 222 } | 231 } |
| 223 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); | 232 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); |
| 224 if (r.BothInputsAre(Type::Primitive()) && r.NeitherInputCanBe(maybe_string)) { | 233 if (r.BothInputsAre(Type::Primitive()) && r.NeitherInputCanBe(maybe_string)) { |
| 225 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 234 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
| 226 r.ConvertInputsToNumber(); | 235 r.ConvertInputsToNumber(); |
| 227 return r.ChangeToPureOperator(simplified()->NumberAdd()); | 236 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
| 228 } | 237 } |
| 229 #if 0 | 238 #if 0 |
| 230 // TODO(turbofan): General ToNumber disabled for now because: | 239 // TODO(turbofan): General ToNumber disabled for now because: |
| 231 // a) The inserted ToNumber operation screws up observability of valueOf. | 240 // a) The inserted ToNumber operation screws up observability of valueOf. |
| 232 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. | 241 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. |
| 233 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); | 242 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); |
| 234 if (r.NeitherInputCanBe(maybe_string)) { | 243 if (r.NeitherInputCanBe(maybe_string)) { |
| 235 ... | 244 ... |
| 236 } | 245 } |
| 237 #endif | 246 #endif |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 256 JSBinopReduction r(this, node); | 265 JSBinopReduction r(this, node); |
| 257 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(zero_range_)) { | 266 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(zero_range_)) { |
| 258 // TODO(jarin): Propagate frame state input from non-primitive input node to | 267 // TODO(jarin): Propagate frame state input from non-primitive input node to |
| 259 // JSToNumber node. | 268 // JSToNumber node. |
| 260 // TODO(titzer): some Smi bitwise operations don't really require going | 269 // TODO(titzer): some Smi bitwise operations don't really require going |
| 261 // all the way to int32, which can save tagging/untagging for some | 270 // all the way to int32, which can save tagging/untagging for some |
| 262 // operations | 271 // operations |
| 263 // on some platforms. | 272 // on some platforms. |
| 264 // TODO(turbofan): make this heuristic configurable for code size. | 273 // TODO(turbofan): make this heuristic configurable for code size. |
| 265 r.ConvertInputsToInt32(true, true); | 274 r.ConvertInputsToInt32(true, true); |
| 266 return r.ChangeToPureOperator(machine()->Word32Or()); | 275 return r.ChangeToPureOperator(machine()->Word32Or(), Type::Integral32()); |
| 267 } | 276 } |
| 268 return NoChange(); | 277 return NoChange(); |
| 269 } | 278 } |
| 270 | 279 |
| 271 | 280 |
| 272 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { | 281 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { |
| 273 JSBinopReduction r(this, node); | 282 JSBinopReduction r(this, node); |
| 274 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(one_range_)) { | 283 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(one_range_)) { |
| 275 // TODO(jarin): Propagate frame state input from non-primitive input node to | 284 // TODO(jarin): Propagate frame state input from non-primitive input node to |
| 276 // JSToNumber node. | 285 // JSToNumber node. |
| 277 r.ConvertInputsToNumber(); | 286 r.ConvertInputsToNumber(); |
| 278 return r.ChangeToPureOperator(simplified()->NumberMultiply()); | 287 return r.ChangeToPureOperator(simplified()->NumberMultiply(), |
| 288 Type::Number()); | |
| 279 } | 289 } |
| 280 // TODO(turbofan): relax/remove the effects of this operator in other cases. | 290 // TODO(turbofan): relax/remove the effects of this operator in other cases. |
| 281 return NoChange(); | 291 return NoChange(); |
| 282 } | 292 } |
| 283 | 293 |
| 284 | 294 |
| 285 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, | 295 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, |
| 286 const Operator* numberOp) { | 296 const Operator* numberOp) { |
| 287 JSBinopReduction r(this, node); | 297 JSBinopReduction r(this, node); |
| 288 if (r.BothInputsAre(Type::Primitive())) { | 298 if (r.BothInputsAre(Type::Primitive())) { |
| 289 r.ConvertInputsToNumber(); | 299 r.ConvertInputsToNumber(); |
| 290 return r.ChangeToPureOperator(numberOp); | 300 return r.ChangeToPureOperator(numberOp, Type::Number()); |
| 291 } | 301 } |
| 292 #if 0 | 302 #if 0 |
| 293 // TODO(turbofan): General ToNumber disabled for now because: | 303 // TODO(turbofan): General ToNumber disabled for now because: |
| 294 // a) The inserted ToNumber operation screws up observability of valueOf. | 304 // a) The inserted ToNumber operation screws up observability of valueOf. |
| 295 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. | 305 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. |
| 296 if (r.OneInputIs(Type::Primitive())) { | 306 if (r.OneInputIs(Type::Primitive())) { |
| 297 // If at least one input is a primitive, then insert appropriate conversions | 307 // If at least one input is a primitive, then insert appropriate conversions |
| 298 // to number and reduce this operator to the given numeric one. | 308 // to number and reduce this operator to the given numeric one. |
| 299 // TODO(turbofan): make this heuristic configurable for code size. | 309 // TODO(turbofan): make this heuristic configurable for code size. |
| 300 r.ConvertInputsToNumber(); | 310 r.ConvertInputsToNumber(); |
| 301 return r.ChangeToPureOperator(numberOp); | 311 return r.ChangeToPureOperator(numberOp); |
| 302 } | 312 } |
| 303 #endif | 313 #endif |
| 304 // TODO(turbofan): relax/remove the effects of this operator in other cases. | 314 // TODO(turbofan): relax/remove the effects of this operator in other cases. |
| 305 return NoChange(); | 315 return NoChange(); |
| 306 } | 316 } |
| 307 | 317 |
| 308 | 318 |
| 309 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed, | 319 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed, |
| 310 bool right_signed, | 320 bool right_signed, |
| 311 const Operator* intOp) { | 321 const Operator* intOp) { |
| 312 JSBinopReduction r(this, node); | 322 JSBinopReduction r(this, node); |
| 313 if (r.BothInputsAre(Type::Primitive())) { | 323 if (r.BothInputsAre(Type::Primitive())) { |
| 314 // TODO(titzer): some Smi bitwise operations don't really require going | 324 // TODO(titzer): some Smi bitwise operations don't really require going |
| 315 // all the way to int32, which can save tagging/untagging for some | 325 // all the way to int32, which can save tagging/untagging for some |
| 316 // operations | 326 // operations |
| 317 // on some platforms. | 327 // on some platforms. |
| 318 // TODO(turbofan): make this heuristic configurable for code size. | 328 // TODO(turbofan): make this heuristic configurable for code size. |
| 319 r.ConvertInputsToInt32(left_signed, right_signed); | 329 r.ConvertInputsToInt32(left_signed, right_signed); |
| 320 return r.ChangeToPureOperator(intOp); | 330 return r.ChangeToPureOperator(intOp, Type::Integral32()); |
| 321 } | 331 } |
| 322 return NoChange(); | 332 return NoChange(); |
| 323 } | 333 } |
| 324 | 334 |
| 325 | 335 |
| 326 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed, | 336 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed, |
| 327 const Operator* shift_op) { | 337 const Operator* shift_op) { |
| 328 JSBinopReduction r(this, node); | 338 JSBinopReduction r(this, node); |
| 329 if (r.BothInputsAre(Type::Primitive())) { | 339 if (r.BothInputsAre(Type::Primitive())) { |
| 330 r.ConvertInputsForShift(left_signed); | 340 r.ConvertInputsForShift(left_signed); |
| 331 return r.ChangeToPureOperator(shift_op); | 341 return r.ChangeToPureOperator(shift_op, Type::Integral32()); |
| 332 } | 342 } |
| 333 return NoChange(); | 343 return NoChange(); |
| 334 } | 344 } |
| 335 | 345 |
| 336 | 346 |
| 337 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { | 347 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { |
| 338 JSBinopReduction r(this, node); | 348 JSBinopReduction r(this, node); |
| 339 if (r.BothInputsAre(Type::String())) { | 349 if (r.BothInputsAre(Type::String())) { |
| 340 // If both inputs are definitely strings, perform a string comparison. | 350 // If both inputs are definitely strings, perform a string comparison. |
| 341 const Operator* stringOp; | 351 const Operator* stringOp; |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 899 | 909 |
| 900 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { | 910 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { |
| 901 if (rhs == 0) return lhs; | 911 if (rhs == 0) return lhs; |
| 902 return graph()->NewNode(machine()->Word32Shl(), lhs, | 912 return graph()->NewNode(machine()->Word32Shl(), lhs, |
| 903 jsgraph()->Int32Constant(rhs)); | 913 jsgraph()->Int32Constant(rhs)); |
| 904 } | 914 } |
| 905 | 915 |
| 906 } // namespace compiler | 916 } // namespace compiler |
| 907 } // namespace internal | 917 } // namespace internal |
| 908 } // namespace v8 | 918 } // namespace v8 |
| OLD | NEW |