OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 3524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3535 // value is on the stack already. | 3535 // value is on the stack already. |
3536 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, | 3536 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, |
3537 Register key, Register vector, | 3537 Register key, Register vector, |
3538 Register slot, Register feedback, | 3538 Register slot, Register feedback, |
3539 bool is_polymorphic, Label* miss) { | 3539 bool is_polymorphic, Label* miss) { |
3540 // feedback initially contains the feedback array | 3540 // feedback initially contains the feedback array |
3541 Label next, next_loop, prepare_next; | 3541 Label next, next_loop, prepare_next; |
3542 Label load_smi_map, compare_map; | 3542 Label load_smi_map, compare_map; |
3543 Label start_polymorphic; | 3543 Label start_polymorphic; |
3544 Label pop_and_miss; | 3544 Label pop_and_miss; |
3545 ExternalReference virtual_register = | |
3546 ExternalReference::virtual_handler_register(masm->isolate()); | |
3547 | 3545 |
3548 __ push(receiver); | 3546 __ push(receiver); |
3549 __ push(vector); | 3547 // Value, vector and slot are passed on the stack, so no need to save/restore |
| 3548 // them. |
3550 | 3549 |
3551 Register receiver_map = receiver; | 3550 Register receiver_map = receiver; |
3552 Register cached_map = vector; | 3551 Register cached_map = vector; |
3553 | 3552 |
3554 // Receiver might not be a heap object. | 3553 // Receiver might not be a heap object. |
3555 __ JumpIfSmi(receiver, &load_smi_map); | 3554 __ JumpIfSmi(receiver, &load_smi_map); |
3556 __ mov(receiver_map, FieldOperand(receiver, 0)); | 3555 __ mov(receiver_map, FieldOperand(receiver, 0)); |
3557 __ bind(&compare_map); | 3556 __ bind(&compare_map); |
3558 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); | 3557 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); |
3559 | 3558 |
3560 // A named keyed store might have a 2 element array, all other cases can count | 3559 // A named keyed store might have a 2 element array, all other cases can count |
3561 // on an array with at least 2 {map, handler} pairs, so they can go right | 3560 // on an array with at least 2 {map, handler} pairs, so they can go right |
3562 // into polymorphic array handling. | 3561 // into polymorphic array handling. |
3563 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 3562 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
3564 __ j(not_equal, &start_polymorphic); | 3563 __ j(not_equal, &start_polymorphic); |
3565 | 3564 |
3566 // found, now call handler. | 3565 // found, now call handler. |
3567 Register handler = feedback; | 3566 Register handler = feedback; |
3568 DCHECK(handler.is(StoreWithVectorDescriptor::ValueRegister())); | 3567 DCHECK(handler.is(StoreWithVectorDescriptor::ValueRegister())); |
3569 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); | 3568 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); |
3570 __ pop(vector); | |
3571 __ pop(receiver); | 3569 __ pop(receiver); |
3572 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | 3570 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
3573 __ mov(Operand::StaticVariable(virtual_register), handler); | 3571 __ jmp(handler); |
3574 __ pop(handler); // Pop "value". | |
3575 __ jmp(Operand::StaticVariable(virtual_register)); | |
3576 | 3572 |
3577 // Polymorphic, we have to loop from 2 to N | 3573 // Polymorphic, we have to loop from 2 to N |
3578 __ bind(&start_polymorphic); | 3574 __ bind(&start_polymorphic); |
3579 __ push(key); | 3575 __ push(key); |
3580 Register counter = key; | 3576 Register counter = key; |
3581 __ mov(counter, Immediate(Smi::FromInt(2))); | 3577 __ mov(counter, Immediate(Smi::FromInt(2))); |
3582 | 3578 |
3583 if (!is_polymorphic) { | 3579 if (!is_polymorphic) { |
3584 // If is_polymorphic is false, we may only have a two element array. | 3580 // If is_polymorphic is false, we may only have a two element array. |
3585 // Check against length now in that case. | 3581 // Check against length now in that case. |
3586 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | 3582 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
3587 __ j(greater_equal, &pop_and_miss); | 3583 __ j(greater_equal, &pop_and_miss); |
3588 } | 3584 } |
3589 | 3585 |
3590 __ bind(&next_loop); | 3586 __ bind(&next_loop); |
3591 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 3587 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
3592 FixedArray::kHeaderSize)); | 3588 FixedArray::kHeaderSize)); |
3593 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 3589 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
3594 __ j(not_equal, &prepare_next); | 3590 __ j(not_equal, &prepare_next); |
3595 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, | 3591 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, |
3596 FixedArray::kHeaderSize + kPointerSize)); | 3592 FixedArray::kHeaderSize + kPointerSize)); |
3597 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | 3593 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
3598 __ pop(key); | 3594 __ pop(key); |
3599 __ pop(vector); | |
3600 __ pop(receiver); | 3595 __ pop(receiver); |
3601 __ mov(Operand::StaticVariable(virtual_register), handler); | 3596 __ jmp(handler); |
3602 __ pop(handler); // Pop "value". | |
3603 __ jmp(Operand::StaticVariable(virtual_register)); | |
3604 | 3597 |
3605 __ bind(&prepare_next); | 3598 __ bind(&prepare_next); |
3606 __ add(counter, Immediate(Smi::FromInt(2))); | 3599 __ add(counter, Immediate(Smi::FromInt(2))); |
3607 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | 3600 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
3608 __ j(less, &next_loop); | 3601 __ j(less, &next_loop); |
3609 | 3602 |
3610 // We exhausted our array of map handler pairs. | 3603 // We exhausted our array of map handler pairs. |
3611 __ bind(&pop_and_miss); | 3604 __ bind(&pop_and_miss); |
3612 __ pop(key); | 3605 __ pop(key); |
3613 __ pop(vector); | |
3614 __ pop(receiver); | 3606 __ pop(receiver); |
3615 __ jmp(miss); | 3607 __ jmp(miss); |
3616 | 3608 |
3617 __ bind(&load_smi_map); | 3609 __ bind(&load_smi_map); |
3618 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | 3610 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
3619 __ jmp(&compare_map); | 3611 __ jmp(&compare_map); |
3620 } | 3612 } |
3621 | 3613 |
3622 | 3614 |
3623 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, | 3615 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, |
3624 Register key, Register vector, | 3616 Register key, Register vector, |
3625 Register slot, Register weak_cell, | 3617 Register slot, Register weak_cell, |
3626 Label* miss) { | 3618 Label* miss) { |
3627 // The store ic value is on the stack. | 3619 // The store ic value is on the stack. |
3628 DCHECK(weak_cell.is(StoreWithVectorDescriptor::ValueRegister())); | 3620 DCHECK(weak_cell.is(StoreWithVectorDescriptor::ValueRegister())); |
3629 ExternalReference virtual_register = | |
3630 ExternalReference::virtual_handler_register(masm->isolate()); | |
3631 | 3621 |
3632 // feedback initially contains the feedback array | 3622 // feedback initially contains the feedback array |
3633 Label compare_smi_map; | 3623 Label compare_smi_map; |
3634 | 3624 |
3635 // Move the weak map into the weak_cell register. | 3625 // Move the weak map into the weak_cell register. |
3636 Register ic_map = weak_cell; | 3626 Register ic_map = weak_cell; |
3637 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); | 3627 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); |
3638 | 3628 |
3639 // Receiver might not be a heap object. | 3629 // Receiver might not be a heap object. |
3640 __ JumpIfSmi(receiver, &compare_smi_map); | 3630 __ JumpIfSmi(receiver, &compare_smi_map); |
3641 __ cmp(ic_map, FieldOperand(receiver, 0)); | 3631 __ cmp(ic_map, FieldOperand(receiver, 0)); |
3642 __ j(not_equal, miss); | 3632 __ j(not_equal, miss); |
3643 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 3633 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
3644 FixedArray::kHeaderSize + kPointerSize)); | 3634 FixedArray::kHeaderSize + kPointerSize)); |
3645 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 3635 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
3646 // Put the store ic value back in it's register. | |
3647 __ mov(Operand::StaticVariable(virtual_register), weak_cell); | |
3648 __ pop(weak_cell); // Pop "value". | |
3649 // jump to the handler. | 3636 // jump to the handler. |
3650 __ jmp(Operand::StaticVariable(virtual_register)); | 3637 __ jmp(weak_cell); |
3651 | 3638 |
3652 // In microbenchmarks, it made sense to unroll this code so that the call to | 3639 // In microbenchmarks, it made sense to unroll this code so that the call to |
3653 // the handler is duplicated for a HeapObject receiver and a Smi receiver. | 3640 // the handler is duplicated for a HeapObject receiver and a Smi receiver. |
3654 __ bind(&compare_smi_map); | 3641 __ bind(&compare_smi_map); |
3655 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); | 3642 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); |
3656 __ j(not_equal, miss); | 3643 __ j(not_equal, miss); |
3657 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 3644 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
3658 FixedArray::kHeaderSize + kPointerSize)); | 3645 FixedArray::kHeaderSize + kPointerSize)); |
3659 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 3646 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
3660 __ mov(Operand::StaticVariable(virtual_register), weak_cell); | |
3661 __ pop(weak_cell); // Pop "value". | |
3662 // jump to the handler. | 3647 // jump to the handler. |
3663 __ jmp(Operand::StaticVariable(virtual_register)); | 3648 __ jmp(weak_cell); |
3664 } | 3649 } |
3665 | 3650 |
3666 void StoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 3651 void StoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
3667 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); // edx | 3652 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); // edx |
3668 Register key = StoreWithVectorDescriptor::NameRegister(); // ecx | 3653 Register key = StoreWithVectorDescriptor::NameRegister(); // ecx |
3669 Register value = StoreWithVectorDescriptor::ValueRegister(); // eax | 3654 Register value = StoreWithVectorDescriptor::ValueRegister(); // eax |
3670 Register vector = StoreWithVectorDescriptor::VectorRegister(); // ebx | 3655 Register vector = StoreWithVectorDescriptor::VectorRegister(); // ebx |
3671 Register slot = StoreWithVectorDescriptor::SlotRegister(); // edi | 3656 Register slot = StoreWithVectorDescriptor::SlotRegister(); // edi |
3672 Label miss; | 3657 Label miss; |
3673 | 3658 |
3674 if (StoreWithVectorDescriptor::kPassLastArgsOnStack) { | 3659 if (StoreWithVectorDescriptor::kPassLastArgsOnStack) { |
3675 // Current stack layout: | 3660 // Current stack layout: |
3676 // - esp[8] -- value | 3661 // - esp[8] -- value |
3677 // - esp[4] -- slot | 3662 // - esp[4] -- slot |
3678 // - esp[0] -- return address | 3663 // - esp[0] -- return address |
3679 STATIC_ASSERT(StoreDescriptor::kStackArgumentsCount == 2); | 3664 STATIC_ASSERT(StoreDescriptor::kStackArgumentsCount == 2); |
3680 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); | 3665 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); |
3681 if (in_frame) { | 3666 if (in_frame) { |
3682 __ RecordComment("[ StoreDescriptor -> StoreWithVectorDescriptor"); | 3667 __ RecordComment("[ StoreDescriptor -> StoreWithVectorDescriptor"); |
3683 // If the vector is not on the stack, then insert the vector beneath | 3668 // If the vector is not on the stack, then insert the vector beneath |
3684 // return address in order to prepare for calling handler with | 3669 // return address in order to prepare for calling handler with |
3685 // StoreWithVector calling convention. | 3670 // StoreWithVector calling convention. |
3686 __ push(Operand(esp, 0)); | 3671 __ push(Operand(esp, 0)); |
3687 __ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister()); | 3672 __ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister()); |
3688 __ RecordComment("]"); | 3673 __ RecordComment("]"); |
3689 } else { | 3674 } else { |
3690 __ mov(vector, Operand(esp, 1 * kPointerSize)); | 3675 __ mov(vector, Operand(esp, 1 * kPointerSize)); |
3691 } | 3676 } |
3692 __ mov(slot, Operand(esp, 2 * kPointerSize)); | 3677 __ mov(slot, Operand(esp, 2 * kPointerSize)); |
3693 __ mov(value, Operand(esp, 3 * kPointerSize)); | |
3694 } | 3678 } |
3695 | 3679 |
3696 __ push(value); | |
3697 | |
3698 Register scratch = value; | 3680 Register scratch = value; |
3699 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, | 3681 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
3700 FixedArray::kHeaderSize)); | 3682 FixedArray::kHeaderSize)); |
3701 | 3683 |
3702 // Is it a weak cell? | 3684 // Is it a weak cell? |
3703 Label try_array; | 3685 Label try_array; |
3704 Label not_array, smi_key, key_okay; | 3686 Label not_array, smi_key, key_okay; |
3705 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); | 3687 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); |
3706 __ j(not_equal, &try_array); | 3688 __ j(not_equal, &try_array); |
3707 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); | 3689 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
3708 | 3690 |
3709 // Is it a fixed array? | 3691 // Is it a fixed array? |
3710 __ bind(&try_array); | 3692 __ bind(&try_array); |
3711 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); | 3693 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); |
3712 __ j(not_equal, ¬_array); | 3694 __ j(not_equal, ¬_array); |
3713 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, true, | 3695 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, true, |
3714 &miss); | 3696 &miss); |
3715 | 3697 |
3716 __ bind(¬_array); | 3698 __ bind(¬_array); |
3717 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); | 3699 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); |
3718 __ j(not_equal, &miss); | 3700 __ j(not_equal, &miss); |
3719 | 3701 |
3720 __ pop(value); | |
3721 __ push(slot); | |
3722 __ push(vector); | |
3723 masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, slot, | 3702 masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, slot, |
3724 no_reg); | 3703 no_reg); |
3725 __ pop(vector); | |
3726 __ pop(slot); | |
3727 Label no_pop_miss; | |
3728 __ jmp(&no_pop_miss); | |
3729 | |
3730 __ bind(&miss); | 3704 __ bind(&miss); |
3731 __ pop(value); | |
3732 __ bind(&no_pop_miss); | |
3733 StoreIC::GenerateMiss(masm); | 3705 StoreIC::GenerateMiss(masm); |
3734 } | 3706 } |
3735 | 3707 |
3736 void KeyedStoreICStub::Generate(MacroAssembler* masm) { | 3708 void KeyedStoreICStub::Generate(MacroAssembler* masm) { |
3737 GenerateImpl(masm, false); | 3709 GenerateImpl(masm, false); |
3738 } | 3710 } |
3739 | 3711 |
3740 void KeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { | 3712 void KeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { |
3741 GenerateImpl(masm, true); | 3713 GenerateImpl(masm, true); |
3742 } | 3714 } |
3743 | 3715 |
3744 | 3716 |
3745 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, | 3717 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, |
3746 Register receiver, Register key, | 3718 Register receiver, Register key, |
3747 Register vector, Register slot, | 3719 Register vector, Register slot, |
3748 Register feedback, Label* miss) { | 3720 Register feedback, Label* miss) { |
3749 // feedback initially contains the feedback array | 3721 // feedback initially contains the feedback array |
3750 Label next, next_loop, prepare_next; | 3722 Label next, next_loop, prepare_next; |
3751 Label load_smi_map, compare_map; | 3723 Label load_smi_map, compare_map; |
3752 Label transition_call; | 3724 Label transition_call; |
3753 Label pop_and_miss; | 3725 Label pop_and_miss; |
3754 ExternalReference virtual_register = | |
3755 ExternalReference::virtual_handler_register(masm->isolate()); | |
3756 ExternalReference virtual_slot = | |
3757 ExternalReference::virtual_slot_register(masm->isolate()); | |
3758 | 3726 |
3759 __ push(receiver); | 3727 __ push(receiver); |
3760 __ push(vector); | 3728 // Value, vector and slot are passed on the stack, so no need to save/restore |
| 3729 // them. |
3761 | 3730 |
3762 Register receiver_map = receiver; | 3731 Register receiver_map = receiver; |
3763 Register cached_map = vector; | 3732 Register cached_map = vector; |
3764 Register value = StoreDescriptor::ValueRegister(); | |
3765 | 3733 |
3766 // Receiver might not be a heap object. | 3734 // Receiver might not be a heap object. |
3767 __ JumpIfSmi(receiver, &load_smi_map); | 3735 __ JumpIfSmi(receiver, &load_smi_map); |
3768 __ mov(receiver_map, FieldOperand(receiver, 0)); | 3736 __ mov(receiver_map, FieldOperand(receiver, 0)); |
3769 __ bind(&compare_map); | 3737 __ bind(&compare_map); |
3770 | 3738 |
3771 // Polymorphic, we have to loop from 0 to N - 1 | 3739 // Polymorphic, we have to loop from 0 to N - 1 |
3772 __ push(key); | 3740 __ push(key); |
3773 // Current stack layout: | 3741 // Current stack layout: |
3774 // - esp[0] -- key | 3742 // - esp[0] -- key |
| 3743 // - esp[4] -- receiver |
| 3744 // - esp[8] -- return address |
| 3745 // - esp[12] -- vector |
| 3746 // - esp[16] -- slot |
| 3747 // - esp[20] -- value |
| 3748 // |
| 3749 // Required stack layout for handler call (see StoreWithVectorDescriptor): |
| 3750 // - esp[0] -- return address |
3775 // - esp[4] -- vector | 3751 // - esp[4] -- vector |
3776 // - esp[8] -- receiver | 3752 // - esp[8] -- slot |
3777 // - esp[12] -- value | 3753 // - esp[12] -- value |
3778 // - esp[16] -- return address | 3754 // - receiver, key, handler in registers. |
3779 // | |
3780 // Required stack layout for handler call: | |
3781 // - esp[0] -- return address | |
3782 // - receiver, key, value, vector, slot in registers. | |
3783 // - handler in virtual register. | |
3784 Register counter = key; | 3755 Register counter = key; |
3785 __ mov(counter, Immediate(Smi::FromInt(0))); | 3756 __ mov(counter, Immediate(Smi::FromInt(0))); |
3786 __ bind(&next_loop); | 3757 __ bind(&next_loop); |
3787 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 3758 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
3788 FixedArray::kHeaderSize)); | 3759 FixedArray::kHeaderSize)); |
3789 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 3760 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
3790 __ j(not_equal, &prepare_next); | 3761 __ j(not_equal, &prepare_next); |
3791 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 3762 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
3792 FixedArray::kHeaderSize + kPointerSize)); | 3763 FixedArray::kHeaderSize + kPointerSize)); |
3793 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); | 3764 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); |
3794 __ j(not_equal, &transition_call); | 3765 __ j(not_equal, &transition_call); |
3795 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, | 3766 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
3796 FixedArray::kHeaderSize + 2 * kPointerSize)); | 3767 FixedArray::kHeaderSize + 2 * kPointerSize)); |
3797 __ pop(key); | 3768 __ pop(key); |
3798 __ pop(vector); | |
3799 __ pop(receiver); | 3769 __ pop(receiver); |
3800 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); | 3770 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
3801 __ mov(Operand::StaticVariable(virtual_register), feedback); | 3771 __ jmp(feedback); |
3802 __ pop(value); | |
3803 | |
3804 // Call store handler using StoreWithVectorDescriptor calling convention. | |
3805 __ jmp(Operand::StaticVariable(virtual_register)); | |
3806 | 3772 |
3807 __ bind(&transition_call); | 3773 __ bind(&transition_call); |
3808 // Current stack layout: | 3774 // Current stack layout: |
3809 // - esp[0] -- key | 3775 // - esp[0] -- key |
| 3776 // - esp[4] -- receiver |
| 3777 // - esp[8] -- return address |
| 3778 // - esp[12] -- vector |
| 3779 // - esp[16] -- slot |
| 3780 // - esp[20] -- value |
| 3781 // |
| 3782 // Required stack layout for handler call (see StoreTransitionDescriptor): |
| 3783 // - esp[0] -- return address |
3810 // - esp[4] -- vector | 3784 // - esp[4] -- vector |
3811 // - esp[8] -- receiver | 3785 // - esp[8] -- slot |
3812 // - esp[12] -- value | 3786 // - esp[12] -- value |
3813 // - esp[16] -- return address | 3787 // - receiver, key, map, handler in registers. |
3814 // | |
3815 // Required stack layout for handler call: | |
3816 // - esp[0] -- return address | |
3817 // - receiver, key, value, map, vector in registers. | |
3818 // - handler and slot in virtual registers. | |
3819 __ mov(Operand::StaticVariable(virtual_slot), slot); | |
3820 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, | 3788 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
3821 FixedArray::kHeaderSize + 2 * kPointerSize)); | 3789 FixedArray::kHeaderSize + 2 * kPointerSize)); |
3822 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); | 3790 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
3823 __ mov(Operand::StaticVariable(virtual_register), feedback); | |
3824 | 3791 |
3825 __ mov(cached_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 3792 __ mov(cached_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
3826 // The weak cell may have been cleared. | 3793 // The weak cell may have been cleared. |
3827 __ JumpIfSmi(cached_map, &pop_and_miss); | 3794 __ JumpIfSmi(cached_map, &pop_and_miss); |
3828 DCHECK(!cached_map.is(StoreTransitionDescriptor::MapRegister())); | 3795 DCHECK(!cached_map.is(StoreTransitionDescriptor::MapRegister())); |
3829 __ mov(StoreTransitionDescriptor::MapRegister(), cached_map); | 3796 __ mov(StoreTransitionDescriptor::MapRegister(), cached_map); |
3830 | 3797 |
3831 // Call store transition handler using StoreTransitionDescriptor calling | 3798 // Call store transition handler using StoreTransitionDescriptor calling |
3832 // convention. | 3799 // convention. |
3833 __ pop(key); | 3800 __ pop(key); |
3834 __ pop(vector); | |
3835 __ pop(receiver); | 3801 __ pop(receiver); |
3836 __ pop(value); | |
3837 // Ensure that the transition handler we are going to call has the same | 3802 // Ensure that the transition handler we are going to call has the same |
3838 // number of stack arguments which means that we don't have to adapt them | 3803 // number of stack arguments which means that we don't have to adapt them |
3839 // before the call. | 3804 // before the call. |
3840 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); | 3805 STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); |
3841 STATIC_ASSERT(StoreTransitionDescriptor::kStackArgumentsCount == 3); | 3806 STATIC_ASSERT(StoreTransitionDescriptor::kStackArgumentsCount == 3); |
3842 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - | 3807 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - |
3843 StoreWithVectorDescriptor::kValue == | 3808 StoreWithVectorDescriptor::kValue == |
3844 StoreTransitionDescriptor::kParameterCount - | 3809 StoreTransitionDescriptor::kParameterCount - |
3845 StoreTransitionDescriptor::kValue); | 3810 StoreTransitionDescriptor::kValue); |
3846 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - | 3811 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - |
3847 StoreWithVectorDescriptor::kSlot == | 3812 StoreWithVectorDescriptor::kSlot == |
3848 StoreTransitionDescriptor::kParameterCount - | 3813 StoreTransitionDescriptor::kParameterCount - |
3849 StoreTransitionDescriptor::kSlot); | 3814 StoreTransitionDescriptor::kSlot); |
3850 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - | 3815 STATIC_ASSERT(StoreWithVectorDescriptor::kParameterCount - |
3851 StoreWithVectorDescriptor::kVector == | 3816 StoreWithVectorDescriptor::kVector == |
3852 StoreTransitionDescriptor::kParameterCount - | 3817 StoreTransitionDescriptor::kParameterCount - |
3853 StoreTransitionDescriptor::kVector); | 3818 StoreTransitionDescriptor::kVector); |
3854 __ jmp(Operand::StaticVariable(virtual_register)); | 3819 __ jmp(feedback); |
3855 | 3820 |
3856 __ bind(&prepare_next); | 3821 __ bind(&prepare_next); |
3857 __ add(counter, Immediate(Smi::FromInt(3))); | 3822 __ add(counter, Immediate(Smi::FromInt(3))); |
3858 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | 3823 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
3859 __ j(less, &next_loop); | 3824 __ j(less, &next_loop); |
3860 | 3825 |
3861 // We exhausted our array of map handler pairs. | 3826 // We exhausted our array of map handler pairs. |
3862 __ bind(&pop_and_miss); | 3827 __ bind(&pop_and_miss); |
3863 __ pop(key); | 3828 __ pop(key); |
3864 __ pop(vector); | |
3865 __ pop(receiver); | 3829 __ pop(receiver); |
3866 __ jmp(miss); | 3830 __ jmp(miss); |
3867 | 3831 |
3868 __ bind(&load_smi_map); | 3832 __ bind(&load_smi_map); |
3869 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | 3833 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
3870 __ jmp(&compare_map); | 3834 __ jmp(&compare_map); |
3871 } | 3835 } |
3872 | 3836 |
3873 void KeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 3837 void KeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
3874 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); // edx | 3838 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); // edx |
(...skipping 15 matching lines...) Expand all Loading... |
3890 // If the vector is not on the stack, then insert the vector beneath | 3854 // If the vector is not on the stack, then insert the vector beneath |
3891 // return address in order to prepare for calling handler with | 3855 // return address in order to prepare for calling handler with |
3892 // StoreWithVector calling convention. | 3856 // StoreWithVector calling convention. |
3893 __ push(Operand(esp, 0)); | 3857 __ push(Operand(esp, 0)); |
3894 __ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister()); | 3858 __ mov(Operand(esp, 4), StoreWithVectorDescriptor::VectorRegister()); |
3895 __ RecordComment("]"); | 3859 __ RecordComment("]"); |
3896 } else { | 3860 } else { |
3897 __ mov(vector, Operand(esp, 1 * kPointerSize)); | 3861 __ mov(vector, Operand(esp, 1 * kPointerSize)); |
3898 } | 3862 } |
3899 __ mov(slot, Operand(esp, 2 * kPointerSize)); | 3863 __ mov(slot, Operand(esp, 2 * kPointerSize)); |
3900 __ mov(value, Operand(esp, 3 * kPointerSize)); | |
3901 } | 3864 } |
3902 | 3865 |
3903 __ push(value); | |
3904 | |
3905 Register scratch = value; | 3866 Register scratch = value; |
3906 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, | 3867 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
3907 FixedArray::kHeaderSize)); | 3868 FixedArray::kHeaderSize)); |
3908 | 3869 |
3909 // Is it a weak cell? | 3870 // Is it a weak cell? |
3910 Label try_array; | 3871 Label try_array; |
3911 Label not_array, smi_key, key_okay; | 3872 Label not_array, smi_key, key_okay; |
3912 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); | 3873 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); |
3913 __ j(not_equal, &try_array); | 3874 __ j(not_equal, &try_array); |
3914 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); | 3875 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
3915 | 3876 |
3916 // Is it a fixed array? | 3877 // Is it a fixed array? |
3917 __ bind(&try_array); | 3878 __ bind(&try_array); |
3918 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); | 3879 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); |
3919 __ j(not_equal, ¬_array); | 3880 __ j(not_equal, ¬_array); |
3920 HandlePolymorphicKeyedStoreCase(masm, receiver, key, vector, slot, scratch, | 3881 HandlePolymorphicKeyedStoreCase(masm, receiver, key, vector, slot, scratch, |
3921 &miss); | 3882 &miss); |
3922 | 3883 |
3923 __ bind(¬_array); | 3884 __ bind(¬_array); |
3924 Label try_poly_name; | 3885 Label try_poly_name; |
3925 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); | 3886 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); |
3926 __ j(not_equal, &try_poly_name); | 3887 __ j(not_equal, &try_poly_name); |
3927 | 3888 |
3928 __ pop(value); | |
3929 | |
3930 Handle<Code> megamorphic_stub = | 3889 Handle<Code> megamorphic_stub = |
3931 KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); | 3890 KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); |
3932 __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET); | 3891 __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET); |
3933 | 3892 |
3934 __ bind(&try_poly_name); | 3893 __ bind(&try_poly_name); |
3935 // We might have a name in feedback, and a fixed array in the next slot. | 3894 // We might have a name in feedback, and a fixed array in the next slot. |
3936 __ cmp(key, scratch); | 3895 __ cmp(key, scratch); |
3937 __ j(not_equal, &miss); | 3896 __ j(not_equal, &miss); |
3938 // If the name comparison succeeded, we know we have a fixed array with | 3897 // If the name comparison succeeded, we know we have a fixed array with |
3939 // at least one map/handler pair. | 3898 // at least one map/handler pair. |
3940 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, | 3899 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
3941 FixedArray::kHeaderSize + kPointerSize)); | 3900 FixedArray::kHeaderSize + kPointerSize)); |
3942 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, false, | 3901 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, false, |
3943 &miss); | 3902 &miss); |
3944 | 3903 |
3945 __ bind(&miss); | 3904 __ bind(&miss); |
3946 __ pop(value); | |
3947 KeyedStoreIC::GenerateMiss(masm); | 3905 KeyedStoreIC::GenerateMiss(masm); |
3948 } | 3906 } |
3949 | 3907 |
3950 | 3908 |
3951 void CallICTrampolineStub::Generate(MacroAssembler* masm) { | 3909 void CallICTrampolineStub::Generate(MacroAssembler* masm) { |
3952 __ EmitLoadTypeFeedbackVector(ebx); | 3910 __ EmitLoadTypeFeedbackVector(ebx); |
3953 CallICStub stub(isolate(), state()); | 3911 CallICStub stub(isolate(), state()); |
3954 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3912 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3955 } | 3913 } |
3956 | 3914 |
(...skipping 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5512 kStackUnwindSpace, nullptr, return_value_operand, | 5470 kStackUnwindSpace, nullptr, return_value_operand, |
5513 NULL); | 5471 NULL); |
5514 } | 5472 } |
5515 | 5473 |
5516 #undef __ | 5474 #undef __ |
5517 | 5475 |
5518 } // namespace internal | 5476 } // namespace internal |
5519 } // namespace v8 | 5477 } // namespace v8 |
5520 | 5478 |
5521 #endif // V8_TARGET_ARCH_IA32 | 5479 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |