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