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 |