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-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 } | 520 } |
521 // TODO(turbofan): js-typed-lowering of ToString(x:boolean) | 521 // TODO(turbofan): js-typed-lowering of ToString(x:boolean) |
522 // TODO(turbofan): js-typed-lowering of ToString(x:number) | 522 // TODO(turbofan): js-typed-lowering of ToString(x:number) |
523 return NoChange(); | 523 return NoChange(); |
524 } | 524 } |
525 | 525 |
526 | 526 |
527 Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) { | 527 Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) { |
528 if (input->opcode() == IrOpcode::kJSToBoolean) { | 528 if (input->opcode() == IrOpcode::kJSToBoolean) { |
529 // Recursively try to reduce the input first. | 529 // Recursively try to reduce the input first. |
530 Reduction result = ReduceJSToBooleanInput(input->InputAt(0)); | 530 Reduction result = ReduceJSToBoolean(input); |
531 if (result.Changed()) { | 531 if (result.Changed()) return result; |
532 RelaxEffects(input); | |
533 return result; | |
534 } | |
535 return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x) | 532 return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x) |
536 } | 533 } |
537 Type* input_type = NodeProperties::GetBounds(input).upper; | 534 Type* input_type = NodeProperties::GetBounds(input).upper; |
538 if (input_type->Is(Type::Boolean())) { | 535 if (input_type->Is(Type::Boolean())) { |
539 return Changed(input); // JSToBoolean(x:boolean) => x | 536 return Changed(input); // JSToBoolean(x:boolean) => x |
540 } | 537 } |
541 if (input_type->Is(Type::Undefined())) { | 538 if (input_type->Is(Type::Undefined())) { |
542 // JSToBoolean(undefined) => #false | 539 // JSToBoolean(undefined) => #false |
543 return ReplaceWith(jsgraph()->FalseConstant()); | 540 return ReplaceWith(jsgraph()->FalseConstant()); |
544 } | 541 } |
(...skipping 19 matching lines...) Expand all Loading... |
564 if (input_type->Is(Type::String())) { | 561 if (input_type->Is(Type::String())) { |
565 // JSToBoolean(x:string) => BooleanNot(NumberEqual(x.length, #0)) | 562 // JSToBoolean(x:string) => BooleanNot(NumberEqual(x.length, #0)) |
566 FieldAccess access = AccessBuilder::ForStringLength(); | 563 FieldAccess access = AccessBuilder::ForStringLength(); |
567 Node* length = graph()->NewNode(simplified()->LoadField(access), input, | 564 Node* length = graph()->NewNode(simplified()->LoadField(access), input, |
568 graph()->start(), graph()->start()); | 565 graph()->start(), graph()->start()); |
569 Node* cmp = graph()->NewNode(simplified()->NumberEqual(), length, | 566 Node* cmp = graph()->NewNode(simplified()->NumberEqual(), length, |
570 jsgraph()->ZeroConstant()); | 567 jsgraph()->ZeroConstant()); |
571 Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp); | 568 Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp); |
572 return ReplaceWith(inv); | 569 return ReplaceWith(inv); |
573 } | 570 } |
574 // TODO(turbofan): We need some kinda of PrimitiveToBoolean simplified | 571 return NoChange(); |
575 // operator, then we can do the pushing in the SimplifiedOperatorReducer | 572 } |
576 // and do not need to protect against stack overflow (because of backedges | 573 |
577 // in phis) below. | 574 |
578 if (input->opcode() == IrOpcode::kPhi && | 575 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
579 input_type->Is( | 576 // Try to reduce the input first. |
580 Type::Union(Type::Boolean(), Type::OrderedNumber(), zone()))) { | 577 Node* const input = node->InputAt(0); |
581 // JSToBoolean(phi(x1,...,xn):ordered-number|boolean) | 578 Reduction reduction = ReduceJSToBooleanInput(input); |
582 // => phi(JSToBoolean(x1),...,JSToBoolean(xn)) | 579 if (reduction.Changed()) { |
583 int input_count = input->InputCount() - 1; | 580 NodeProperties::ReplaceWithValue(node, reduction.replacement()); |
584 Node** inputs = zone()->NewArray<Node*>(input_count + 1); | 581 return reduction; |
| 582 } |
| 583 Type* const input_type = NodeProperties::GetBounds(input).upper; |
| 584 if (input->opcode() == IrOpcode::kPhi && input_type->Is(Type::Primitive())) { |
| 585 // JSToBoolean(phi(x1,...,xn,control):primitive) |
| 586 // => phi(JSToBoolean(x1),...,JSToBoolean(xn),control):boolean |
| 587 RelaxEffects(node); |
| 588 int const input_count = input->InputCount() - 1; |
| 589 Node* const control = input->InputAt(input_count); |
| 590 DCHECK_LE(0, input_count); |
| 591 DCHECK(NodeProperties::IsControl(control)); |
| 592 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); |
| 593 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); |
| 594 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
585 for (int i = 0; i < input_count; ++i) { | 595 for (int i = 0; i < input_count; ++i) { |
586 Node* value = input->InputAt(i); | 596 Node* value = input->InputAt(i); |
587 Type* value_type = NodeProperties::GetBounds(value).upper; | |
588 // Recursively try to reduce the value first. | 597 // Recursively try to reduce the value first. |
589 Reduction result = (value_type->Is(Type::Boolean()) || | 598 Reduction reduction = ReduceJSToBooleanInput(value); |
590 value_type->Is(Type::OrderedNumber())) | 599 if (reduction.Changed()) { |
591 ? ReduceJSToBooleanInput(value) | 600 value = reduction.replacement(); |
592 : NoChange(); | |
593 if (result.Changed()) { | |
594 inputs[i] = result.replacement(); | |
595 } else { | 601 } else { |
596 inputs[i] = graph()->NewNode(javascript()->ToBoolean(), value, | 602 value = graph()->NewNode(javascript()->ToBoolean(), value, |
597 jsgraph()->ZeroConstant(), | 603 jsgraph()->ZeroConstant(), graph()->start(), |
598 graph()->start(), graph()->start()); | 604 graph()->start()); |
| 605 } |
| 606 if (i < node->InputCount()) { |
| 607 node->ReplaceInput(i, value); |
| 608 } else { |
| 609 node->AppendInput(graph()->zone(), value); |
599 } | 610 } |
600 } | 611 } |
601 inputs[input_count] = input->InputAt(input_count); | 612 if (input_count < node->InputCount()) { |
602 Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, input_count), | 613 node->ReplaceInput(input_count, control); |
603 input_count + 1, inputs); | 614 } else { |
604 return ReplaceWith(phi); | 615 node->AppendInput(graph()->zone(), control); |
| 616 } |
| 617 node->TrimInputCount(input_count + 1); |
| 618 return Changed(node); |
605 } | 619 } |
606 return NoChange(); | 620 return NoChange(); |
607 } | 621 } |
608 | 622 |
609 | 623 |
610 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { | 624 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) { |
611 Node* key = NodeProperties::GetValueInput(node, 1); | 625 Node* key = NodeProperties::GetValueInput(node, 1); |
612 Node* base = NodeProperties::GetValueInput(node, 0); | 626 Node* base = NodeProperties::GetValueInput(node, 0); |
613 Type* key_type = NodeProperties::GetBounds(key).upper; | 627 Type* key_type = NodeProperties::GetBounds(key).upper; |
614 Type* base_type = NodeProperties::GetBounds(base).upper; | 628 Type* base_type = NodeProperties::GetBounds(base).upper; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 // JSUnaryNot(x) => BooleanNot(JSToBoolean(x)) | 760 // JSUnaryNot(x) => BooleanNot(JSToBoolean(x)) |
747 value = graph()->NewNode(simplified()->BooleanNot(), node); | 761 value = graph()->NewNode(simplified()->BooleanNot(), node); |
748 node->set_op(javascript()->ToBoolean()); | 762 node->set_op(javascript()->ToBoolean()); |
749 NodeProperties::ReplaceWithValue(node, value, node); | 763 NodeProperties::ReplaceWithValue(node, value, node); |
750 // Note: ReplaceUses() smashes all uses, so smash it back here. | 764 // Note: ReplaceUses() smashes all uses, so smash it back here. |
751 value->ReplaceInput(0, node); | 765 value->ReplaceInput(0, node); |
752 return Changed(node); | 766 return Changed(node); |
753 } | 767 } |
754 } | 768 } |
755 case IrOpcode::kJSToBoolean: | 769 case IrOpcode::kJSToBoolean: |
756 return ReplaceWithReduction(node, | 770 return ReduceJSToBoolean(node); |
757 ReduceJSToBooleanInput(node->InputAt(0))); | |
758 case IrOpcode::kJSToNumber: | 771 case IrOpcode::kJSToNumber: |
759 return ReplaceWithReduction(node, | 772 return ReplaceWithReduction(node, |
760 ReduceJSToNumberInput(node->InputAt(0))); | 773 ReduceJSToNumberInput(node->InputAt(0))); |
761 case IrOpcode::kJSToString: | 774 case IrOpcode::kJSToString: |
762 return ReplaceWithReduction(node, | 775 return ReplaceWithReduction(node, |
763 ReduceJSToStringInput(node->InputAt(0))); | 776 ReduceJSToStringInput(node->InputAt(0))); |
764 case IrOpcode::kJSLoadProperty: | 777 case IrOpcode::kJSLoadProperty: |
765 return ReduceJSLoadProperty(node); | 778 return ReduceJSLoadProperty(node); |
766 case IrOpcode::kJSStoreProperty: | 779 case IrOpcode::kJSStoreProperty: |
767 return ReduceJSStoreProperty(node); | 780 return ReduceJSStoreProperty(node); |
768 case IrOpcode::kJSCallFunction: | 781 case IrOpcode::kJSCallFunction: |
769 return JSBuiltinReducer(jsgraph()).Reduce(node); | 782 return JSBuiltinReducer(jsgraph()).Reduce(node); |
770 default: | 783 default: |
771 break; | 784 break; |
772 } | 785 } |
773 return NoChange(); | 786 return NoChange(); |
774 } | 787 } |
775 | 788 |
776 } // namespace compiler | 789 } // namespace compiler |
777 } // namespace internal | 790 } // namespace internal |
778 } // namespace v8 | 791 } // namespace v8 |
OLD | NEW |