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