| 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 |