Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(710)

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 10388047: Implement correct checking for inherited readonliness on assignment. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed Michael's comments. Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/stub-cache.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 713 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 __ Jump(code, RelocInfo::CODE_TARGET); 724 __ Jump(code, RelocInfo::CODE_TARGET);
725 } 725 }
726 726
727 727
728 // Both name_reg and receiver_reg are preserved on jumps to miss_label, 728 // Both name_reg and receiver_reg are preserved on jumps to miss_label,
729 // but may be destroyed if store is successful. 729 // but may be destroyed if store is successful.
730 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 730 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
731 Handle<JSObject> object, 731 Handle<JSObject> object,
732 int index, 732 int index,
733 Handle<Map> transition, 733 Handle<Map> transition,
734 Handle<String> name,
734 Register receiver_reg, 735 Register receiver_reg,
735 Register name_reg, 736 Register name_reg,
736 Register scratch, 737 Register scratch1,
738 Register scratch2,
737 Label* miss_label) { 739 Label* miss_label) {
740 LookupResult lookup(masm->isolate());
741 object->Lookup(*name, &lookup);
742 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
743 // In sloppy mode, we could just return the value and be done. However, we
744 // might be in strict mode, where we have to throw. Since we cannot tell,
745 // go into slow case unconditionally.
746 __ jmp(miss_label);
747 return;
748 }
749
738 // Check that the map of the object hasn't changed. 750 // Check that the map of the object hasn't changed.
739 CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS 751 CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
740 : REQUIRE_EXACT_MAP; 752 : REQUIRE_EXACT_MAP;
741 __ CheckMap(receiver_reg, Handle<Map>(object->map()), 753 __ CheckMap(receiver_reg, Handle<Map>(object->map()),
742 miss_label, DO_SMI_CHECK, mode); 754 miss_label, DO_SMI_CHECK, mode);
743 755
744 // Perform global security token check if needed. 756 // Perform global security token check if needed.
745 if (object->IsJSGlobalProxy()) { 757 if (object->IsJSGlobalProxy()) {
746 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 758 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
759 }
760
761 // Check that we are allowed to write this.
762 if (!transition.is_null() && object->GetPrototype()->IsJSObject()) {
763 JSObject* holder;
764 if (lookup.IsFound()) {
765 holder = lookup.holder();
766 } else {
767 // Find the top object.
768 holder = *object;
769 do {
770 holder = JSObject::cast(holder->GetPrototype());
771 } while (holder->GetPrototype()->IsJSObject());
772 }
773 // We need an extra register, push
774 __ push(name_reg);
775 Label miss_pop, done_check;
776 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
777 scratch1, scratch2, name, &miss_pop);
778 __ jmp(&done_check);
779 __ bind(&miss_pop);
780 __ pop(name_reg);
781 __ jmp(miss_label);
782 __ bind(&done_check);
783 __ pop(name_reg);
747 } 784 }
748 785
749 // Stub never generated for non-global objects that require access 786 // Stub never generated for non-global objects that require access
750 // checks. 787 // checks.
751 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 788 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
752 789
753 // Perform map transition for the receiver if necessary. 790 // Perform map transition for the receiver if necessary.
754 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { 791 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
755 // The properties must be extended before we can store the value. 792 // The properties must be extended before we can store the value.
756 // We jump to a runtime call that extends the properties array. 793 // We jump to a runtime call that extends the properties array.
757 __ pop(scratch); // Return address. 794 __ pop(scratch1); // Return address.
758 __ push(receiver_reg); 795 __ push(receiver_reg);
759 __ Push(transition); 796 __ Push(transition);
760 __ push(rax); 797 __ push(rax);
761 __ push(scratch); 798 __ push(scratch1);
762 __ TailCallExternalReference( 799 __ TailCallExternalReference(
763 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 800 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
764 masm->isolate()), 801 masm->isolate()),
765 3, 802 3,
766 1); 803 1);
767 return; 804 return;
768 } 805 }
769 806
770 if (!transition.is_null()) { 807 if (!transition.is_null()) {
771 // Update the map of the object; no write barrier updating is 808 // Update the map of the object; no write barrier updating is
772 // needed because the map is never in new space. 809 // needed because the map is never in new space.
773 __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset), transition); 810 __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset), transition);
774 } 811 }
775 812
776 // Adjust for the number of properties stored in the object. Even in the 813 // Adjust for the number of properties stored in the object. Even in the
777 // face of a transition we can use the old map here because the size of the 814 // face of a transition we can use the old map here because the size of the
778 // object and the number of in-object properties is not going to change. 815 // object and the number of in-object properties is not going to change.
779 index -= object->map()->inobject_properties(); 816 index -= object->map()->inobject_properties();
780 817
781 if (index < 0) { 818 if (index < 0) {
782 // Set the property straight into the object. 819 // Set the property straight into the object.
783 int offset = object->map()->instance_size() + (index * kPointerSize); 820 int offset = object->map()->instance_size() + (index * kPointerSize);
784 __ movq(FieldOperand(receiver_reg, offset), rax); 821 __ movq(FieldOperand(receiver_reg, offset), rax);
785 822
786 // Update the write barrier for the array address. 823 // Update the write barrier for the array address.
787 // Pass the value being stored in the now unused name_reg. 824 // Pass the value being stored in the now unused name_reg.
788 __ movq(name_reg, rax); 825 __ movq(name_reg, rax);
789 __ RecordWriteField( 826 __ RecordWriteField(
790 receiver_reg, offset, name_reg, scratch, kDontSaveFPRegs); 827 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs);
791 } else { 828 } else {
792 // Write to the properties array. 829 // Write to the properties array.
793 int offset = index * kPointerSize + FixedArray::kHeaderSize; 830 int offset = index * kPointerSize + FixedArray::kHeaderSize;
794 // Get the properties array (optimistically). 831 // Get the properties array (optimistically).
795 __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); 832 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
796 __ movq(FieldOperand(scratch, offset), rax); 833 __ movq(FieldOperand(scratch1, offset), rax);
797 834
798 // Update the write barrier for the array address. 835 // Update the write barrier for the array address.
799 // Pass the value being stored in the now unused name_reg. 836 // Pass the value being stored in the now unused name_reg.
800 __ movq(name_reg, rax); 837 __ movq(name_reg, rax);
801 __ RecordWriteField( 838 __ RecordWriteField(
802 scratch, offset, name_reg, receiver_reg, kDontSaveFPRegs); 839 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs);
803 } 840 }
804 841
805 // Return the value (register rax). 842 // Return the value (register rax).
806 __ ret(0); 843 __ ret(0);
807 } 844 }
808 845
809 846
810 // Generate code to check that a global property cell is empty. Create 847 // Generate code to check that a global property cell is empty. Create
811 // the property cell at compilation time if no cell exists for the 848 // the property cell at compilation time if no cell exists for the
812 // property. 849 // property.
(...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after
2289 Handle<String> name) { 2326 Handle<String> name) {
2290 // ----------- S t a t e ------------- 2327 // ----------- S t a t e -------------
2291 // -- rax : value 2328 // -- rax : value
2292 // -- rcx : name 2329 // -- rcx : name
2293 // -- rdx : receiver 2330 // -- rdx : receiver
2294 // -- rsp[0] : return address 2331 // -- rsp[0] : return address
2295 // ----------------------------------- 2332 // -----------------------------------
2296 Label miss; 2333 Label miss;
2297 2334
2298 // Generate store field code. Preserves receiver and name on jump to miss. 2335 // Generate store field code. Preserves receiver and name on jump to miss.
2299 GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); 2336 GenerateStoreField(masm(),
2337 object,
2338 index,
2339 transition,
2340 name,
2341 rdx, rcx, rbx, rdi,
2342 &miss);
2300 2343
2301 // Handle store cache miss. 2344 // Handle store cache miss.
2302 __ bind(&miss); 2345 __ bind(&miss);
2303 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2346 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2304 __ Jump(ic, RelocInfo::CODE_TARGET); 2347 __ Jump(ic, RelocInfo::CODE_TARGET);
2305 2348
2306 // Return the generated code. 2349 // Return the generated code.
2307 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2350 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2308 } 2351 }
2309 2352
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2462 Label miss; 2505 Label miss;
2463 2506
2464 Counters* counters = isolate()->counters(); 2507 Counters* counters = isolate()->counters();
2465 __ IncrementCounter(counters->keyed_store_field(), 1); 2508 __ IncrementCounter(counters->keyed_store_field(), 1);
2466 2509
2467 // Check that the name has not changed. 2510 // Check that the name has not changed.
2468 __ Cmp(rcx, name); 2511 __ Cmp(rcx, name);
2469 __ j(not_equal, &miss); 2512 __ j(not_equal, &miss);
2470 2513
2471 // Generate store field code. Preserves receiver and name on jump to miss. 2514 // Generate store field code. Preserves receiver and name on jump to miss.
2472 GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); 2515 GenerateStoreField(masm(),
2516 object,
2517 index,
2518 transition,
2519 name,
2520 rdx, rcx, rbx, rdi,
2521 &miss);
2473 2522
2474 // Handle store cache miss. 2523 // Handle store cache miss.
2475 __ bind(&miss); 2524 __ bind(&miss);
2476 __ DecrementCounter(counters->keyed_store_field(), 1); 2525 __ DecrementCounter(counters->keyed_store_field(), 1);
2477 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2526 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2478 __ Jump(ic, RelocInfo::CODE_TARGET); 2527 __ Jump(ic, RelocInfo::CODE_TARGET);
2479 2528
2480 // Return the generated code. 2529 // Return the generated code.
2481 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2530 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name);
2482 } 2531 }
(...skipping 1348 matching lines...) Expand 10 before | Expand all | Expand 10 after
3831 __ jmp(ic_slow, RelocInfo::CODE_TARGET); 3880 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3832 } 3881 }
3833 } 3882 }
3834 3883
3835 3884
3836 #undef __ 3885 #undef __
3837 3886
3838 } } // namespace v8::internal 3887 } } // namespace v8::internal
3839 3888
3840 #endif // V8_TARGET_ARCH_X64 3889 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/stub-cache.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698