| 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_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 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 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); | 497 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); |
| 498 ElementsTransitionGenerator::GenerateDoubleToObject(masm, receiver, key, | 498 ElementsTransitionGenerator::GenerateDoubleToObject(masm, receiver, key, |
| 499 value, ebx, mode, slow); | 499 value, ebx, mode, slow); |
| 500 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); | 500 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 501 __ jmp(&finish_object_store); | 501 __ jmp(&finish_object_store); |
| 502 } | 502 } |
| 503 | 503 |
| 504 | 504 |
| 505 void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, | 505 void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, |
| 506 LanguageMode language_mode) { | 506 LanguageMode language_mode) { |
| 507 typedef StoreWithVectorDescriptor Descriptor; |
| 507 // Return address is on the stack. | 508 // Return address is on the stack. |
| 508 Label slow, fast_object, fast_object_grow; | 509 Label slow, fast_object, fast_object_grow; |
| 509 Label fast_double, fast_double_grow; | 510 Label fast_double, fast_double_grow; |
| 510 Label array, extra, check_if_double_array, maybe_name_key, miss; | 511 Label array, extra, check_if_double_array, maybe_name_key, miss; |
| 511 Register receiver = StoreDescriptor::ReceiverRegister(); | 512 Register receiver = Descriptor::ReceiverRegister(); |
| 512 Register key = StoreDescriptor::NameRegister(); | 513 Register key = Descriptor::NameRegister(); |
| 513 DCHECK(receiver.is(edx)); | 514 DCHECK(receiver.is(edx)); |
| 514 DCHECK(key.is(ecx)); | 515 DCHECK(key.is(ecx)); |
| 515 | 516 |
| 516 // Check that the object isn't a smi. | 517 // Check that the object isn't a smi. |
| 517 __ JumpIfSmi(receiver, &slow); | 518 __ JumpIfSmi(receiver, &slow); |
| 518 // Get the map from the receiver. | 519 // Get the map from the receiver. |
| 519 __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset)); | 520 __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 520 // Check that the receiver does not require access checks. | 521 // Check that the receiver does not require access checks. |
| 521 // The generic stub does not perform map checks. | 522 // The generic stub does not perform map checks. |
| 522 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), | 523 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), |
| 523 Immediate(1 << Map::kIsAccessCheckNeeded)); | 524 Immediate(1 << Map::kIsAccessCheckNeeded)); |
| 524 __ j(not_zero, &slow); | 525 __ j(not_zero, &slow); |
| 526 |
| 527 __ LoadParameterFromStack<Descriptor>(Descriptor::ValueRegister(), |
| 528 Descriptor::kValue); |
| 529 |
| 525 // Check that the key is a smi. | 530 // Check that the key is a smi. |
| 526 __ JumpIfNotSmi(key, &maybe_name_key); | 531 __ JumpIfNotSmi(key, &maybe_name_key); |
| 527 __ CmpInstanceType(edi, JS_ARRAY_TYPE); | 532 __ CmpInstanceType(edi, JS_ARRAY_TYPE); |
| 528 __ j(equal, &array); | 533 __ j(equal, &array); |
| 529 // Check that the object is some kind of JS object EXCEPT JS Value type. In | 534 // Check that the object is some kind of JS object EXCEPT JS Value type. In |
| 530 // the case that the object is a value-wrapper object, we enter the runtime | 535 // the case that the object is a value-wrapper object, we enter the runtime |
| 531 // system to make sure that indexing into string objects works as intended. | 536 // system to make sure that indexing into string objects works as intended. |
| 532 STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE); | 537 STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE); |
| 533 __ CmpInstanceType(edi, JS_OBJECT_TYPE); | 538 __ CmpInstanceType(edi, JS_OBJECT_TYPE); |
| 534 __ j(below, &slow); | 539 __ j(below, &slow); |
| 535 | 540 |
| 536 // Object case: Check key against length in the elements array. | 541 // Object case: Check key against length in the elements array. |
| 537 // Key is a smi. | 542 // Key is a smi. |
| 538 // edi: receiver map | 543 // edi: receiver map |
| 539 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); | 544 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); |
| 540 // Check array bounds. Both the key and the length of FixedArray are smis. | 545 // Check array bounds. Both the key and the length of FixedArray are smis. |
| 541 __ cmp(key, FieldOperand(ebx, FixedArray::kLengthOffset)); | 546 __ cmp(key, FieldOperand(ebx, FixedArray::kLengthOffset)); |
| 542 __ j(below, &fast_object); | 547 __ j(below, &fast_object); |
| 543 | 548 |
| 544 // Slow case: call runtime. | 549 // Slow case: call runtime. |
| 545 __ bind(&slow); | 550 __ bind(&slow); |
| 546 PropertyICCompiler::GenerateRuntimeSetProperty(masm, language_mode); | 551 PropertyICCompiler::GenerateRuntimeSetProperty(masm, language_mode); |
| 547 // Never returns to here. | 552 // Never returns to here. |
| 548 | 553 |
| 549 __ bind(&maybe_name_key); | 554 __ bind(&maybe_name_key); |
| 550 __ mov(ebx, FieldOperand(key, HeapObject::kMapOffset)); | 555 __ mov(ebx, FieldOperand(key, HeapObject::kMapOffset)); |
| 551 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 556 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 552 __ JumpIfNotUniqueNameInstanceType(ebx, &slow); | 557 __ JumpIfNotUniqueNameInstanceType(ebx, &slow); |
| 553 | 558 |
| 554 | |
| 555 // The handlers in the stub cache expect a vector and slot. Since we won't | |
| 556 // change the IC from any downstream misses, a dummy vector can be used. | |
| 557 Handle<TypeFeedbackVector> dummy_vector = | |
| 558 TypeFeedbackVector::DummyVector(masm->isolate()); | |
| 559 int slot = dummy_vector->GetIndex( | |
| 560 FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)); | |
| 561 __ push(Immediate(Smi::FromInt(slot))); | |
| 562 __ push(Immediate(dummy_vector)); | |
| 563 | |
| 564 masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, edi, | 559 masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, edi, |
| 565 no_reg); | 560 no_reg); |
| 566 | 561 |
| 567 __ pop(StoreWithVectorDescriptor::VectorRegister()); | |
| 568 __ pop(StoreWithVectorDescriptor::SlotRegister()); | |
| 569 | |
| 570 // Cache miss. | 562 // Cache miss. |
| 571 __ jmp(&miss); | 563 __ jmp(&miss); |
| 572 | 564 |
| 573 // Extra capacity case: Check if there is extra capacity to | 565 // Extra capacity case: Check if there is extra capacity to |
| 574 // perform the store and update the length. Used for adding one | 566 // perform the store and update the length. Used for adding one |
| 575 // element to the array by writing to array[array.length]. | 567 // element to the array by writing to array[array.length]. |
| 576 __ bind(&extra); | 568 __ bind(&extra); |
| 577 // receiver is a JSArray. | 569 // receiver is a JSArray. |
| 578 // key is a smi. | 570 // key is a smi. |
| 579 // ebx: receiver->elements, a FixedArray | 571 // ebx: receiver->elements, a FixedArray |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 718 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 727 // Return address is on the stack. | 719 // Return address is on the stack. |
| 728 StoreIC_PushArgs(masm); | 720 StoreIC_PushArgs(masm); |
| 729 | 721 |
| 730 // Perform tail call to the entry. | 722 // Perform tail call to the entry. |
| 731 __ TailCallRuntime(Runtime::kStoreIC_Miss); | 723 __ TailCallRuntime(Runtime::kStoreIC_Miss); |
| 732 } | 724 } |
| 733 | 725 |
| 734 | 726 |
| 735 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 727 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 728 typedef StoreWithVectorDescriptor Descriptor; |
| 736 Label restore_miss; | 729 Label restore_miss; |
| 737 Register receiver = StoreDescriptor::ReceiverRegister(); | 730 Register receiver = Descriptor::ReceiverRegister(); |
| 738 Register name = StoreDescriptor::NameRegister(); | 731 Register name = Descriptor::NameRegister(); |
| 739 Register value = StoreDescriptor::ValueRegister(); | 732 Register value = Descriptor::ValueRegister(); |
| 740 Register vector = StoreWithVectorDescriptor::VectorRegister(); | 733 // Since the slot and vector values are passed on the stack we can use |
| 741 Register slot = StoreWithVectorDescriptor::SlotRegister(); | 734 // respective registers as scratch registers. |
| 735 Register scratch1 = Descriptor::VectorRegister(); |
| 736 Register scratch2 = Descriptor::SlotRegister(); |
| 742 | 737 |
| 743 // A lot of registers are needed for storing to slow case | 738 __ LoadParameterFromStack<Descriptor>(value, Descriptor::kValue); |
| 744 // objects. Push and restore receiver but rely on | 739 |
| 745 // GenerateDictionaryStore preserving the value and name. | 740 // A lot of registers are needed for storing to slow case objects. |
| 741 // Push and restore receiver but rely on GenerateDictionaryStore preserving |
| 742 // the value and name. |
| 746 __ push(receiver); | 743 __ push(receiver); |
| 747 __ push(vector); | |
| 748 __ push(slot); | |
| 749 | 744 |
| 750 Register dictionary = ebx; | 745 Register dictionary = receiver; |
| 751 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 746 __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 752 GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, | 747 GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, |
| 753 receiver, edi); | 748 scratch1, scratch2); |
| 754 __ Drop(3); | 749 __ Drop(1); |
| 755 Counters* counters = masm->isolate()->counters(); | 750 Counters* counters = masm->isolate()->counters(); |
| 756 __ IncrementCounter(counters->ic_store_normal_hit(), 1); | 751 __ IncrementCounter(counters->ic_store_normal_hit(), 1); |
| 757 __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); | 752 __ ret(Descriptor::kStackArgumentsCount * kPointerSize); |
| 758 | 753 |
| 759 __ bind(&restore_miss); | 754 __ bind(&restore_miss); |
| 760 __ pop(slot); | |
| 761 __ pop(vector); | |
| 762 __ pop(receiver); | 755 __ pop(receiver); |
| 763 __ IncrementCounter(counters->ic_store_normal_miss(), 1); | 756 __ IncrementCounter(counters->ic_store_normal_miss(), 1); |
| 764 GenerateMiss(masm); | 757 GenerateMiss(masm); |
| 765 } | 758 } |
| 766 | 759 |
| 767 | 760 |
| 768 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 761 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 769 // Return address is on the stack. | 762 // Return address is on the stack. |
| 770 StoreIC_PushArgs(masm); | 763 StoreIC_PushArgs(masm); |
| 771 | 764 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 Condition cc = | 843 Condition cc = |
| 851 (check == ENABLE_INLINED_SMI_CHECK) | 844 (check == ENABLE_INLINED_SMI_CHECK) |
| 852 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 845 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 853 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 846 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 854 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 847 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 855 } | 848 } |
| 856 } // namespace internal | 849 } // namespace internal |
| 857 } // namespace v8 | 850 } // namespace v8 |
| 858 | 851 |
| 859 #endif // V8_TARGET_ARCH_X87 | 852 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |