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/js-builtin-reducer.h" | 5 #include "src/compiler/js-builtin-reducer.h" |
6 | 6 |
7 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
536 // String.fromCharCode(a:plain-primitive) -> StringFromCharCode(a) | 536 // String.fromCharCode(a:plain-primitive) -> StringFromCharCode(a) |
537 Node* input = ToNumber(r.GetJSCallInput(0)); | 537 Node* input = ToNumber(r.GetJSCallInput(0)); |
538 Node* value = graph()->NewNode(simplified()->StringFromCharCode(), input); | 538 Node* value = graph()->NewNode(simplified()->StringFromCharCode(), input); |
539 return Replace(value); | 539 return Replace(value); |
540 } | 540 } |
541 return NoChange(); | 541 return NoChange(); |
542 } | 542 } |
543 | 543 |
544 namespace { | 544 namespace { |
545 | 545 |
546 Node* GetStringReceiver(Node* node) { | 546 Node* GetStringWitness(Node* node) { |
547 Node* receiver = NodeProperties::GetValueInput(node, 1); | 547 Node* receiver = NodeProperties::GetValueInput(node, 1); |
548 Type* receiver_type = NodeProperties::GetType(receiver); | 548 Type* receiver_type = NodeProperties::GetType(receiver); |
549 Node* effect = NodeProperties::GetEffectInput(node); | 549 Node* effect = NodeProperties::GetEffectInput(node); |
550 if (receiver_type->Is(Type::String())) return receiver; | 550 if (receiver_type->Is(Type::String())) return receiver; |
551 // Check if the {node} is dominated by a CheckString renaming for | 551 // Check if the {node} is dominated by a CheckString renaming for |
552 // it's {receiver}, and if so use that renaming as {receiver} for | 552 // it's {receiver}, and if so use that renaming as {receiver} for |
553 // the lowering below. | 553 // the lowering below. |
554 for (Node* dominator = effect;;) { | 554 for (Node* dominator = effect;;) { |
555 if (dominator->opcode() == IrOpcode::kCheckString && | 555 if (dominator->opcode() == IrOpcode::kCheckString && |
556 dominator->InputAt(0) == receiver) { | 556 dominator->InputAt(0) == receiver) { |
(...skipping 12 matching lines...) Expand all Loading... | |
569 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) | 569 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) |
570 Reduction JSBuiltinReducer::ReduceStringCharAt(Node* node) { | 570 Reduction JSBuiltinReducer::ReduceStringCharAt(Node* node) { |
571 // We need at least target, receiver and index parameters. | 571 // We need at least target, receiver and index parameters. |
572 if (node->op()->ValueInputCount() >= 3) { | 572 if (node->op()->ValueInputCount() >= 3) { |
573 Node* index = NodeProperties::GetValueInput(node, 2); | 573 Node* index = NodeProperties::GetValueInput(node, 2); |
574 Type* index_type = NodeProperties::GetType(index); | 574 Type* index_type = NodeProperties::GetType(index); |
575 Node* effect = NodeProperties::GetEffectInput(node); | 575 Node* effect = NodeProperties::GetEffectInput(node); |
576 Node* control = NodeProperties::GetControlInput(node); | 576 Node* control = NodeProperties::GetControlInput(node); |
577 | 577 |
578 if (index_type->Is(Type::Unsigned32())) { | 578 if (index_type->Is(Type::Unsigned32())) { |
579 if (Node* receiver = GetStringReceiver(node)) { | 579 if (Node* receiver = GetStringWitness(node)) { |
580 // Determine the {receiver} length. | 580 // Determine the {receiver} length. |
581 Node* receiver_length = effect = graph()->NewNode( | 581 Node* receiver_length = effect = graph()->NewNode( |
582 simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, | 582 simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, |
583 effect, control); | 583 effect, control); |
584 | 584 |
585 // Check if {index} is less than {receiver} length. | 585 // Check if {index} is less than {receiver} length. |
586 Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, | 586 Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, |
587 receiver_length); | 587 receiver_length); |
588 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 588 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
589 check, control); | 589 check, control); |
(...skipping 30 matching lines...) Expand all Loading... | |
620 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) | 620 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) |
621 Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) { | 621 Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) { |
622 // We need at least target, receiver and index parameters. | 622 // We need at least target, receiver and index parameters. |
623 if (node->op()->ValueInputCount() >= 3) { | 623 if (node->op()->ValueInputCount() >= 3) { |
624 Node* index = NodeProperties::GetValueInput(node, 2); | 624 Node* index = NodeProperties::GetValueInput(node, 2); |
625 Type* index_type = NodeProperties::GetType(index); | 625 Type* index_type = NodeProperties::GetType(index); |
626 Node* effect = NodeProperties::GetEffectInput(node); | 626 Node* effect = NodeProperties::GetEffectInput(node); |
627 Node* control = NodeProperties::GetControlInput(node); | 627 Node* control = NodeProperties::GetControlInput(node); |
628 | 628 |
629 if (index_type->Is(Type::Unsigned32())) { | 629 if (index_type->Is(Type::Unsigned32())) { |
630 if (Node* receiver = GetStringReceiver(node)) { | 630 if (Node* receiver = GetStringWitness(node)) { |
631 // Determine the {receiver} length. | 631 // Determine the {receiver} length. |
632 Node* receiver_length = effect = graph()->NewNode( | 632 Node* receiver_length = effect = graph()->NewNode( |
633 simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, | 633 simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, |
634 effect, control); | 634 effect, control); |
635 | 635 |
636 // Check if {index} is less than {receiver} length. | 636 // Check if {index} is less than {receiver} length. |
637 Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, | 637 Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, |
638 receiver_length); | 638 receiver_length); |
639 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 639 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
640 check, control); | 640 check, control); |
(...skipping 14 matching lines...) Expand all Loading... | |
655 | 655 |
656 ReplaceWithValue(node, value, effect, control); | 656 ReplaceWithValue(node, value, effect, control); |
657 return Replace(value); | 657 return Replace(value); |
658 } | 658 } |
659 } | 659 } |
660 } | 660 } |
661 | 661 |
662 return NoChange(); | 662 return NoChange(); |
663 } | 663 } |
664 | 664 |
665 namespace { | |
666 | |
667 bool HasInstanceTypeWitness(Node* receiver, Node* effect, | |
668 InstanceType instance_type) { | |
669 for (Node* dominator = effect;;) { | |
670 if (dominator->opcode() == IrOpcode::kCheckMaps && | |
671 dominator->InputAt(0) == receiver) { | |
672 // Check if all maps have the given {instance_type}. | |
673 for (int i = 1; i < dominator->op()->ValueInputCount(); ++i) { | |
674 Node* const map = NodeProperties::GetValueInput(dominator, i); | |
675 Type* const map_type = NodeProperties::GetType(map); | |
676 if (!map_type->IsConstant()) return false; | |
677 Handle<Map> const map_value = | |
678 Handle<Map>::cast(map_type->AsConstant()->Value()); | |
679 if (map_value->instance_type() != instance_type) return false; | |
680 } | |
681 return dominator; | |
epertoso
2016/08/01 10:27:09
how about return true?
Benedikt Meurer
2016/08/01 10:32:44
Done.
| |
682 } | |
683 switch (dominator->opcode()) { | |
684 case IrOpcode::kStoreField: { | |
685 FieldAccess const& access = FieldAccessOf(dominator->op()); | |
686 if (access.base_is_tagged == kTaggedBase && | |
687 access.offset == HeapObject::kMapOffset) { | |
688 return false; | |
689 } | |
690 break; | |
691 } | |
692 case IrOpcode::kStoreElement: | |
693 break; | |
694 default: { | |
695 DCHECK_EQ(1, dominator->op()->EffectOutputCount()); | |
696 if (dominator->op()->EffectInputCount() != 1 || | |
697 !dominator->op()->HasProperty(Operator::kNoWrite)) { | |
698 // Didn't find any appropriate CheckMaps node. | |
699 return false; | |
700 } | |
701 break; | |
702 } | |
703 } | |
704 dominator = NodeProperties::GetEffectInput(dominator); | |
705 } | |
706 } | |
707 | |
708 } // namespace | |
709 | |
710 Reduction JSBuiltinReducer::ReduceArrayBufferViewAccessor( | |
711 Node* node, InstanceType instance_type, FieldAccess const& access) { | |
712 Node* receiver = NodeProperties::GetValueInput(node, 1); | |
713 Node* effect = NodeProperties::GetEffectInput(node); | |
714 Node* control = NodeProperties::GetControlInput(node); | |
715 if (HasInstanceTypeWitness(receiver, effect, instance_type)) { | |
716 // Load the {receiver}s field. | |
717 Node* receiver_length = effect = graph()->NewNode( | |
718 simplified()->LoadField(access), receiver, effect, control); | |
719 | |
720 // Check if the {receiver}s buffer was neutered. | |
721 Node* receiver_buffer = effect = graph()->NewNode( | |
722 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()), | |
723 receiver, effect, control); | |
724 Node* receiver_buffer_bitfield = effect = graph()->NewNode( | |
725 simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()), | |
726 receiver_buffer, effect, control); | |
727 Node* check = graph()->NewNode( | |
728 simplified()->NumberEqual(), | |
729 graph()->NewNode( | |
730 simplified()->NumberBitwiseAnd(), receiver_buffer_bitfield, | |
731 jsgraph()->Constant(JSArrayBuffer::WasNeutered::kMask)), | |
732 jsgraph()->ZeroConstant()); | |
733 | |
734 // Default to zero if the {receiver}s buffer was neutered. | |
735 Node* value = | |
736 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), | |
737 check, receiver_length, jsgraph()->ZeroConstant()); | |
738 | |
739 ReplaceWithValue(node, value, effect, control); | |
740 return Replace(value); | |
741 } | |
742 return NoChange(); | |
743 } | |
744 | |
665 Reduction JSBuiltinReducer::Reduce(Node* node) { | 745 Reduction JSBuiltinReducer::Reduce(Node* node) { |
666 Reduction reduction = NoChange(); | 746 Reduction reduction = NoChange(); |
667 JSCallReduction r(node); | 747 JSCallReduction r(node); |
668 | 748 |
669 // Dispatch according to the BuiltinFunctionId if present. | 749 // Dispatch according to the BuiltinFunctionId if present. |
670 if (!r.HasBuiltinFunctionId()) return NoChange(); | 750 if (!r.HasBuiltinFunctionId()) return NoChange(); |
671 switch (r.GetBuiltinFunctionId()) { | 751 switch (r.GetBuiltinFunctionId()) { |
672 case kMathAbs: | 752 case kMathAbs: |
673 reduction = ReduceMathAbs(node); | 753 reduction = ReduceMathAbs(node); |
674 break; | 754 break; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
771 case kNumberParseInt: | 851 case kNumberParseInt: |
772 reduction = ReduceNumberParseInt(node); | 852 reduction = ReduceNumberParseInt(node); |
773 break; | 853 break; |
774 case kStringFromCharCode: | 854 case kStringFromCharCode: |
775 reduction = ReduceStringFromCharCode(node); | 855 reduction = ReduceStringFromCharCode(node); |
776 break; | 856 break; |
777 case kStringCharAt: | 857 case kStringCharAt: |
778 return ReduceStringCharAt(node); | 858 return ReduceStringCharAt(node); |
779 case kStringCharCodeAt: | 859 case kStringCharCodeAt: |
780 return ReduceStringCharCodeAt(node); | 860 return ReduceStringCharCodeAt(node); |
861 case kDataViewByteLength: | |
862 return ReduceArrayBufferViewAccessor( | |
863 node, JS_DATA_VIEW_TYPE, | |
864 AccessBuilder::ForJSArrayBufferViewByteLength()); | |
865 case kDataViewByteOffset: | |
866 return ReduceArrayBufferViewAccessor( | |
867 node, JS_DATA_VIEW_TYPE, | |
868 AccessBuilder::ForJSArrayBufferViewByteOffset()); | |
869 case kTypedArrayByteLength: | |
870 return ReduceArrayBufferViewAccessor( | |
871 node, JS_TYPED_ARRAY_TYPE, | |
872 AccessBuilder::ForJSArrayBufferViewByteLength()); | |
873 case kTypedArrayByteOffset: | |
874 return ReduceArrayBufferViewAccessor( | |
875 node, JS_TYPED_ARRAY_TYPE, | |
876 AccessBuilder::ForJSArrayBufferViewByteOffset()); | |
877 case kTypedArrayLength: | |
878 return ReduceArrayBufferViewAccessor( | |
879 node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength()); | |
781 default: | 880 default: |
782 break; | 881 break; |
783 } | 882 } |
784 | 883 |
785 // Replace builtin call assuming replacement nodes are pure values that don't | 884 // Replace builtin call assuming replacement nodes are pure values that don't |
786 // produce an effect. Replaces {node} with {reduction} and relaxes effects. | 885 // produce an effect. Replaces {node} with {reduction} and relaxes effects. |
787 if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement()); | 886 if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement()); |
788 | 887 |
789 return reduction; | 888 return reduction; |
790 } | 889 } |
(...skipping 22 matching lines...) Expand all Loading... | |
813 } | 912 } |
814 | 913 |
815 | 914 |
816 SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const { | 915 SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const { |
817 return jsgraph()->simplified(); | 916 return jsgraph()->simplified(); |
818 } | 917 } |
819 | 918 |
820 } // namespace compiler | 919 } // namespace compiler |
821 } // namespace internal | 920 } // namespace internal |
822 } // namespace v8 | 921 } // namespace v8 |
OLD | NEW |