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::kChangeSmiToInt32: |
| 35 return ChangeSmiToInt32(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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 | 116 |
115 Node* ChangeLowering::ChangeInt32ToSmi(Node* value) { | 117 Node* ChangeLowering::ChangeInt32ToSmi(Node* value) { |
116 if (machine()->Is64()) { | 118 if (machine()->Is64()) { |
117 value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value); | 119 value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value); |
118 } | 120 } |
119 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()); | 121 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()); |
120 } | 122 } |
121 | 123 |
122 | 124 |
123 Node* ChangeLowering::ChangeSmiToFloat64(Node* value) { | 125 Node* ChangeLowering::ChangeSmiToFloat64(Node* value) { |
124 return ChangeInt32ToFloat64(ChangeSmiToInt32(value)); | 126 return ChangeInt32ToFloat64(ChangeSmiToWord32(value)); |
125 } | 127 } |
126 | 128 |
127 | 129 Node* ChangeLowering::ChangeSmiToWord32(Node* value) { |
128 Node* ChangeLowering::ChangeSmiToInt32(Node* value) { | |
129 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); | 130 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); |
130 if (machine()->Is64()) { | 131 if (machine()->Is64()) { |
131 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); | 132 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); |
132 } | 133 } |
133 return value; | 134 return value; |
134 } | 135 } |
135 | 136 |
136 | 137 |
137 Node* ChangeLowering::ChangeUint32ToFloat64(Node* value) { | 138 Node* ChangeLowering::ChangeUint32ToFloat64(Node* value) { |
138 return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value); | 139 return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 271 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
271 Node* vfalse = graph()->NewNode(common()->Projection(0), add); | 272 Node* vfalse = graph()->NewNode(common()->Projection(0), add); |
272 | 273 |
273 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); | 274 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
274 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 275 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
275 vtrue, vfalse, merge); | 276 vtrue, vfalse, merge); |
276 | 277 |
277 return Replace(phi); | 278 return Replace(phi); |
278 } | 279 } |
279 | 280 |
| 281 Reduction ChangeLowering::ChangeSmiToInt32(Node* value) { |
| 282 return Replace(ChangeSmiToWord32(value)); |
| 283 } |
280 | 284 |
281 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control, | 285 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control, |
282 Signedness signedness) { | 286 Signedness signedness) { |
283 if (NodeProperties::GetType(value)->Is(Type::TaggedSigned())) { | 287 if (NodeProperties::GetType(value)->Is(Type::TaggedSigned())) { |
284 return Replace(ChangeSmiToInt32(value)); | 288 return ChangeSmiToInt32(value); |
285 } | 289 } |
286 | 290 |
287 const Operator* op = (signedness == kSigned) | 291 const Operator* op = (signedness == kSigned) |
288 ? machine()->ChangeFloat64ToInt32() | 292 ? machine()->ChangeFloat64ToInt32() |
289 : machine()->ChangeFloat64ToUint32(); | 293 : machine()->ChangeFloat64ToUint32(); |
290 | 294 |
291 if (NodeProperties::GetType(value)->Is(Type::TaggedPointer()) && | 295 if (NodeProperties::GetType(value)->Is(Type::TaggedPointer()) && |
292 NodeProperties::GetType(value)->Is(Type::Number())) { | 296 NodeProperties::GetType(value)->Is(Type::Number())) { |
293 return Replace(graph()->NewNode(op, LoadHeapNumberValue(value, control))); | 297 return Replace(graph()->NewNode(op, LoadHeapNumberValue(value, control))); |
294 } | 298 } |
(...skipping 22 matching lines...) Expand all Loading... |
317 if_not_smi = | 321 if_not_smi = |
318 graph()->NewNode(common()->Merge(2), if_undefined, if_not_undefined); | 322 graph()->NewNode(common()->Merge(2), if_undefined, if_not_undefined); |
319 vnot_smi = | 323 vnot_smi = |
320 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | 324 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
321 vundefined, vheap_number, if_not_smi); | 325 vundefined, vheap_number, if_not_smi); |
322 } else { | 326 } else { |
323 vnot_smi = graph()->NewNode(op, LoadHeapNumberValue(value, if_not_smi)); | 327 vnot_smi = graph()->NewNode(op, LoadHeapNumberValue(value, if_not_smi)); |
324 } | 328 } |
325 | 329 |
326 Node* if_smi = graph()->NewNode(common()->IfFalse(), branch); | 330 Node* if_smi = graph()->NewNode(common()->IfFalse(), branch); |
327 Node* vfrom_smi = ChangeSmiToInt32(value); | 331 Node* vfrom_smi = ChangeSmiToWord32(value); |
328 | 332 |
329 Node* merge = graph()->NewNode(common()->Merge(2), if_not_smi, if_smi); | 333 Node* merge = graph()->NewNode(common()->Merge(2), if_not_smi, if_smi); |
330 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | 334 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
331 vnot_smi, vfrom_smi, merge); | 335 vnot_smi, vfrom_smi, merge); |
332 | 336 |
333 return Replace(phi); | 337 return Replace(phi); |
334 } | 338 } |
335 | 339 |
336 | 340 |
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) { | 341 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); | 342 Node* check = TestNotSmi(value); |
417 Node* branch = | 343 Node* branch = |
418 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | 344 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); |
419 | 345 |
420 Node* if_not_smi = graph()->NewNode(common()->IfTrue(), branch); | 346 Node* if_not_smi = graph()->NewNode(common()->IfTrue(), branch); |
421 | 347 |
422 Node* vnot_smi; | 348 Node* vnot_smi; |
423 if (NodeProperties::GetType(value)->Maybe(Type::Undefined())) { | 349 if (NodeProperties::GetType(value)->Maybe(Type::Undefined())) { |
424 Node* check_undefined = graph()->NewNode(machine()->WordEqual(), value, | 350 Node* check_undefined = graph()->NewNode(machine()->WordEqual(), value, |
425 jsgraph()->UndefinedConstant()); | 351 jsgraph()->UndefinedConstant()); |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 } | 707 } |
782 | 708 |
783 | 709 |
784 MachineOperatorBuilder* ChangeLowering::machine() const { | 710 MachineOperatorBuilder* ChangeLowering::machine() const { |
785 return jsgraph()->machine(); | 711 return jsgraph()->machine(); |
786 } | 712 } |
787 | 713 |
788 } // namespace compiler | 714 } // namespace compiler |
789 } // namespace internal | 715 } // namespace internal |
790 } // namespace v8 | 716 } // namespace v8 |
OLD | NEW |