| 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 |