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