| 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/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/ic/ic.h" | 8 #include "src/ic/ic.h" |
| 9 #include "src/ic/ic-compiler.h" | 9 #include "src/ic/ic-compiler.h" |
| 10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 __ bind(&slow); | 554 __ bind(&slow); |
| 555 PropertyICCompiler::GenerateRuntimeSetProperty(masm, language_mode); | 555 PropertyICCompiler::GenerateRuntimeSetProperty(masm, language_mode); |
| 556 // Never returns to here. | 556 // Never returns to here. |
| 557 | 557 |
| 558 __ bind(&maybe_name_key); | 558 __ bind(&maybe_name_key); |
| 559 __ mov(ebx, FieldOperand(key, HeapObject::kMapOffset)); | 559 __ mov(ebx, FieldOperand(key, HeapObject::kMapOffset)); |
| 560 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 560 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 561 __ JumpIfNotUniqueNameInstanceType(ebx, &slow); | 561 __ JumpIfNotUniqueNameInstanceType(ebx, &slow); |
| 562 | 562 |
| 563 | 563 |
| 564 if (FLAG_vector_stores) { | 564 // The handlers in the stub cache expect a vector and slot. Since we won't |
| 565 // The handlers in the stub cache expect a vector and slot. Since we won't | 565 // change the IC from any downstream misses, a dummy vector can be used. |
| 566 // change the IC from any downstream misses, a dummy vector can be used. | 566 Handle<TypeFeedbackVector> dummy_vector = |
| 567 Handle<TypeFeedbackVector> dummy_vector = | 567 TypeFeedbackVector::DummyVector(masm->isolate()); |
| 568 TypeFeedbackVector::DummyVector(masm->isolate()); | 568 int slot = dummy_vector->GetIndex( |
| 569 int slot = dummy_vector->GetIndex( | 569 FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)); |
| 570 FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)); | 570 __ push(Immediate(Smi::FromInt(slot))); |
| 571 __ push(Immediate(Smi::FromInt(slot))); | 571 __ push(Immediate(dummy_vector)); |
| 572 __ push(Immediate(dummy_vector)); | |
| 573 } | |
| 574 | 572 |
| 575 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 573 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
| 576 Code::ComputeHandlerFlags(Code::STORE_IC)); | 574 Code::ComputeHandlerFlags(Code::STORE_IC)); |
| 577 masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags, | 575 masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags, |
| 578 receiver, key, edi, no_reg); | 576 receiver, key, edi, no_reg); |
| 579 | 577 |
| 580 if (FLAG_vector_stores) { | 578 __ pop(VectorStoreICDescriptor::VectorRegister()); |
| 581 __ pop(VectorStoreICDescriptor::VectorRegister()); | 579 __ pop(VectorStoreICDescriptor::SlotRegister()); |
| 582 __ pop(VectorStoreICDescriptor::SlotRegister()); | |
| 583 } | |
| 584 | 580 |
| 585 // Cache miss. | 581 // Cache miss. |
| 586 __ jmp(&miss); | 582 __ jmp(&miss); |
| 587 | 583 |
| 588 // Extra capacity case: Check if there is extra capacity to | 584 // Extra capacity case: Check if there is extra capacity to |
| 589 // perform the store and update the length. Used for adding one | 585 // perform the store and update the length. Used for adding one |
| 590 // element to the array by writing to array[array.length]. | 586 // element to the array by writing to array[array.length]. |
| 591 __ bind(&extra); | 587 __ bind(&extra); |
| 592 // receiver is a JSArray. | 588 // receiver is a JSArray. |
| 593 // key is a smi. | 589 // key is a smi. |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 __ push(ebx); | 721 __ push(ebx); |
| 726 | 722 |
| 727 // Do tail-call to runtime routine. | 723 // Do tail-call to runtime routine. |
| 728 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong | 724 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong |
| 729 : Runtime::kKeyedGetProperty, | 725 : Runtime::kKeyedGetProperty, |
| 730 2, 1); | 726 2, 1); |
| 731 } | 727 } |
| 732 | 728 |
| 733 | 729 |
| 734 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 730 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 735 if (FLAG_vector_stores) { | 731 // This shouldn't be called. |
| 736 // This shouldn't be called. | 732 // TODO(mvstanton): remove this method. |
| 737 __ int3(); | 733 __ int3(); |
| 738 return; | 734 return; |
| 739 } | |
| 740 | |
| 741 // Return address is on the stack. | |
| 742 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | |
| 743 Code::ComputeHandlerFlags(Code::STORE_IC)); | |
| 744 masm->isolate()->stub_cache()->GenerateProbe( | |
| 745 masm, Code::STORE_IC, flags, StoreDescriptor::ReceiverRegister(), | |
| 746 StoreDescriptor::NameRegister(), ebx, no_reg); | |
| 747 | |
| 748 // Cache miss: Jump to runtime. | |
| 749 GenerateMiss(masm); | |
| 750 } | 735 } |
| 751 | 736 |
| 752 | 737 |
| 753 static void StoreIC_PushArgs(MacroAssembler* masm) { | 738 static void StoreIC_PushArgs(MacroAssembler* masm) { |
| 754 Register receiver = StoreDescriptor::ReceiverRegister(); | 739 Register receiver = StoreDescriptor::ReceiverRegister(); |
| 755 Register name = StoreDescriptor::NameRegister(); | 740 Register name = StoreDescriptor::NameRegister(); |
| 756 Register value = StoreDescriptor::ValueRegister(); | 741 Register value = StoreDescriptor::ValueRegister(); |
| 742 Register slot = VectorStoreICDescriptor::SlotRegister(); |
| 743 Register vector = VectorStoreICDescriptor::VectorRegister(); |
| 757 | 744 |
| 758 if (FLAG_vector_stores) { | 745 __ xchg(receiver, Operand(esp, 0)); |
| 759 Register slot = VectorStoreICDescriptor::SlotRegister(); | 746 __ push(name); |
| 760 Register vector = VectorStoreICDescriptor::VectorRegister(); | 747 __ push(value); |
| 761 | 748 __ push(slot); |
| 762 __ xchg(receiver, Operand(esp, 0)); | 749 __ push(vector); |
| 763 __ push(name); | 750 __ push(receiver); // Contains the return address. |
| 764 __ push(value); | |
| 765 __ push(slot); | |
| 766 __ push(vector); | |
| 767 __ push(receiver); // Contains the return address. | |
| 768 } else { | |
| 769 DCHECK(!ebx.is(receiver) && !ebx.is(name) && !ebx.is(value)); | |
| 770 __ pop(ebx); | |
| 771 __ push(receiver); | |
| 772 __ push(name); | |
| 773 __ push(value); | |
| 774 __ push(ebx); | |
| 775 } | |
| 776 } | 751 } |
| 777 | 752 |
| 778 | 753 |
| 779 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 754 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 780 // Return address is on the stack. | 755 // Return address is on the stack. |
| 781 StoreIC_PushArgs(masm); | 756 StoreIC_PushArgs(masm); |
| 782 | 757 |
| 783 // Perform tail call to the entry. | 758 // Perform tail call to the entry. |
| 784 int args = FLAG_vector_stores ? 5 : 3; | 759 __ TailCallRuntime(Runtime::kStoreIC_Miss, 5, 1); |
| 785 __ TailCallRuntime(Runtime::kStoreIC_Miss, args, 1); | |
| 786 } | 760 } |
| 787 | 761 |
| 788 | 762 |
| 789 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 763 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 790 Label restore_miss; | 764 Label restore_miss; |
| 791 Register receiver = StoreDescriptor::ReceiverRegister(); | 765 Register receiver = StoreDescriptor::ReceiverRegister(); |
| 792 Register name = StoreDescriptor::NameRegister(); | 766 Register name = StoreDescriptor::NameRegister(); |
| 793 Register value = StoreDescriptor::ValueRegister(); | 767 Register value = StoreDescriptor::ValueRegister(); |
| 794 Register vector = VectorStoreICDescriptor::VectorRegister(); | 768 Register vector = VectorStoreICDescriptor::VectorRegister(); |
| 795 Register slot = VectorStoreICDescriptor::SlotRegister(); | 769 Register slot = VectorStoreICDescriptor::SlotRegister(); |
| 796 | 770 |
| 797 // A lot of registers are needed for storing to slow case | 771 // A lot of registers are needed for storing to slow case |
| 798 // objects. Push and restore receiver but rely on | 772 // objects. Push and restore receiver but rely on |
| 799 // GenerateDictionaryStore preserving the value and name. | 773 // GenerateDictionaryStore preserving the value and name. |
| 800 __ push(receiver); | 774 __ push(receiver); |
| 801 if (FLAG_vector_stores) { | 775 __ push(vector); |
| 802 __ push(vector); | 776 __ push(slot); |
| 803 __ push(slot); | |
| 804 } | |
| 805 | 777 |
| 806 Register dictionary = ebx; | 778 Register dictionary = ebx; |
| 807 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 779 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 808 GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, | 780 GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, |
| 809 receiver, edi); | 781 receiver, edi); |
| 810 __ Drop(FLAG_vector_stores ? 3 : 1); | 782 __ Drop(3); |
| 811 Counters* counters = masm->isolate()->counters(); | 783 Counters* counters = masm->isolate()->counters(); |
| 812 __ IncrementCounter(counters->store_normal_hit(), 1); | 784 __ IncrementCounter(counters->store_normal_hit(), 1); |
| 813 __ ret(0); | 785 __ ret(0); |
| 814 | 786 |
| 815 __ bind(&restore_miss); | 787 __ bind(&restore_miss); |
| 816 if (FLAG_vector_stores) { | 788 __ pop(slot); |
| 817 __ pop(slot); | 789 __ pop(vector); |
| 818 __ pop(vector); | |
| 819 } | |
| 820 __ pop(receiver); | 790 __ pop(receiver); |
| 821 __ IncrementCounter(counters->store_normal_miss(), 1); | 791 __ IncrementCounter(counters->store_normal_miss(), 1); |
| 822 GenerateMiss(masm); | 792 GenerateMiss(masm); |
| 823 } | 793 } |
| 824 | 794 |
| 825 | 795 |
| 826 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 796 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 827 // Return address is on the stack. | 797 // Return address is on the stack. |
| 828 StoreIC_PushArgs(masm); | 798 StoreIC_PushArgs(masm); |
| 829 | 799 |
| 830 // Do tail-call to runtime routine. | 800 // Do tail-call to runtime routine. |
| 831 int args = FLAG_vector_stores ? 5 : 3; | 801 __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss, 5, 1); |
| 832 __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss, args, 1); | |
| 833 } | 802 } |
| 834 | 803 |
| 835 | 804 |
| 836 #undef __ | 805 #undef __ |
| 837 | 806 |
| 838 | 807 |
| 839 Condition CompareIC::ComputeCondition(Token::Value op) { | 808 Condition CompareIC::ComputeCondition(Token::Value op) { |
| 840 switch (op) { | 809 switch (op) { |
| 841 case Token::EQ_STRICT: | 810 case Token::EQ_STRICT: |
| 842 case Token::EQ: | 811 case Token::EQ: |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 Condition cc = | 869 Condition cc = |
| 901 (check == ENABLE_INLINED_SMI_CHECK) | 870 (check == ENABLE_INLINED_SMI_CHECK) |
| 902 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 871 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 903 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 872 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 904 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 873 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 905 } | 874 } |
| 906 } // namespace internal | 875 } // namespace internal |
| 907 } // namespace v8 | 876 } // namespace v8 |
| 908 | 877 |
| 909 #endif // V8_TARGET_ARCH_IA32 | 878 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |