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/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/code-stubs.h" | 6 #include "src/code-stubs.h" |
7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
8 #include "src/compiler/js-generic-lowering.h" | 8 #include "src/compiler/js-generic-lowering.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/machine-operator.h" | 10 #include "src/compiler/machine-operator.h" |
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 ReplaceWithRuntimeCall(node, Runtime::kForInDone); | 609 ReplaceWithRuntimeCall(node, Runtime::kForInDone); |
610 } | 610 } |
611 | 611 |
612 | 612 |
613 void JSGenericLowering::LowerJSForInNext(Node* node) { | 613 void JSGenericLowering::LowerJSForInNext(Node* node) { |
614 ReplaceWithRuntimeCall(node, Runtime::kForInNext); | 614 ReplaceWithRuntimeCall(node, Runtime::kForInNext); |
615 } | 615 } |
616 | 616 |
617 | 617 |
618 void JSGenericLowering::LowerJSForInPrepare(Node* node) { | 618 void JSGenericLowering::LowerJSForInPrepare(Node* node) { |
619 Node* object = NodeProperties::GetValueInput(node, 0); | 619 ReplaceWithRuntimeCall(node, Runtime::kForInPrepare); |
620 Node* context = NodeProperties::GetContextInput(node); | |
621 Node* effect = NodeProperties::GetEffectInput(node); | |
622 Node* control = NodeProperties::GetControlInput(node); | |
623 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); | |
624 | |
625 // Get the set of properties to enumerate. | |
626 Runtime::Function const* function = | |
627 Runtime::FunctionForId(Runtime::kGetPropertyNamesFast); | |
628 CallDescriptor const* descriptor = Linkage::GetRuntimeCallDescriptor( | |
629 zone(), function->function_id, 1, Operator::kNoProperties, | |
630 CallDescriptor::kNeedsFrameState); | |
631 Node* cache_type = effect = graph()->NewNode( | |
632 common()->Call(descriptor), | |
633 jsgraph()->CEntryStubConstant(function->result_size), object, | |
634 jsgraph()->ExternalConstant(function->function_id), | |
635 jsgraph()->Int32Constant(1), context, frame_state, effect, control); | |
636 control = graph()->NewNode(common()->IfSuccess(), cache_type); | |
637 | |
638 Node* object_map = effect = graph()->NewNode( | |
639 machine()->Load(MachineType::AnyTagged()), object, | |
640 jsgraph()->IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag), | |
641 effect, control); | |
642 Node* cache_type_map = effect = graph()->NewNode( | |
643 machine()->Load(MachineType::AnyTagged()), cache_type, | |
644 jsgraph()->IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag), | |
645 effect, control); | |
646 Node* meta_map = jsgraph()->HeapConstant(isolate()->factory()->meta_map()); | |
647 | |
648 // If we got a map from the GetPropertyNamesFast runtime call, we can do a | |
649 // fast modification check. Otherwise, we got a fixed array, and we have to | |
650 // perform a slow check on every iteration. | |
651 Node* check0 = | |
652 graph()->NewNode(machine()->WordEqual(), cache_type_map, meta_map); | |
653 Node* branch0 = | |
654 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | |
655 | |
656 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | |
657 Node* cache_array_true0; | |
658 Node* cache_length_true0; | |
659 Node* cache_type_true0; | |
660 Node* etrue0; | |
661 { | |
662 // Enum cache case. | |
663 Node* cache_type_enum_length = etrue0 = graph()->NewNode( | |
664 machine()->Load(MachineType::Uint32()), cache_type, | |
665 jsgraph()->IntPtrConstant(Map::kBitField3Offset - kHeapObjectTag), | |
666 effect, if_true0); | |
667 cache_type_enum_length = | |
668 graph()->NewNode(machine()->Word32And(), cache_type_enum_length, | |
669 jsgraph()->Uint32Constant(Map::EnumLengthBits::kMask)); | |
670 | |
671 Node* check1 = | |
672 graph()->NewNode(machine()->Word32Equal(), cache_type_enum_length, | |
673 jsgraph()->Int32Constant(0)); | |
674 Node* branch1 = | |
675 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0); | |
676 | |
677 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
678 Node* cache_array_true1; | |
679 Node* etrue1; | |
680 { | |
681 // No properties to enumerate. | |
682 cache_array_true1 = | |
683 jsgraph()->HeapConstant(isolate()->factory()->empty_fixed_array()); | |
684 etrue1 = etrue0; | |
685 } | |
686 | |
687 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
688 Node* cache_array_false1; | |
689 Node* efalse1; | |
690 { | |
691 // Load the enumeration cache from the instance descriptors of {object}. | |
692 Node* object_map_descriptors = efalse1 = graph()->NewNode( | |
693 machine()->Load(MachineType::AnyTagged()), object_map, | |
694 jsgraph()->IntPtrConstant(Map::kDescriptorsOffset - kHeapObjectTag), | |
695 etrue0, if_false1); | |
696 Node* object_map_enum_cache = efalse1 = graph()->NewNode( | |
697 machine()->Load(MachineType::AnyTagged()), object_map_descriptors, | |
698 jsgraph()->IntPtrConstant(DescriptorArray::kEnumCacheOffset - | |
699 kHeapObjectTag), | |
700 efalse1, if_false1); | |
701 cache_array_false1 = efalse1 = graph()->NewNode( | |
702 machine()->Load(MachineType::AnyTagged()), object_map_enum_cache, | |
703 jsgraph()->IntPtrConstant( | |
704 DescriptorArray::kEnumCacheBridgeCacheOffset - kHeapObjectTag), | |
705 efalse1, if_false1); | |
706 } | |
707 | |
708 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
709 etrue0 = | |
710 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); | |
711 cache_array_true0 = | |
712 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
713 cache_array_true1, cache_array_false1, if_true0); | |
714 | |
715 cache_length_true0 = graph()->NewNode( | |
716 machine()->WordShl(), | |
717 machine()->Is64() | |
718 ? graph()->NewNode(machine()->ChangeUint32ToUint64(), | |
719 cache_type_enum_length) | |
720 : cache_type_enum_length, | |
721 jsgraph()->Int32Constant(kSmiShiftSize + kSmiTagSize)); | |
722 cache_type_true0 = cache_type; | |
723 } | |
724 | |
725 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
726 Node* cache_array_false0; | |
727 Node* cache_length_false0; | |
728 Node* cache_type_false0; | |
729 Node* efalse0; | |
730 { | |
731 // FixedArray case. | |
732 cache_type_false0 = jsgraph()->OneConstant(); // Smi means slow check | |
733 cache_array_false0 = cache_type; | |
734 cache_length_false0 = efalse0 = graph()->NewNode( | |
735 machine()->Load(MachineType::AnyTagged()), cache_array_false0, | |
736 jsgraph()->IntPtrConstant(FixedArray::kLengthOffset - kHeapObjectTag), | |
737 effect, if_false0); | |
738 } | |
739 | |
740 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
741 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
742 Node* cache_array = | |
743 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
744 cache_array_true0, cache_array_false0, control); | |
745 Node* cache_length = | |
746 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
747 cache_length_true0, cache_length_false0, control); | |
748 cache_type = | |
749 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
750 cache_type_true0, cache_type_false0, control); | |
751 | |
752 for (auto edge : node->use_edges()) { | |
753 if (NodeProperties::IsEffectEdge(edge)) { | |
754 edge.UpdateTo(effect); | |
755 } else if (NodeProperties::IsControlEdge(edge)) { | |
756 Node* const use = edge.from(); | |
757 if (use->opcode() == IrOpcode::kIfSuccess) { | |
758 use->ReplaceUses(control); | |
759 use->Kill(); | |
760 } else if (use->opcode() == IrOpcode::kIfException) { | |
761 edge.UpdateTo(cache_type_true0); | |
762 } else { | |
763 UNREACHABLE(); | |
764 } | |
765 } else { | |
766 Node* const use = edge.from(); | |
767 DCHECK(NodeProperties::IsValueEdge(edge)); | |
768 DCHECK_EQ(IrOpcode::kProjection, use->opcode()); | |
769 switch (ProjectionIndexOf(use->op())) { | |
770 case 0: | |
771 use->ReplaceUses(cache_type); | |
772 break; | |
773 case 1: | |
774 use->ReplaceUses(cache_array); | |
775 break; | |
776 case 2: | |
777 use->ReplaceUses(cache_length); | |
778 break; | |
779 default: | |
780 UNREACHABLE(); | |
781 break; | |
782 } | |
783 use->Kill(); | |
784 } | |
785 } | |
786 } | 620 } |
787 | 621 |
788 | 622 |
789 void JSGenericLowering::LowerJSForInStep(Node* node) { | 623 void JSGenericLowering::LowerJSForInStep(Node* node) { |
790 ReplaceWithRuntimeCall(node, Runtime::kForInStep); | 624 ReplaceWithRuntimeCall(node, Runtime::kForInStep); |
791 } | 625 } |
792 | 626 |
793 | 627 |
794 void JSGenericLowering::LowerJSLoadMessage(Node* node) { | 628 void JSGenericLowering::LowerJSLoadMessage(Node* node) { |
795 ExternalReference message_address = | 629 ExternalReference message_address = |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 } | 707 } |
874 | 708 |
875 | 709 |
876 MachineOperatorBuilder* JSGenericLowering::machine() const { | 710 MachineOperatorBuilder* JSGenericLowering::machine() const { |
877 return jsgraph()->machine(); | 711 return jsgraph()->machine(); |
878 } | 712 } |
879 | 713 |
880 } // namespace compiler | 714 } // namespace compiler |
881 } // namespace internal | 715 } // namespace internal |
882 } // namespace v8 | 716 } // namespace v8 |
OLD | NEW |