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/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 4549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4560 | 4560 |
4561 // value is on the stack already. | 4561 // value is on the stack already. |
4562 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, | 4562 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, |
4563 Register key, Register vector, | 4563 Register key, Register vector, |
4564 Register slot, Register feedback, | 4564 Register slot, Register feedback, |
4565 Label* miss) { | 4565 Label* miss) { |
4566 // feedback initially contains the feedback array | 4566 // feedback initially contains the feedback array |
4567 Label next, next_loop, prepare_next; | 4567 Label next, next_loop, prepare_next; |
4568 Label load_smi_map, compare_map; | 4568 Label load_smi_map, compare_map; |
4569 Label start_polymorphic; | 4569 Label start_polymorphic; |
4570 ExternalReference virtual_register = | |
4571 ExternalReference::vector_store_virtual_register(masm->isolate()); | |
4572 | 4570 |
4573 __ push(receiver); | 4571 __ push(receiver); |
4574 __ push(vector); | 4572 __ push(vector); |
4575 | 4573 |
4576 Register receiver_map = receiver; | 4574 Register receiver_map = receiver; |
4577 Register cached_map = vector; | 4575 Register cached_map = vector; |
4578 | 4576 |
4579 // Receiver might not be a heap object. | 4577 // Receiver might not be a heap object. |
4580 __ JumpIfSmi(receiver, &load_smi_map); | 4578 __ JumpIfSmi(receiver, &load_smi_map); |
4581 __ mov(receiver_map, FieldOperand(receiver, 0)); | 4579 __ mov(receiver_map, FieldOperand(receiver, 0)); |
4582 __ bind(&compare_map); | 4580 __ bind(&compare_map); |
4583 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); | 4581 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); |
4584 | 4582 |
4585 // A named keyed store might have a 2 element array, all other cases can count | 4583 // A named keyed store might have a 2 element array, all other cases can count |
4586 // on an array with at least 2 {map, handler} pairs, so they can go right | 4584 // on an array with at least 2 {map, handler} pairs, so they can go right |
4587 // into polymorphic array handling. | 4585 // into polymorphic array handling. |
4588 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 4586 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
4589 __ j(not_equal, &start_polymorphic); | 4587 __ j(not_equal, &start_polymorphic); |
4590 | 4588 |
4591 // found, now call handler. | 4589 // found, now call handler. |
4592 Register handler = feedback; | 4590 Register handler = feedback; |
4593 DCHECK(handler.is(VectorStoreICDescriptor::ValueRegister())); | 4591 DCHECK(handler.is(VectorStoreICDescriptor::ValueRegister())); |
4594 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); | 4592 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); |
4595 __ pop(vector); | 4593 __ pop(vector); |
4596 __ pop(receiver); | 4594 __ pop(receiver); |
4597 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | 4595 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
4598 __ mov(Operand::StaticVariable(virtual_register), handler); | 4596 __ xchg(handler, Operand(esp, 0)); |
4599 __ pop(handler); // Pop "value". | 4597 __ ret(0); |
4600 __ jmp(Operand::StaticVariable(virtual_register)); | |
4601 | 4598 |
4602 // Polymorphic, we have to loop from 2 to N | 4599 // Polymorphic, we have to loop from 2 to N |
4603 | 4600 |
4604 // TODO(mvstanton): I think there is a bug here, we are assuming the | 4601 // TODO(mvstanton): I think there is a bug here, we are assuming the |
4605 // array has more than one map/handler pair, but we call this function in the | 4602 // array has more than one map/handler pair, but we call this function in the |
4606 // keyed store with a string key case, where it might be just an array of two | 4603 // keyed store with a string key case, where it might be just an array of two |
4607 // elements. | 4604 // elements. |
4608 | 4605 |
4609 __ bind(&start_polymorphic); | 4606 __ bind(&start_polymorphic); |
4610 __ push(key); | 4607 __ push(key); |
4611 Register counter = key; | 4608 Register counter = key; |
4612 __ mov(counter, Immediate(Smi::FromInt(2))); | 4609 __ mov(counter, Immediate(Smi::FromInt(2))); |
4613 __ bind(&next_loop); | 4610 __ bind(&next_loop); |
4614 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 4611 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
4615 FixedArray::kHeaderSize)); | 4612 FixedArray::kHeaderSize)); |
4616 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 4613 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
4617 __ j(not_equal, &prepare_next); | 4614 __ j(not_equal, &prepare_next); |
4618 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, | 4615 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, |
4619 FixedArray::kHeaderSize + kPointerSize)); | 4616 FixedArray::kHeaderSize + kPointerSize)); |
4620 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | |
4621 __ pop(key); | 4617 __ pop(key); |
4622 __ pop(vector); | 4618 __ pop(vector); |
4623 __ pop(receiver); | 4619 __ pop(receiver); |
4624 __ mov(Operand::StaticVariable(virtual_register), handler); | 4620 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
4625 __ pop(handler); // Pop "value". | 4621 __ xchg(handler, Operand(esp, 0)); |
4626 __ jmp(Operand::StaticVariable(virtual_register)); | 4622 __ ret(0); |
4627 | 4623 |
4628 __ bind(&prepare_next); | 4624 __ bind(&prepare_next); |
4629 __ add(counter, Immediate(Smi::FromInt(2))); | 4625 __ add(counter, Immediate(Smi::FromInt(2))); |
4630 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | 4626 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
4631 __ j(less, &next_loop); | 4627 __ j(less, &next_loop); |
4632 | 4628 |
4633 // We exhausted our array of map handler pairs. | 4629 // We exhausted our array of map handler pairs. |
4634 __ pop(key); | 4630 __ pop(key); |
4635 __ pop(vector); | 4631 __ pop(vector); |
4636 __ pop(receiver); | 4632 __ pop(receiver); |
4637 __ jmp(miss); | 4633 __ jmp(miss); |
4638 | 4634 |
4639 __ bind(&load_smi_map); | 4635 __ bind(&load_smi_map); |
4640 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | 4636 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
4641 __ jmp(&compare_map); | 4637 __ jmp(&compare_map); |
4642 } | 4638 } |
4643 | 4639 |
4644 | 4640 |
4645 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, | 4641 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, |
4646 Register key, Register vector, | 4642 Register key, Register vector, |
4647 Register slot, Register weak_cell, | 4643 Register slot, Register weak_cell, |
4648 Label* miss) { | 4644 Label* miss) { |
4649 // The store ic value is on the stack. | 4645 // The store ic value is on the stack. |
4650 DCHECK(weak_cell.is(VectorStoreICDescriptor::ValueRegister())); | 4646 DCHECK(weak_cell.is(VectorStoreICDescriptor::ValueRegister())); |
4651 ExternalReference virtual_register = | |
4652 ExternalReference::vector_store_virtual_register(masm->isolate()); | |
4653 | 4647 |
4654 // feedback initially contains the feedback array | 4648 // feedback initially contains the feedback array |
4655 Label compare_smi_map; | 4649 Label compare_smi_map; |
4656 | 4650 |
4657 // Move the weak map into the weak_cell register. | 4651 // Move the weak map into the weak_cell register. |
4658 Register ic_map = weak_cell; | 4652 Register ic_map = weak_cell; |
4659 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); | 4653 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); |
4660 | 4654 |
4661 // Receiver might not be a heap object. | 4655 // Receiver might not be a heap object. |
4662 __ JumpIfSmi(receiver, &compare_smi_map); | 4656 __ JumpIfSmi(receiver, &compare_smi_map); |
4663 __ cmp(ic_map, FieldOperand(receiver, 0)); | 4657 __ cmp(ic_map, FieldOperand(receiver, 0)); |
4664 __ j(not_equal, miss); | 4658 __ j(not_equal, miss); |
4665 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 4659 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
4666 FixedArray::kHeaderSize + kPointerSize)); | 4660 FixedArray::kHeaderSize + kPointerSize)); |
4667 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 4661 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
4668 // Put the store ic value back in it's register. | 4662 // Put the store ic value back in it's register. |
4669 __ mov(Operand::StaticVariable(virtual_register), weak_cell); | 4663 __ xchg(weak_cell, Operand(esp, 0)); |
4670 __ pop(weak_cell); // Pop "value". | 4664 // "return" to the handler. |
4671 // jump to the handler. | 4665 __ ret(0); |
4672 __ jmp(Operand::StaticVariable(virtual_register)); | |
4673 | 4666 |
4674 // In microbenchmarks, it made sense to unroll this code so that the call to | 4667 // In microbenchmarks, it made sense to unroll this code so that the call to |
4675 // the handler is duplicated for a HeapObject receiver and a Smi receiver. | 4668 // the handler is duplicated for a HeapObject receiver and a Smi receiver. |
4676 __ bind(&compare_smi_map); | 4669 __ bind(&compare_smi_map); |
4677 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); | 4670 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); |
4678 __ j(not_equal, miss); | 4671 __ j(not_equal, miss); |
4679 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 4672 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
4680 FixedArray::kHeaderSize + kPointerSize)); | 4673 FixedArray::kHeaderSize + kPointerSize)); |
4681 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 4674 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
4682 __ mov(Operand::StaticVariable(virtual_register), weak_cell); | 4675 // Put the store ic value back in it's register. |
4683 __ pop(weak_cell); // Pop "value". | 4676 __ xchg(weak_cell, Operand(esp, 0)); |
4684 // jump to the handler. | 4677 // "return" to the handler. |
4685 __ jmp(Operand::StaticVariable(virtual_register)); | 4678 __ ret(0); |
4686 } | 4679 } |
4687 | 4680 |
4688 | 4681 |
4689 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 4682 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
4690 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx | 4683 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx |
4691 Register key = VectorStoreICDescriptor::NameRegister(); // ecx | 4684 Register key = VectorStoreICDescriptor::NameRegister(); // ecx |
4692 Register value = VectorStoreICDescriptor::ValueRegister(); // eax | 4685 Register value = VectorStoreICDescriptor::ValueRegister(); // eax |
4693 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx | 4686 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx |
4694 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi | 4687 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi |
4695 Label miss; | 4688 Label miss; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4748 | 4741 |
4749 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, | 4742 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, |
4750 Register receiver, Register key, | 4743 Register receiver, Register key, |
4751 Register vector, Register slot, | 4744 Register vector, Register slot, |
4752 Register feedback, Label* miss) { | 4745 Register feedback, Label* miss) { |
4753 // feedback initially contains the feedback array | 4746 // feedback initially contains the feedback array |
4754 Label next, next_loop, prepare_next; | 4747 Label next, next_loop, prepare_next; |
4755 Label load_smi_map, compare_map; | 4748 Label load_smi_map, compare_map; |
4756 Label transition_call; | 4749 Label transition_call; |
4757 Label pop_and_miss; | 4750 Label pop_and_miss; |
4758 ExternalReference virtual_register = | |
4759 ExternalReference::vector_store_virtual_register(masm->isolate()); | |
4760 | 4751 |
4761 __ push(receiver); | 4752 __ push(receiver); |
4762 __ push(vector); | 4753 __ push(vector); |
4763 | 4754 |
4764 Register receiver_map = receiver; | 4755 Register receiver_map = receiver; |
4765 Register cached_map = vector; | 4756 Register cached_map = vector; |
4766 | 4757 |
4767 // Receiver might not be a heap object. | 4758 // Receiver might not be a heap object. |
4768 __ JumpIfSmi(receiver, &load_smi_map); | 4759 __ JumpIfSmi(receiver, &load_smi_map); |
4769 __ mov(receiver_map, FieldOperand(receiver, 0)); | 4760 __ mov(receiver_map, FieldOperand(receiver, 0)); |
(...skipping 16 matching lines...) Expand all Loading... |
4786 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 4777 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
4787 FixedArray::kHeaderSize + kPointerSize)); | 4778 FixedArray::kHeaderSize + kPointerSize)); |
4788 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); | 4779 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); |
4789 __ j(not_equal, &transition_call); | 4780 __ j(not_equal, &transition_call); |
4790 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, | 4781 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
4791 FixedArray::kHeaderSize + 2 * kPointerSize)); | 4782 FixedArray::kHeaderSize + 2 * kPointerSize)); |
4792 __ pop(key); | 4783 __ pop(key); |
4793 __ pop(vector); | 4784 __ pop(vector); |
4794 __ pop(receiver); | 4785 __ pop(receiver); |
4795 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); | 4786 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
4796 __ mov(Operand::StaticVariable(virtual_register), feedback); | 4787 __ xchg(feedback, Operand(esp, 0)); |
4797 __ pop(feedback); // Pop "value". | 4788 __ ret(0); |
4798 __ jmp(Operand::StaticVariable(virtual_register)); | |
4799 | 4789 |
4800 __ bind(&transition_call); | 4790 __ bind(&transition_call); |
4801 // Oh holy hell this will be tough. | 4791 // Oh holy hell this will be tough. |
4802 // The map goes in vector register. | 4792 // The map goes in vector register. |
4803 __ mov(receiver, FieldOperand(cached_map, WeakCell::kValueOffset)); | 4793 __ mov(receiver, FieldOperand(cached_map, WeakCell::kValueOffset)); |
4804 // The weak cell may have been cleared. | 4794 // The weak cell may have been cleared. |
4805 __ JumpIfSmi(receiver, &pop_and_miss); | 4795 __ JumpIfSmi(receiver, &pop_and_miss); |
4806 // slot goes on the stack, and holds return address. | 4796 // slot goes on the stack, and holds return address. |
4807 __ xchg(slot, Operand(esp, 4 * kPointerSize)); | 4797 __ xchg(slot, Operand(esp, 4 * kPointerSize)); |
4808 // Get the handler in value. | 4798 // Get the handler in value. |
(...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5816 Operand(ebp, 7 * kPointerSize), NULL); | 5806 Operand(ebp, 7 * kPointerSize), NULL); |
5817 } | 5807 } |
5818 | 5808 |
5819 | 5809 |
5820 #undef __ | 5810 #undef __ |
5821 | 5811 |
5822 } // namespace internal | 5812 } // namespace internal |
5823 } // namespace v8 | 5813 } // namespace v8 |
5824 | 5814 |
5825 #endif // V8_TARGET_ARCH_IA32 | 5815 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |