OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 | 420 |
421 | 421 |
422 Object* StoreStubCompiler::CompileStoreCallback(JSObject* a, | 422 Object* StoreStubCompiler::CompileStoreCallback(JSObject* a, |
423 AccessorInfo* b, | 423 AccessorInfo* b, |
424 String* c) { | 424 String* c) { |
425 UNIMPLEMENTED(); | 425 UNIMPLEMENTED(); |
426 return NULL; | 426 return NULL; |
427 } | 427 } |
428 | 428 |
429 | 429 |
430 Object* StoreStubCompiler::CompileStoreField(JSObject* a, | 430 Object* StoreStubCompiler::CompileStoreField(JSObject* object, |
431 int b, | 431 int index, |
432 Map* c, | 432 Map* transition, |
433 String* d) { | 433 String* name) { |
434 UNIMPLEMENTED(); | 434 // ----------- S t a t e ------------- |
435 return NULL; | 435 // -- rax : value |
| 436 // -- rcx : name |
| 437 // -- rsp[0] : return address |
| 438 // -- rsp[8] : receiver |
| 439 // ----------------------------------- |
| 440 Label miss; |
| 441 |
| 442 // Get the object from the stack. |
| 443 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); |
| 444 |
| 445 // Generate store field code. Trashes the name register. |
| 446 GenerateStoreField(masm(), |
| 447 Builtins::StoreIC_ExtendStorage, |
| 448 object, |
| 449 index, |
| 450 transition, |
| 451 rbx, rcx, rdx, |
| 452 &miss); |
| 453 |
| 454 // Handle store cache miss. |
| 455 __ bind(&miss); |
| 456 __ Move(rcx, Handle<String>(name)); // restore name |
| 457 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); |
| 458 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 459 |
| 460 // Return the generated code. |
| 461 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
436 } | 462 } |
437 | 463 |
438 | 464 |
439 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* a, String* b) { | 465 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* a, String* b) { |
440 UNIMPLEMENTED(); | 466 UNIMPLEMENTED(); |
441 return NULL; | 467 return NULL; |
442 } | 468 } |
443 | 469 |
444 | 470 |
445 Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, | 471 Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 | 718 |
693 // Probe the secondary table. | 719 // Probe the secondary table. |
694 ProbeTable(masm, flags, kSecondary, name, scratch); | 720 ProbeTable(masm, flags, kSecondary, name, scratch); |
695 | 721 |
696 // Cache miss: Fall-through and let caller handle the miss by | 722 // Cache miss: Fall-through and let caller handle the miss by |
697 // entering the runtime system. | 723 // entering the runtime system. |
698 __ bind(&miss); | 724 __ bind(&miss); |
699 } | 725 } |
700 | 726 |
701 | 727 |
| 728 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 729 Builtins::Name storage_extend, |
| 730 JSObject* object, |
| 731 int index, |
| 732 Map* transition, |
| 733 Register receiver_reg, |
| 734 Register name_reg, |
| 735 Register scratch, |
| 736 Label* miss_label) { |
| 737 // Check that the object isn't a smi. |
| 738 __ testl(receiver_reg, Immediate(kSmiTagMask)); |
| 739 __ j(zero, miss_label); |
| 740 |
| 741 // Check that the map of the object hasn't changed. |
| 742 __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 743 Handle<Map>(object->map())); |
| 744 __ j(not_equal, miss_label); |
| 745 |
| 746 // Perform global security token check if needed. |
| 747 if (object->IsJSGlobalProxy()) { |
| 748 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 749 } |
| 750 |
| 751 // Stub never generated for non-global objects that require access |
| 752 // checks. |
| 753 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 754 |
| 755 // Perform map transition for the receiver if necessary. |
| 756 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { |
| 757 // The properties must be extended before we can store the value. |
| 758 // We jump to a runtime call that extends the properties array. |
| 759 __ Move(rcx, Handle<Map>(transition)); |
| 760 Handle<Code> ic(Builtins::builtin(storage_extend)); |
| 761 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 762 return; |
| 763 } |
| 764 |
| 765 if (transition != NULL) { |
| 766 // Update the map of the object; no write barrier updating is |
| 767 // needed because the map is never in new space. |
| 768 __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 769 Handle<Map>(transition)); |
| 770 } |
| 771 |
| 772 // Adjust for the number of properties stored in the object. Even in the |
| 773 // face of a transition we can use the old map here because the size of the |
| 774 // object and the number of in-object properties is not going to change. |
| 775 index -= object->map()->inobject_properties(); |
| 776 |
| 777 if (index < 0) { |
| 778 // Set the property straight into the object. |
| 779 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 780 __ movq(FieldOperand(receiver_reg, offset), rax); |
| 781 |
| 782 // Update the write barrier for the array address. |
| 783 // Pass the value being stored in the now unused name_reg. |
| 784 __ movq(name_reg, rax); |
| 785 __ RecordWrite(receiver_reg, offset, name_reg, scratch); |
| 786 } else { |
| 787 // Write to the properties array. |
| 788 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 789 // Get the properties array (optimistically). |
| 790 __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 791 __ movq(FieldOperand(scratch, offset), rax); |
| 792 |
| 793 // Update the write barrier for the array address. |
| 794 // Pass the value being stored in the now unused name_reg. |
| 795 __ movq(name_reg, rax); |
| 796 __ RecordWrite(scratch, offset, name_reg, receiver_reg); |
| 797 } |
| 798 |
| 799 // Return the value (register rax). |
| 800 __ ret(0); |
| 801 } |
| 802 |
| 803 |
702 #undef __ | 804 #undef __ |
703 | 805 |
704 | 806 |
705 } } // namespace v8::internal | 807 } } // namespace v8::internal |
OLD | NEW |