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 4596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4607 void VectorStoreICStub::Generate(MacroAssembler* masm) { | 4607 void VectorStoreICStub::Generate(MacroAssembler* masm) { |
4608 GenerateImpl(masm, false); | 4608 GenerateImpl(masm, false); |
4609 } | 4609 } |
4610 | 4610 |
4611 | 4611 |
4612 void VectorStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { | 4612 void VectorStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { |
4613 GenerateImpl(masm, true); | 4613 GenerateImpl(masm, true); |
4614 } | 4614 } |
4615 | 4615 |
4616 | 4616 |
| 4617 // value is on the stack already. |
| 4618 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, |
| 4619 Register key, Register vector, |
| 4620 Register slot, Register feedback, |
| 4621 Label* miss) { |
| 4622 // feedback initially contains the feedback array |
| 4623 Label next, next_loop, prepare_next; |
| 4624 Label load_smi_map, compare_map; |
| 4625 Label start_polymorphic; |
| 4626 |
| 4627 __ push(receiver); |
| 4628 __ push(vector); |
| 4629 |
| 4630 Register receiver_map = receiver; |
| 4631 Register cached_map = vector; |
| 4632 |
| 4633 // Receiver might not be a heap object. |
| 4634 __ JumpIfSmi(receiver, &load_smi_map); |
| 4635 __ mov(receiver_map, FieldOperand(receiver, 0)); |
| 4636 __ bind(&compare_map); |
| 4637 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); |
| 4638 |
| 4639 // A named keyed store might have a 2 element array, all other cases can count |
| 4640 // on an array with at least 2 {map, handler} pairs, so they can go right |
| 4641 // into polymorphic array handling. |
| 4642 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4643 __ j(not_equal, &start_polymorphic); |
| 4644 |
| 4645 // found, now call handler. |
| 4646 Register handler = feedback; |
| 4647 DCHECK(handler.is(VectorStoreICDescriptor::ValueRegister())); |
| 4648 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); |
| 4649 __ pop(vector); |
| 4650 __ pop(receiver); |
| 4651 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
| 4652 __ xchg(handler, Operand(esp, 0)); |
| 4653 __ ret(0); |
| 4654 |
| 4655 // Polymorphic, we have to loop from 2 to N |
| 4656 |
| 4657 // TODO(mvstanton): I think there is a bug here, we are assuming the |
| 4658 // array has more than one map/handler pair, but we call this function in the |
| 4659 // keyed store with a string key case, where it might be just an array of two |
| 4660 // elements. |
| 4661 |
| 4662 __ bind(&start_polymorphic); |
| 4663 __ push(key); |
| 4664 Register counter = key; |
| 4665 __ mov(counter, Immediate(Smi::FromInt(2))); |
| 4666 __ bind(&next_loop); |
| 4667 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4668 FixedArray::kHeaderSize)); |
| 4669 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4670 __ j(not_equal, &prepare_next); |
| 4671 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4672 FixedArray::kHeaderSize + kPointerSize)); |
| 4673 __ pop(key); |
| 4674 __ pop(vector); |
| 4675 __ pop(receiver); |
| 4676 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
| 4677 __ xchg(handler, Operand(esp, 0)); |
| 4678 __ ret(0); |
| 4679 |
| 4680 __ bind(&prepare_next); |
| 4681 __ add(counter, Immediate(Smi::FromInt(2))); |
| 4682 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
| 4683 __ j(less, &next_loop); |
| 4684 |
| 4685 // We exhausted our array of map handler pairs. |
| 4686 __ pop(key); |
| 4687 __ pop(vector); |
| 4688 __ pop(receiver); |
| 4689 __ jmp(miss); |
| 4690 |
| 4691 __ bind(&load_smi_map); |
| 4692 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
| 4693 __ jmp(&compare_map); |
| 4694 } |
| 4695 |
| 4696 |
| 4697 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, |
| 4698 Register key, Register vector, |
| 4699 Register slot, Register weak_cell, |
| 4700 Label* miss) { |
| 4701 // The store ic value is on the stack. |
| 4702 DCHECK(weak_cell.is(VectorStoreICDescriptor::ValueRegister())); |
| 4703 |
| 4704 // feedback initially contains the feedback array |
| 4705 Label compare_smi_map; |
| 4706 |
| 4707 // Move the weak map into the weak_cell register. |
| 4708 Register ic_map = weak_cell; |
| 4709 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); |
| 4710 |
| 4711 // Receiver might not be a heap object. |
| 4712 __ JumpIfSmi(receiver, &compare_smi_map); |
| 4713 __ cmp(ic_map, FieldOperand(receiver, 0)); |
| 4714 __ j(not_equal, miss); |
| 4715 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
| 4716 FixedArray::kHeaderSize + kPointerSize)); |
| 4717 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
| 4718 // Put the store ic value back in it's register. |
| 4719 __ xchg(weak_cell, Operand(esp, 0)); |
| 4720 // "return" to the handler. |
| 4721 __ ret(0); |
| 4722 |
| 4723 // In microbenchmarks, it made sense to unroll this code so that the call to |
| 4724 // the handler is duplicated for a HeapObject receiver and a Smi receiver. |
| 4725 __ bind(&compare_smi_map); |
| 4726 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); |
| 4727 __ j(not_equal, miss); |
| 4728 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
| 4729 FixedArray::kHeaderSize + kPointerSize)); |
| 4730 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
| 4731 // Put the store ic value back in it's register. |
| 4732 __ xchg(weak_cell, Operand(esp, 0)); |
| 4733 // "return" to the handler. |
| 4734 __ ret(0); |
| 4735 } |
| 4736 |
| 4737 |
4617 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 4738 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
| 4739 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx |
| 4740 Register key = VectorStoreICDescriptor::NameRegister(); // ecx |
| 4741 Register value = VectorStoreICDescriptor::ValueRegister(); // eax |
| 4742 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx |
| 4743 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi |
4618 Label miss; | 4744 Label miss; |
4619 | 4745 |
4620 // TODO(mvstanton): Implement. | 4746 __ push(value); |
| 4747 |
| 4748 Register scratch = value; |
| 4749 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
| 4750 FixedArray::kHeaderSize)); |
| 4751 |
| 4752 // Is it a weak cell? |
| 4753 Label try_array; |
| 4754 Label not_array, smi_key, key_okay; |
| 4755 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); |
| 4756 __ j(not_equal, &try_array); |
| 4757 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
| 4758 |
| 4759 // Is it a fixed array? |
| 4760 __ bind(&try_array); |
| 4761 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); |
| 4762 __ j(not_equal, ¬_array); |
| 4763 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
| 4764 |
| 4765 __ bind(¬_array); |
| 4766 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); |
| 4767 __ j(not_equal, &miss); |
| 4768 |
| 4769 __ pop(value); |
| 4770 __ push(slot); |
| 4771 __ push(vector); |
| 4772 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags( |
| 4773 Code::ComputeHandlerFlags(Code::STORE_IC)); |
| 4774 masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, code_flags, |
| 4775 receiver, key, slot, no_reg); |
| 4776 __ pop(vector); |
| 4777 __ pop(slot); |
| 4778 Label no_pop_miss; |
| 4779 __ jmp(&no_pop_miss); |
| 4780 |
4621 __ bind(&miss); | 4781 __ bind(&miss); |
| 4782 __ pop(value); |
| 4783 __ bind(&no_pop_miss); |
4622 StoreIC::GenerateMiss(masm); | 4784 StoreIC::GenerateMiss(masm); |
4623 } | 4785 } |
4624 | 4786 |
4625 | 4787 |
4626 void VectorKeyedStoreICStub::Generate(MacroAssembler* masm) { | 4788 void VectorKeyedStoreICStub::Generate(MacroAssembler* masm) { |
4627 GenerateImpl(masm, false); | 4789 GenerateImpl(masm, false); |
4628 } | 4790 } |
4629 | 4791 |
4630 | 4792 |
4631 void VectorKeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { | 4793 void VectorKeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { |
4632 GenerateImpl(masm, true); | 4794 GenerateImpl(masm, true); |
4633 } | 4795 } |
4634 | 4796 |
4635 | 4797 |
| 4798 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, |
| 4799 Register receiver, Register key, |
| 4800 Register vector, Register slot, |
| 4801 Register feedback, Label* miss) { |
| 4802 // feedback initially contains the feedback array |
| 4803 Label next, next_loop, prepare_next; |
| 4804 Label load_smi_map, compare_map; |
| 4805 Label transition_call; |
| 4806 Label pop_and_miss; |
| 4807 |
| 4808 __ push(receiver); |
| 4809 __ push(vector); |
| 4810 |
| 4811 Register receiver_map = receiver; |
| 4812 Register cached_map = vector; |
| 4813 |
| 4814 // Receiver might not be a heap object. |
| 4815 __ JumpIfSmi(receiver, &load_smi_map); |
| 4816 __ mov(receiver_map, FieldOperand(receiver, 0)); |
| 4817 __ bind(&compare_map); |
| 4818 |
| 4819 // Polymorphic, we have to loop from 0 to N - 1 |
| 4820 __ push(key); |
| 4821 // On the stack we have: |
| 4822 // key (esp) |
| 4823 // vector |
| 4824 // receiver |
| 4825 // value |
| 4826 Register counter = key; |
| 4827 __ mov(counter, Immediate(Smi::FromInt(0))); |
| 4828 __ bind(&next_loop); |
| 4829 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4830 FixedArray::kHeaderSize)); |
| 4831 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4832 __ j(not_equal, &prepare_next); |
| 4833 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4834 FixedArray::kHeaderSize + kPointerSize)); |
| 4835 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); |
| 4836 __ j(not_equal, &transition_call); |
| 4837 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4838 FixedArray::kHeaderSize + 2 * kPointerSize)); |
| 4839 __ pop(key); |
| 4840 __ pop(vector); |
| 4841 __ pop(receiver); |
| 4842 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
| 4843 __ xchg(feedback, Operand(esp, 0)); |
| 4844 __ ret(0); |
| 4845 |
| 4846 __ bind(&transition_call); |
| 4847 // Oh holy hell this will be tough. |
| 4848 // The map goes in vector register. |
| 4849 __ mov(receiver, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4850 // The weak cell may have been cleared. |
| 4851 __ JumpIfSmi(receiver, &pop_and_miss); |
| 4852 // slot goes on the stack, and holds return address. |
| 4853 __ xchg(slot, Operand(esp, 4 * kPointerSize)); |
| 4854 // Get the handler in value. |
| 4855 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4856 FixedArray::kHeaderSize + 2 * kPointerSize)); |
| 4857 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
| 4858 // Pop key into place. |
| 4859 __ pop(key); |
| 4860 // Put the return address on top of stack, vector goes in slot. |
| 4861 __ xchg(slot, Operand(esp, 0)); |
| 4862 // put the map on the stack, receiver holds receiver. |
| 4863 __ xchg(receiver, Operand(esp, 1 * kPointerSize)); |
| 4864 // put the vector on the stack, slot holds value. |
| 4865 __ xchg(slot, Operand(esp, 2 * kPointerSize)); |
| 4866 // feedback (value) = value, slot = handler. |
| 4867 __ xchg(feedback, slot); |
| 4868 __ jmp(slot); |
| 4869 |
| 4870 __ bind(&prepare_next); |
| 4871 __ add(counter, Immediate(Smi::FromInt(3))); |
| 4872 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
| 4873 __ j(less, &next_loop); |
| 4874 |
| 4875 // We exhausted our array of map handler pairs. |
| 4876 __ bind(&pop_and_miss); |
| 4877 __ pop(key); |
| 4878 __ pop(vector); |
| 4879 __ pop(receiver); |
| 4880 __ jmp(miss); |
| 4881 |
| 4882 __ bind(&load_smi_map); |
| 4883 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
| 4884 __ jmp(&compare_map); |
| 4885 } |
| 4886 |
| 4887 |
4636 void VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 4888 void VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
| 4889 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx |
| 4890 Register key = VectorStoreICDescriptor::NameRegister(); // ecx |
| 4891 Register value = VectorStoreICDescriptor::ValueRegister(); // eax |
| 4892 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx |
| 4893 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi |
4637 Label miss; | 4894 Label miss; |
4638 | 4895 |
4639 // TODO(mvstanton): Implement. | 4896 __ push(value); |
| 4897 |
| 4898 Register scratch = value; |
| 4899 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
| 4900 FixedArray::kHeaderSize)); |
| 4901 |
| 4902 // Is it a weak cell? |
| 4903 Label try_array; |
| 4904 Label not_array, smi_key, key_okay; |
| 4905 __ CompareRoot(FieldOperand(scratch, 0), Heap::kWeakCellMapRootIndex); |
| 4906 __ j(not_equal, &try_array); |
| 4907 HandleMonomorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
| 4908 |
| 4909 // Is it a fixed array? |
| 4910 __ bind(&try_array); |
| 4911 __ CompareRoot(FieldOperand(scratch, 0), Heap::kFixedArrayMapRootIndex); |
| 4912 __ j(not_equal, ¬_array); |
| 4913 HandlePolymorphicKeyedStoreCase(masm, receiver, key, vector, slot, scratch, |
| 4914 &miss); |
| 4915 |
| 4916 __ bind(¬_array); |
| 4917 Label try_poly_name; |
| 4918 __ CompareRoot(scratch, Heap::kmegamorphic_symbolRootIndex); |
| 4919 __ j(not_equal, &try_poly_name); |
| 4920 |
| 4921 __ pop(value); |
| 4922 |
| 4923 Handle<Code> megamorphic_stub = |
| 4924 KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); |
| 4925 __ jmp(megamorphic_stub, RelocInfo::CODE_TARGET); |
| 4926 |
| 4927 __ bind(&try_poly_name); |
| 4928 // We might have a name in feedback, and a fixed array in the next slot. |
| 4929 __ cmp(key, scratch); |
| 4930 __ j(not_equal, &miss); |
| 4931 // If the name comparison succeeded, we know we have a fixed array with |
| 4932 // at least one map/handler pair. |
| 4933 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
| 4934 FixedArray::kHeaderSize + kPointerSize)); |
| 4935 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, &miss); |
| 4936 |
4640 __ bind(&miss); | 4937 __ bind(&miss); |
| 4938 __ pop(value); |
4641 KeyedStoreIC::GenerateMiss(masm); | 4939 KeyedStoreIC::GenerateMiss(masm); |
4642 } | 4940 } |
4643 | 4941 |
4644 | 4942 |
4645 void CallICTrampolineStub::Generate(MacroAssembler* masm) { | 4943 void CallICTrampolineStub::Generate(MacroAssembler* masm) { |
4646 EmitLoadTypeFeedbackVector(masm, ebx); | 4944 EmitLoadTypeFeedbackVector(masm, ebx); |
4647 CallICStub stub(isolate(), state()); | 4945 CallICStub stub(isolate(), state()); |
4648 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 4946 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
4649 } | 4947 } |
4650 | 4948 |
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5571 Operand(ebp, 7 * kPointerSize), NULL); | 5869 Operand(ebp, 7 * kPointerSize), NULL); |
5572 } | 5870 } |
5573 | 5871 |
5574 | 5872 |
5575 #undef __ | 5873 #undef __ |
5576 | 5874 |
5577 } // namespace internal | 5875 } // namespace internal |
5578 } // namespace v8 | 5876 } // namespace v8 |
5579 | 5877 |
5580 #endif // V8_TARGET_ARCH_IA32 | 5878 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |