OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 __ jmp(code, RelocInfo::CODE_TARGET); | 738 __ jmp(code, RelocInfo::CODE_TARGET); |
739 } | 739 } |
740 | 740 |
741 | 741 |
742 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 742 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
743 // but may be destroyed if store is successful. | 743 // but may be destroyed if store is successful. |
744 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 744 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
745 Handle<JSObject> object, | 745 Handle<JSObject> object, |
746 int index, | 746 int index, |
747 Handle<Map> transition, | 747 Handle<Map> transition, |
| 748 Handle<String> name, |
748 Register receiver_reg, | 749 Register receiver_reg, |
749 Register name_reg, | 750 Register name_reg, |
750 Register scratch, | 751 Register scratch1, |
| 752 Register scratch2, |
751 Label* miss_label) { | 753 Label* miss_label) { |
| 754 LookupResult lookup(masm->isolate()); |
| 755 object->Lookup(*name, &lookup); |
| 756 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { |
| 757 // In sloppy mode, we could just return the value and be done. However, we |
| 758 // might be in strict mode, where we have to throw. Since we cannot tell, |
| 759 // go into slow case unconditionally. |
| 760 __ jmp(miss_label); |
| 761 return; |
| 762 } |
| 763 |
752 // Check that the map of the object hasn't changed. | 764 // Check that the map of the object hasn't changed. |
753 CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS | 765 CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS |
754 : REQUIRE_EXACT_MAP; | 766 : REQUIRE_EXACT_MAP; |
755 __ CheckMap(receiver_reg, Handle<Map>(object->map()), | 767 __ CheckMap(receiver_reg, Handle<Map>(object->map()), |
756 miss_label, DO_SMI_CHECK, mode); | 768 miss_label, DO_SMI_CHECK, mode); |
757 | 769 |
758 // Perform global security token check if needed. | 770 // Perform global security token check if needed. |
759 if (object->IsJSGlobalProxy()) { | 771 if (object->IsJSGlobalProxy()) { |
760 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 772 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); |
| 773 } |
| 774 |
| 775 // Check that we are allowed to write this. |
| 776 if (!transition.is_null() && object->GetPrototype()->IsJSObject()) { |
| 777 JSObject* holder; |
| 778 if (lookup.IsFound()) { |
| 779 holder = lookup.holder(); |
| 780 } else { |
| 781 // Find the top object. |
| 782 holder = *object; |
| 783 do { |
| 784 holder = JSObject::cast(holder->GetPrototype()); |
| 785 } while (holder->GetPrototype()->IsJSObject()); |
| 786 } |
| 787 // We need an extra register, push |
| 788 __ push(name_reg); |
| 789 Label miss_pop, done_check; |
| 790 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, |
| 791 scratch1, scratch2, name, &miss_pop); |
| 792 __ jmp(&done_check); |
| 793 __ bind(&miss_pop); |
| 794 __ pop(name_reg); |
| 795 __ jmp(miss_label); |
| 796 __ bind(&done_check); |
| 797 __ pop(name_reg); |
761 } | 798 } |
762 | 799 |
763 // Stub never generated for non-global objects that require access | 800 // Stub never generated for non-global objects that require access |
764 // checks. | 801 // checks. |
765 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 802 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
766 | 803 |
767 // Perform map transition for the receiver if necessary. | 804 // Perform map transition for the receiver if necessary. |
768 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { | 805 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { |
769 // The properties must be extended before we can store the value. | 806 // The properties must be extended before we can store the value. |
770 // We jump to a runtime call that extends the properties array. | 807 // We jump to a runtime call that extends the properties array. |
771 __ pop(scratch); // Return address. | 808 __ pop(scratch1); // Return address. |
772 __ push(receiver_reg); | 809 __ push(receiver_reg); |
773 __ push(Immediate(transition)); | 810 __ push(Immediate(transition)); |
774 __ push(eax); | 811 __ push(eax); |
775 __ push(scratch); | 812 __ push(scratch1); |
776 __ TailCallExternalReference( | 813 __ TailCallExternalReference( |
777 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 814 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
778 masm->isolate()), | 815 masm->isolate()), |
779 3, | 816 3, |
780 1); | 817 1); |
781 return; | 818 return; |
782 } | 819 } |
783 | 820 |
784 if (!transition.is_null()) { | 821 if (!transition.is_null()) { |
785 // Update the map of the object; no write barrier updating is | 822 // Update the map of the object; no write barrier updating is |
(...skipping 11 matching lines...) Expand all Loading... |
797 // Set the property straight into the object. | 834 // Set the property straight into the object. |
798 int offset = object->map()->instance_size() + (index * kPointerSize); | 835 int offset = object->map()->instance_size() + (index * kPointerSize); |
799 __ mov(FieldOperand(receiver_reg, offset), eax); | 836 __ mov(FieldOperand(receiver_reg, offset), eax); |
800 | 837 |
801 // Update the write barrier for the array address. | 838 // Update the write barrier for the array address. |
802 // Pass the value being stored in the now unused name_reg. | 839 // Pass the value being stored in the now unused name_reg. |
803 __ mov(name_reg, eax); | 840 __ mov(name_reg, eax); |
804 __ RecordWriteField(receiver_reg, | 841 __ RecordWriteField(receiver_reg, |
805 offset, | 842 offset, |
806 name_reg, | 843 name_reg, |
807 scratch, | 844 scratch1, |
808 kDontSaveFPRegs); | 845 kDontSaveFPRegs); |
809 } else { | 846 } else { |
810 // Write to the properties array. | 847 // Write to the properties array. |
811 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 848 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
812 // Get the properties array (optimistically). | 849 // Get the properties array (optimistically). |
813 __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 850 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
814 __ mov(FieldOperand(scratch, offset), eax); | 851 __ mov(FieldOperand(scratch1, offset), eax); |
815 | 852 |
816 // Update the write barrier for the array address. | 853 // Update the write barrier for the array address. |
817 // Pass the value being stored in the now unused name_reg. | 854 // Pass the value being stored in the now unused name_reg. |
818 __ mov(name_reg, eax); | 855 __ mov(name_reg, eax); |
819 __ RecordWriteField(scratch, | 856 __ RecordWriteField(scratch1, |
820 offset, | 857 offset, |
821 name_reg, | 858 name_reg, |
822 receiver_reg, | 859 receiver_reg, |
823 kDontSaveFPRegs); | 860 kDontSaveFPRegs); |
824 } | 861 } |
825 | 862 |
826 // Return the value (register eax). | 863 // Return the value (register eax). |
827 __ ret(0); | 864 __ ret(0); |
828 } | 865 } |
829 | 866 |
(...skipping 1623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2453 Handle<String> name) { | 2490 Handle<String> name) { |
2454 // ----------- S t a t e ------------- | 2491 // ----------- S t a t e ------------- |
2455 // -- eax : value | 2492 // -- eax : value |
2456 // -- ecx : name | 2493 // -- ecx : name |
2457 // -- edx : receiver | 2494 // -- edx : receiver |
2458 // -- esp[0] : return address | 2495 // -- esp[0] : return address |
2459 // ----------------------------------- | 2496 // ----------------------------------- |
2460 Label miss; | 2497 Label miss; |
2461 | 2498 |
2462 // Generate store field code. Trashes the name register. | 2499 // Generate store field code. Trashes the name register. |
2463 GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); | 2500 GenerateStoreField(masm(), |
2464 | 2501 object, |
| 2502 index, |
| 2503 transition, |
| 2504 name, |
| 2505 edx, ecx, ebx, edi, |
| 2506 &miss); |
2465 // Handle store cache miss. | 2507 // Handle store cache miss. |
2466 __ bind(&miss); | 2508 __ bind(&miss); |
2467 __ mov(ecx, Immediate(name)); // restore name | 2509 __ mov(ecx, Immediate(name)); // restore name |
2468 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2510 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
2469 __ jmp(ic, RelocInfo::CODE_TARGET); | 2511 __ jmp(ic, RelocInfo::CODE_TARGET); |
2470 | 2512 |
2471 // Return the generated code. | 2513 // Return the generated code. |
2472 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); | 2514 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
2473 } | 2515 } |
2474 | 2516 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2627 Label miss; | 2669 Label miss; |
2628 | 2670 |
2629 Counters* counters = isolate()->counters(); | 2671 Counters* counters = isolate()->counters(); |
2630 __ IncrementCounter(counters->keyed_store_field(), 1); | 2672 __ IncrementCounter(counters->keyed_store_field(), 1); |
2631 | 2673 |
2632 // Check that the name has not changed. | 2674 // Check that the name has not changed. |
2633 __ cmp(ecx, Immediate(name)); | 2675 __ cmp(ecx, Immediate(name)); |
2634 __ j(not_equal, &miss); | 2676 __ j(not_equal, &miss); |
2635 | 2677 |
2636 // Generate store field code. Trashes the name register. | 2678 // Generate store field code. Trashes the name register. |
2637 GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); | 2679 GenerateStoreField(masm(), |
| 2680 object, |
| 2681 index, |
| 2682 transition, |
| 2683 name, |
| 2684 edx, ecx, ebx, edi, |
| 2685 &miss); |
2638 | 2686 |
2639 // Handle store cache miss. | 2687 // Handle store cache miss. |
2640 __ bind(&miss); | 2688 __ bind(&miss); |
2641 __ DecrementCounter(counters->keyed_store_field(), 1); | 2689 __ DecrementCounter(counters->keyed_store_field(), 1); |
2642 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2690 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2643 __ jmp(ic, RelocInfo::CODE_TARGET); | 2691 __ jmp(ic, RelocInfo::CODE_TARGET); |
2644 | 2692 |
2645 // Return the generated code. | 2693 // Return the generated code. |
2646 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); | 2694 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
2647 } | 2695 } |
(...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4081 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4129 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
4082 } | 4130 } |
4083 } | 4131 } |
4084 | 4132 |
4085 | 4133 |
4086 #undef __ | 4134 #undef __ |
4087 | 4135 |
4088 } } // namespace v8::internal | 4136 } } // namespace v8::internal |
4089 | 4137 |
4090 #endif // V8_TARGET_ARCH_IA32 | 4138 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |