OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 | 599 |
600 | 600 |
601 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 601 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
602 StrictModeFlag strict_mode) { | 602 StrictModeFlag strict_mode) { |
603 // ----------- S t a t e ------------- | 603 // ----------- S t a t e ------------- |
604 // -- rax : value | 604 // -- rax : value |
605 // -- rcx : key | 605 // -- rcx : key |
606 // -- rdx : receiver | 606 // -- rdx : receiver |
607 // -- rsp[0] : return address | 607 // -- rsp[0] : return address |
608 // ----------------------------------- | 608 // ----------------------------------- |
609 Label slow, slow_with_tagged_index, fast, array, extra; | 609 Label slow, slow_with_tagged_index, fast, array, extra, check_extra_double; |
| 610 Label fast_object_with_map_check, fast_object_without_map_check; |
| 611 Label fast_double_with_map_check, fast_double_without_map_check; |
610 | 612 |
611 // Check that the object isn't a smi. | 613 // Check that the object isn't a smi. |
612 __ JumpIfSmi(rdx, &slow_with_tagged_index); | 614 __ JumpIfSmi(rdx, &slow_with_tagged_index); |
613 // Get the map from the receiver. | 615 // Get the map from the receiver. |
614 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); | 616 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset)); |
615 // Check that the receiver does not require access checks. We need | 617 // Check that the receiver does not require access checks. We need |
616 // to do this because this generic stub does not perform map checks. | 618 // to do this because this generic stub does not perform map checks. |
617 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), | 619 __ testb(FieldOperand(r9, Map::kBitFieldOffset), |
618 Immediate(1 << Map::kIsAccessCheckNeeded)); | 620 Immediate(1 << Map::kIsAccessCheckNeeded)); |
619 __ j(not_zero, &slow_with_tagged_index); | 621 __ j(not_zero, &slow_with_tagged_index); |
620 // Check that the key is a smi. | 622 // Check that the key is a smi. |
621 __ JumpIfNotSmi(rcx, &slow_with_tagged_index); | 623 __ JumpIfNotSmi(rcx, &slow_with_tagged_index); |
622 __ SmiToInteger32(rcx, rcx); | 624 __ SmiToInteger32(rcx, rcx); |
623 | 625 |
624 __ CmpInstanceType(rbx, JS_ARRAY_TYPE); | 626 __ CmpInstanceType(r9, JS_ARRAY_TYPE); |
625 __ j(equal, &array); | 627 __ j(equal, &array); |
626 // Check that the object is some kind of JSObject. | 628 // Check that the object is some kind of JSObject. |
627 __ CmpInstanceType(rbx, FIRST_JS_RECEIVER_TYPE); | 629 __ CmpInstanceType(r9, FIRST_JS_RECEIVER_TYPE); |
628 __ j(below, &slow); | 630 __ j(below, &slow); |
629 __ CmpInstanceType(rbx, JS_PROXY_TYPE); | 631 __ CmpInstanceType(r9, JS_PROXY_TYPE); |
630 __ j(equal, &slow); | 632 __ j(equal, &slow); |
631 __ CmpInstanceType(rbx, JS_FUNCTION_PROXY_TYPE); | 633 __ CmpInstanceType(r9, JS_FUNCTION_PROXY_TYPE); |
632 __ j(equal, &slow); | 634 __ j(equal, &slow); |
633 | 635 |
634 // Object case: Check key against length in the elements array. | 636 // Object case: Check key against length in the elements array. |
635 // rax: value | 637 // rax: value |
636 // rdx: JSObject | 638 // rdx: JSObject |
637 // rcx: index | 639 // rcx: index |
638 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 640 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
639 // Check that the object is in fast mode and writable. | 641 // Check array bounds. |
640 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | |
641 Heap::kFixedArrayMapRootIndex); | |
642 __ j(not_equal, &slow); | |
643 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); | 642 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); |
644 // rax: value | 643 // rax: value |
645 // rbx: FixedArray | 644 // rbx: FixedArray |
646 // rcx: index | 645 // rcx: index |
647 __ j(above, &fast); | 646 __ j(above, &fast_object_with_map_check); |
648 | 647 |
649 // Slow case: call runtime. | 648 // Slow case: call runtime. |
650 __ bind(&slow); | 649 __ bind(&slow); |
651 __ Integer32ToSmi(rcx, rcx); | 650 __ Integer32ToSmi(rcx, rcx); |
652 __ bind(&slow_with_tagged_index); | 651 __ bind(&slow_with_tagged_index); |
653 GenerateRuntimeSetProperty(masm, strict_mode); | 652 GenerateRuntimeSetProperty(masm, strict_mode); |
654 // Never returns to here. | 653 // Never returns to here. |
655 | 654 |
656 // Extra capacity case: Check if there is extra capacity to | 655 // Extra capacity case: Check if there is extra capacity to |
657 // perform the store and update the length. Used for adding one | 656 // perform the store and update the length. Used for adding one |
658 // element to the array by writing to array[array.length]. | 657 // element to the array by writing to array[array.length]. |
659 __ bind(&extra); | 658 __ bind(&extra); |
660 // rax: value | 659 // rax: value |
661 // rdx: receiver (a JSArray) | 660 // rdx: receiver (a JSArray) |
662 // rbx: receiver's elements array (a FixedArray) | 661 // rbx: receiver's elements array (a FixedArray) |
663 // rcx: index | 662 // rcx: index |
664 // flags: smicompare (rdx.length(), rbx) | 663 // flags: smicompare (rdx.length(), rbx) |
665 __ j(not_equal, &slow); // do not leave holes in the array | 664 __ j(not_equal, &slow); // do not leave holes in the array |
666 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); | 665 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); |
667 __ j(below_equal, &slow); | 666 __ j(below_equal, &slow); |
668 // Increment index to get new length. | 667 // Increment index to get new length. |
| 668 __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); |
| 669 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex); |
| 670 __ j(not_equal, &check_extra_double); |
669 __ leal(rdi, Operand(rcx, 1)); | 671 __ leal(rdi, Operand(rcx, 1)); |
670 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi); | 672 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi); |
671 __ jmp(&fast); | 673 __ jmp(&fast_object_without_map_check); |
| 674 |
| 675 __ bind(&check_extra_double); |
| 676 // rdi: elements array's map |
| 677 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); |
| 678 __ j(not_equal, &slow); |
| 679 __ leal(rdi, Operand(rcx, 1)); |
| 680 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi); |
| 681 __ jmp(&fast_double_without_map_check); |
672 | 682 |
673 // Array case: Get the length and the elements array from the JS | 683 // Array case: Get the length and the elements array from the JS |
674 // array. Check that the array is in fast mode (and writable); if it | 684 // array. Check that the array is in fast mode (and writable); if it |
675 // is the length is always a smi. | 685 // is the length is always a smi. |
676 __ bind(&array); | 686 __ bind(&array); |
677 // rax: value | 687 // rax: value |
678 // rdx: receiver (a JSArray) | 688 // rdx: receiver (a JSArray) |
679 // rcx: index | 689 // rcx: index |
680 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 690 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
681 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | |
682 Heap::kFixedArrayMapRootIndex); | |
683 __ j(not_equal, &slow); | |
684 | 691 |
685 // Check the key against the length in the array, compute the | 692 // Check the key against the length in the array, compute the |
686 // address to store into and fall through to fast case. | 693 // address to store into and fall through to fast case. |
687 __ SmiCompareInteger32(FieldOperand(rdx, JSArray::kLengthOffset), rcx); | 694 __ SmiCompareInteger32(FieldOperand(rdx, JSArray::kLengthOffset), rcx); |
688 __ j(below_equal, &extra); | 695 __ j(below_equal, &extra); |
689 | 696 |
690 // Fast case: Do the store. | 697 // Fast case: Do the store. |
691 __ bind(&fast); | 698 __ bind(&fast_object_with_map_check); |
692 // rax: value | 699 // rax: value |
693 // rbx: receiver's elements array (a FixedArray) | 700 // rbx: receiver's elements array (a FixedArray) |
694 // rcx: index | 701 // rcx: index |
695 | 702 // rdx: receiver (a JSArray) |
| 703 __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); |
| 704 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex); |
| 705 __ j(not_equal, &fast_double_with_map_check); |
| 706 __ bind(&fast_object_without_map_check); |
| 707 // Smi stores don't require further checks. |
696 Label non_smi_value; | 708 Label non_smi_value; |
697 __ JumpIfNotSmi(rax, &non_smi_value); | 709 __ JumpIfNotSmi(rax, &non_smi_value); |
698 // It's irrelevant whether array is smi-only or not when writing a smi. | 710 // It's irrelevant whether array is smi-only or not when writing a smi. |
699 __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), | 711 __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), |
700 rax); | 712 rax); |
701 __ ret(0); | 713 __ ret(0); |
702 | 714 |
703 __ bind(&non_smi_value); | 715 __ bind(&non_smi_value); |
704 if (FLAG_smi_only_arrays) { | 716 if (FLAG_smi_only_arrays) { |
705 // Writing a non-smi, check whether array allows non-smi elements. | 717 // Writing a non-smi, check whether array allows non-smi elements. |
706 __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset)); | 718 // r9: receiver's map |
707 __ CheckFastObjectElements(rdi, &slow, Label::kNear); | 719 __ CheckFastObjectElements(r9, &slow, Label::kNear); |
708 } | 720 } |
709 __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), | |
710 rax); | |
711 __ movq(rdx, rax); | |
712 __ lea(rcx, | 721 __ lea(rcx, |
713 FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize)); | 722 FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize)); |
| 723 __ movq(Operand(rcx, 0), rax); |
| 724 __ movq(rdx, rax); |
714 __ RecordWrite( | 725 __ RecordWrite( |
715 rbx, rcx, rdx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 726 rbx, rcx, rdx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
716 __ ret(0); | 727 __ ret(0); |
| 728 |
| 729 __ bind(&fast_double_with_map_check); |
| 730 // Check for fast double array case. If this fails, call through to the |
| 731 // runtime. |
| 732 // rdi: elements array's map |
| 733 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); |
| 734 __ j(not_equal, &slow); |
| 735 __ bind(&fast_double_without_map_check); |
| 736 // If the value is a number, store it as a double in the FastDoubleElements |
| 737 // array. |
| 738 __ StoreNumberToDoubleElements(rax, rbx, rcx, xmm0, &slow); |
| 739 __ ret(0); |
717 } | 740 } |
718 | 741 |
719 | 742 |
720 // The generated code does not accept smi keys. | 743 // The generated code does not accept smi keys. |
721 // The generated code falls through if both probes miss. | 744 // The generated code falls through if both probes miss. |
722 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, | 745 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, |
723 int argc, | 746 int argc, |
724 Code::Kind kind, | 747 Code::Kind kind, |
725 Code::ExtraICState extra_ic_state) { | 748 Code::ExtraICState extra_ic_state) { |
726 // ----------- S t a t e ------------- | 749 // ----------- S t a t e ------------- |
(...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1680 Condition cc = *jmp_address == Assembler::kJncShortOpcode | 1703 Condition cc = *jmp_address == Assembler::kJncShortOpcode |
1681 ? not_zero | 1704 ? not_zero |
1682 : zero; | 1705 : zero; |
1683 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1706 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
1684 } | 1707 } |
1685 | 1708 |
1686 | 1709 |
1687 } } // namespace v8::internal | 1710 } } // namespace v8::internal |
1688 | 1711 |
1689 #endif // V8_TARGET_ARCH_X64 | 1712 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |