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/change-lowering.h" | 5 #include "src/compiler/change-lowering.h" |
6 | 6 |
7 #include "src/address-map.h" | 7 #include "src/address-map.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 Node* control = graph()->start(); | 24 Node* control = graph()->start(); |
25 switch (node->opcode()) { | 25 switch (node->opcode()) { |
26 case IrOpcode::kChangeBitToBool: | 26 case IrOpcode::kChangeBitToBool: |
27 return ChangeBitToBool(node->InputAt(0), control); | 27 return ChangeBitToBool(node->InputAt(0), control); |
28 case IrOpcode::kChangeBoolToBit: | 28 case IrOpcode::kChangeBoolToBit: |
29 return ChangeBoolToBit(node->InputAt(0)); | 29 return ChangeBoolToBit(node->InputAt(0)); |
30 case IrOpcode::kChangeFloat64ToTagged: | 30 case IrOpcode::kChangeFloat64ToTagged: |
31 return ChangeFloat64ToTagged(node->InputAt(0), control); | 31 return ChangeFloat64ToTagged(node->InputAt(0), control); |
32 case IrOpcode::kChangeInt32ToTagged: | 32 case IrOpcode::kChangeInt32ToTagged: |
33 return ChangeInt32ToTagged(node->InputAt(0), control); | 33 return ChangeInt32ToTagged(node->InputAt(0), control); |
| 34 case IrOpcode::kChangeTaggedSignedToWord32: |
| 35 return ChangeTaggedSignedToWord32(node->InputAt(0)); |
34 case IrOpcode::kChangeTaggedToFloat64: | 36 case IrOpcode::kChangeTaggedToFloat64: |
35 return ChangeTaggedToFloat64(node->InputAt(0), control); | 37 return ChangeTaggedToFloat64(node->InputAt(0), control); |
36 case IrOpcode::kChangeTaggedToInt32: | 38 case IrOpcode::kChangeTaggedToInt32: |
37 return ChangeTaggedToUI32(node->InputAt(0), control, kSigned); | 39 return ChangeTaggedToUI32(node->InputAt(0), control, kSigned); |
38 case IrOpcode::kChangeTaggedToUint32: | 40 case IrOpcode::kChangeTaggedToUint32: |
39 return ChangeTaggedToUI32(node->InputAt(0), control, kUnsigned); | 41 return ChangeTaggedToUI32(node->InputAt(0), control, kUnsigned); |
40 case IrOpcode::kChangeUint32ToTagged: | 42 case IrOpcode::kChangeUint32ToTagged: |
41 return ChangeUint32ToTagged(node->InputAt(0), control); | 43 return ChangeUint32ToTagged(node->InputAt(0), control); |
42 case IrOpcode::kLoadField: | 44 case IrOpcode::kLoadField: |
43 return LoadField(node); | 45 return LoadField(node); |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 272 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
271 Node* vfalse = graph()->NewNode(common()->Projection(0), add); | 273 Node* vfalse = graph()->NewNode(common()->Projection(0), add); |
272 | 274 |
273 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); | 275 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
274 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 276 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
275 vtrue, vfalse, merge); | 277 vtrue, vfalse, merge); |
276 | 278 |
277 return Replace(phi); | 279 return Replace(phi); |
278 } | 280 } |
279 | 281 |
| 282 Reduction ChangeLowering::ChangeTaggedSignedToWord32(Node* value) { |
| 283 return Replace(ChangeSmiToInt32(value)); |
| 284 } |
280 | 285 |
281 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control, | 286 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control, |
282 Signedness signedness) { | 287 Signedness signedness) { |
283 if (NodeProperties::GetType(value)->Is(Type::TaggedSigned())) { | 288 if (NodeProperties::GetType(value)->Is(Type::TaggedSigned())) { |
284 return Replace(ChangeSmiToInt32(value)); | 289 return Replace(ChangeSmiToInt32(value)); |
285 } | 290 } |
286 | 291 |
287 const Operator* op = (signedness == kSigned) | 292 const Operator* op = (signedness == kSigned) |
288 ? machine()->ChangeFloat64ToInt32() | 293 ? machine()->ChangeFloat64ToInt32() |
289 : machine()->ChangeFloat64ToUint32(); | 294 : machine()->ChangeFloat64ToUint32(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 Node* vfrom_smi = ChangeSmiToInt32(value); | 332 Node* vfrom_smi = ChangeSmiToInt32(value); |
328 | 333 |
329 Node* merge = graph()->NewNode(common()->Merge(2), if_not_smi, if_smi); | 334 Node* merge = graph()->NewNode(common()->Merge(2), if_not_smi, if_smi); |
330 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | 335 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
331 vnot_smi, vfrom_smi, merge); | 336 vnot_smi, vfrom_smi, merge); |
332 | 337 |
333 return Replace(phi); | 338 return Replace(phi); |
334 } | 339 } |
335 | 340 |
336 | 341 |
337 namespace { | |
338 | |
339 bool CanCover(Node* value, IrOpcode::Value opcode) { | |
340 if (value->opcode() != opcode) return false; | |
341 bool first = true; | |
342 for (Edge const edge : value->use_edges()) { | |
343 if (NodeProperties::IsControlEdge(edge)) continue; | |
344 if (NodeProperties::IsEffectEdge(edge)) continue; | |
345 DCHECK(NodeProperties::IsValueEdge(edge)); | |
346 if (!first) return false; | |
347 first = false; | |
348 } | |
349 return true; | |
350 } | |
351 | |
352 } // namespace | |
353 | |
354 | |
355 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) { | 342 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) { |
356 if (CanCover(value, IrOpcode::kJSToNumber)) { | |
357 // ChangeTaggedToFloat64(JSToNumber(x)) => | |
358 // if IsSmi(x) then ChangeSmiToFloat64(x) | |
359 // else let y = JSToNumber(x) in | |
360 // if IsSmi(y) then ChangeSmiToFloat64(y) | |
361 // else LoadHeapNumberValue(y) | |
362 Node* const object = NodeProperties::GetValueInput(value, 0); | |
363 Node* const context = NodeProperties::GetContextInput(value); | |
364 Node* const frame_state = NodeProperties::GetFrameStateInput(value, 0); | |
365 Node* const effect = NodeProperties::GetEffectInput(value); | |
366 Node* const control = NodeProperties::GetControlInput(value); | |
367 | |
368 const Operator* merge_op = common()->Merge(2); | |
369 const Operator* ephi_op = common()->EffectPhi(2); | |
370 const Operator* phi_op = common()->Phi(MachineRepresentation::kFloat64, 2); | |
371 | |
372 Node* check1 = TestNotSmi(object); | |
373 Node* branch1 = | |
374 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control); | |
375 | |
376 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
377 Node* vtrue1 = graph()->NewNode(value->op(), object, context, frame_state, | |
378 effect, if_true1); | |
379 Node* etrue1 = vtrue1; | |
380 | |
381 Node* check2 = TestNotSmi(vtrue1); | |
382 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_true1); | |
383 | |
384 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
385 Node* vtrue2 = LoadHeapNumberValue(vtrue1, if_true2); | |
386 | |
387 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
388 Node* vfalse2 = ChangeSmiToFloat64(vtrue1); | |
389 | |
390 if_true1 = graph()->NewNode(merge_op, if_true2, if_false2); | |
391 vtrue1 = graph()->NewNode(phi_op, vtrue2, vfalse2, if_true1); | |
392 | |
393 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
394 Node* vfalse1 = ChangeSmiToFloat64(object); | |
395 Node* efalse1 = effect; | |
396 | |
397 Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1); | |
398 Node* ephi1 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1); | |
399 Node* phi1 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1); | |
400 | |
401 // Wire the new diamond into the graph, {JSToNumber} can still throw. | |
402 NodeProperties::ReplaceUses(value, phi1, ephi1, etrue1, etrue1); | |
403 | |
404 // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from | |
405 // the node and places it inside the diamond. Come up with a helper method! | |
406 for (Node* use : etrue1->uses()) { | |
407 if (use->opcode() == IrOpcode::kIfSuccess) { | |
408 use->ReplaceUses(merge1); | |
409 NodeProperties::ReplaceControlInput(branch2, use); | |
410 } | |
411 } | |
412 | |
413 return Replace(phi1); | |
414 } | |
415 | |
416 Node* check = TestNotSmi(value); | 343 Node* check = TestNotSmi(value); |
417 Node* branch = | 344 Node* branch = |
418 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | 345 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); |
419 | 346 |
420 Node* if_not_smi = graph()->NewNode(common()->IfTrue(), branch); | 347 Node* if_not_smi = graph()->NewNode(common()->IfTrue(), branch); |
421 | 348 |
422 Node* vnot_smi; | 349 Node* vnot_smi; |
423 if (NodeProperties::GetType(value)->Maybe(Type::Undefined())) { | 350 if (NodeProperties::GetType(value)->Maybe(Type::Undefined())) { |
424 Node* check_undefined = graph()->NewNode(machine()->WordEqual(), value, | 351 Node* check_undefined = graph()->NewNode(machine()->WordEqual(), value, |
425 jsgraph()->UndefinedConstant()); | 352 jsgraph()->UndefinedConstant()); |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 } | 708 } |
782 | 709 |
783 | 710 |
784 MachineOperatorBuilder* ChangeLowering::machine() const { | 711 MachineOperatorBuilder* ChangeLowering::machine() const { |
785 return jsgraph()->machine(); | 712 return jsgraph()->machine(); |
786 } | 713 } |
787 | 714 |
788 } // namespace compiler | 715 } // namespace compiler |
789 } // namespace internal | 716 } // namespace internal |
790 } // namespace v8 | 717 } // namespace v8 |
OLD | NEW |