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 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 Register receiver, | 336 Register receiver, |
337 Register result, | 337 Register result, |
338 Register scratch, | 338 Register scratch, |
339 Label* miss_label) { | 339 Label* miss_label) { |
340 __ TryGetFunctionPrototype(receiver, result, miss_label); | 340 __ TryGetFunctionPrototype(receiver, result, miss_label); |
341 if (!result.is(rax)) __ movq(rax, result); | 341 if (!result.is(rax)) __ movq(rax, result); |
342 __ ret(0); | 342 __ ret(0); |
343 } | 343 } |
344 | 344 |
345 | 345 |
346 // Load a fast property out of a holder object (src). In-object properties | |
347 // are loaded directly otherwise the property is loaded from the properties | |
348 // fixed array. | |
349 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | |
350 Register dst, | |
351 Register src, | |
352 Handle<JSObject> holder, | |
353 PropertyIndex index) { | |
354 DoGenerateFastPropertyLoad( | |
355 masm, dst, src, index.is_inobject(holder), index.translate(holder)); | |
356 } | |
357 | |
358 | |
359 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, | 346 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, |
360 Register dst, | 347 Register dst, |
361 Register src, | 348 Register src, |
362 bool inobject, | 349 bool inobject, |
363 int index) { | 350 int index) { |
364 int offset = index * kPointerSize; | 351 int offset = index * kPointerSize; |
365 if (!inobject) { | 352 if (!inobject) { |
366 // Calculate the offset into the properties array. | 353 // Calculate the offset into the properties array. |
367 offset = offset + FixedArray::kHeaderSize; | 354 offset = offset + FixedArray::kHeaderSize; |
368 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 355 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 __ j(not_equal, interceptor_succeeded); | 695 __ j(not_equal, interceptor_succeeded); |
709 } | 696 } |
710 | 697 |
711 StubCompiler* stub_compiler_; | 698 StubCompiler* stub_compiler_; |
712 const ParameterCount& arguments_; | 699 const ParameterCount& arguments_; |
713 Register name_; | 700 Register name_; |
714 Code::ExtraICState extra_ic_state_; | 701 Code::ExtraICState extra_ic_state_; |
715 }; | 702 }; |
716 | 703 |
717 | 704 |
718 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 705 void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
719 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 706 Label* label, |
720 Handle<Code> code = (kind == Code::LOAD_IC) | 707 Handle<Name> name) { |
721 ? masm->isolate()->builtins()->LoadIC_Miss() | 708 if (!label->is_unused()) { |
722 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); | 709 __ bind(label); |
723 __ Jump(code, RelocInfo::CODE_TARGET); | 710 __ Move(this->name(), name); |
| 711 } |
724 } | 712 } |
725 | 713 |
726 | 714 |
727 void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) { | |
728 ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC); | |
729 Handle<Code> code = (kind == Code::STORE_IC) | |
730 ? masm->isolate()->builtins()->StoreIC_Miss() | |
731 : masm->isolate()->builtins()->KeyedStoreIC_Miss(); | |
732 __ Jump(code, RelocInfo::CODE_TARGET); | |
733 } | |
734 | |
735 | |
736 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { | |
737 Handle<Code> code = | |
738 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
739 __ Jump(code, RelocInfo::CODE_TARGET); | |
740 } | |
741 | |
742 | |
743 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 715 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
744 // but may be destroyed if store is successful. | 716 // but may be destroyed if store is successful. |
745 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 717 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
746 Handle<JSObject> object, | 718 Handle<JSObject> object, |
747 int index, | 719 int index, |
748 Handle<Map> transition, | 720 Handle<Map> transition, |
749 Handle<Name> name, | 721 Handle<Name> name, |
750 Register receiver_reg, | 722 Register receiver_reg, |
751 Register name_reg, | 723 Register name_reg, |
| 724 Register value_reg, |
752 Register scratch1, | 725 Register scratch1, |
753 Register scratch2, | 726 Register scratch2, |
754 Label* miss_label) { | 727 Label* miss_label, |
| 728 Label* miss_restore_name) { |
755 LookupResult lookup(masm->isolate()); | 729 LookupResult lookup(masm->isolate()); |
756 object->Lookup(*name, &lookup); | 730 object->Lookup(*name, &lookup); |
757 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { | 731 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { |
758 // In sloppy mode, we could just return the value and be done. However, we | 732 // In sloppy mode, we could just return the value and be done. However, we |
759 // might be in strict mode, where we have to throw. Since we cannot tell, | 733 // might be in strict mode, where we have to throw. Since we cannot tell, |
760 // go into slow case unconditionally. | 734 // go into slow case unconditionally. |
761 __ jmp(miss_label); | 735 __ jmp(miss_label); |
762 return; | 736 return; |
763 } | 737 } |
764 | 738 |
(...skipping 13 matching lines...) Expand all Loading... |
778 JSObject* holder; | 752 JSObject* holder; |
779 if (lookup.IsFound()) { | 753 if (lookup.IsFound()) { |
780 holder = lookup.holder(); | 754 holder = lookup.holder(); |
781 } else { | 755 } else { |
782 // Find the top object. | 756 // Find the top object. |
783 holder = *object; | 757 holder = *object; |
784 do { | 758 do { |
785 holder = JSObject::cast(holder->GetPrototype()); | 759 holder = JSObject::cast(holder->GetPrototype()); |
786 } while (holder->GetPrototype()->IsJSObject()); | 760 } while (holder->GetPrototype()->IsJSObject()); |
787 } | 761 } |
788 // We need an extra register, push | |
789 __ push(name_reg); | |
790 Label miss_pop, done_check; | |
791 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, | 762 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, |
792 scratch1, scratch2, name, &miss_pop); | 763 scratch1, scratch2, name, miss_restore_name); |
793 __ jmp(&done_check); | |
794 __ bind(&miss_pop); | |
795 __ pop(name_reg); | |
796 __ jmp(miss_label); | |
797 __ bind(&done_check); | |
798 __ pop(name_reg); | |
799 } | 764 } |
800 | 765 |
801 // Stub never generated for non-global objects that require access | 766 // Stub never generated for non-global objects that require access |
802 // checks. | 767 // checks. |
803 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 768 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
804 | 769 |
805 // Perform map transition for the receiver if necessary. | 770 // Perform map transition for the receiver if necessary. |
806 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { | 771 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { |
807 // The properties must be extended before we can store the value. | 772 // The properties must be extended before we can store the value. |
808 // We jump to a runtime call that extends the properties array. | 773 // We jump to a runtime call that extends the properties array. |
809 __ pop(scratch1); // Return address. | 774 __ pop(scratch1); // Return address. |
810 __ push(receiver_reg); | 775 __ push(receiver_reg); |
811 __ Push(transition); | 776 __ Push(transition); |
812 __ push(rax); | 777 __ push(value_reg); |
813 __ push(scratch1); | 778 __ push(scratch1); |
814 __ TailCallExternalReference( | 779 __ TailCallExternalReference( |
815 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 780 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
816 masm->isolate()), | 781 masm->isolate()), |
817 3, | 782 3, |
818 1); | 783 1); |
819 return; | 784 return; |
820 } | 785 } |
821 | 786 |
822 if (!transition.is_null()) { | 787 if (!transition.is_null()) { |
(...skipping 13 matching lines...) Expand all Loading... |
836 } | 801 } |
837 | 802 |
838 // Adjust for the number of properties stored in the object. Even in the | 803 // Adjust for the number of properties stored in the object. Even in the |
839 // face of a transition we can use the old map here because the size of the | 804 // face of a transition we can use the old map here because the size of the |
840 // object and the number of in-object properties is not going to change. | 805 // object and the number of in-object properties is not going to change. |
841 index -= object->map()->inobject_properties(); | 806 index -= object->map()->inobject_properties(); |
842 | 807 |
843 if (index < 0) { | 808 if (index < 0) { |
844 // Set the property straight into the object. | 809 // Set the property straight into the object. |
845 int offset = object->map()->instance_size() + (index * kPointerSize); | 810 int offset = object->map()->instance_size() + (index * kPointerSize); |
846 __ movq(FieldOperand(receiver_reg, offset), rax); | 811 __ movq(FieldOperand(receiver_reg, offset), value_reg); |
847 | 812 |
848 // Update the write barrier for the array address. | 813 // Update the write barrier for the array address. |
849 // Pass the value being stored in the now unused name_reg. | 814 // Pass the value being stored in the now unused name_reg. |
850 __ movq(name_reg, rax); | 815 __ movq(name_reg, value_reg); |
851 __ RecordWriteField( | 816 __ RecordWriteField( |
852 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs); | 817 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs); |
853 } else { | 818 } else { |
854 // Write to the properties array. | 819 // Write to the properties array. |
855 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 820 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
856 // Get the properties array (optimistically). | 821 // Get the properties array (optimistically). |
857 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 822 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
858 __ movq(FieldOperand(scratch1, offset), rax); | 823 __ movq(FieldOperand(scratch1, offset), value_reg); |
859 | 824 |
860 // Update the write barrier for the array address. | 825 // Update the write barrier for the array address. |
861 // Pass the value being stored in the now unused name_reg. | 826 // Pass the value being stored in the now unused name_reg. |
862 __ movq(name_reg, rax); | 827 __ movq(name_reg, value_reg); |
863 __ RecordWriteField( | 828 __ RecordWriteField( |
864 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs); | 829 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs); |
865 } | 830 } |
866 | 831 |
867 // Return the value (register rax). | 832 // Return the value (register rax). |
| 833 ASSERT(value_reg.is(rax)); |
868 __ ret(0); | 834 __ ret(0); |
869 } | 835 } |
870 | 836 |
871 | 837 |
872 // Generate code to check that a global property cell is empty. Create | 838 // Generate code to check that a global property cell is empty. Create |
873 // the property cell at compilation time if no cell exists for the | 839 // the property cell at compilation time if no cell exists for the |
874 // property. | 840 // property. |
875 static void GenerateCheckPropertyCell(MacroAssembler* masm, | 841 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
876 Handle<GlobalObject> global, | 842 Handle<GlobalObject> global, |
877 Handle<Name> name, | 843 Handle<Name> name, |
(...skipping 23 matching lines...) Expand all Loading... |
901 GenerateCheckPropertyCell(masm, | 867 GenerateCheckPropertyCell(masm, |
902 Handle<GlobalObject>::cast(current), | 868 Handle<GlobalObject>::cast(current), |
903 name, | 869 name, |
904 scratch, | 870 scratch, |
905 miss); | 871 miss); |
906 } | 872 } |
907 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | 873 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
908 } | 874 } |
909 } | 875 } |
910 | 876 |
| 877 |
| 878 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 879 __ jmp(code, RelocInfo::CODE_TARGET); |
| 880 } |
| 881 |
| 882 |
911 #undef __ | 883 #undef __ |
912 #define __ ACCESS_MASM((masm())) | 884 #define __ ACCESS_MASM((masm())) |
913 | 885 |
914 | 886 |
915 void StubCompiler::GenerateTailCall(Handle<Code> code) { | |
916 __ jmp(code, RelocInfo::CODE_TARGET); | |
917 } | |
918 | |
919 | |
920 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 887 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
921 Register object_reg, | 888 Register object_reg, |
922 Handle<JSObject> holder, | 889 Handle<JSObject> holder, |
923 Register holder_reg, | 890 Register holder_reg, |
924 Register scratch1, | 891 Register scratch1, |
925 Register scratch2, | 892 Register scratch2, |
926 Handle<Name> name, | 893 Handle<Name> name, |
927 int save_at_depth, | 894 int save_at_depth, |
928 Label* miss, | 895 Label* miss, |
929 PrototypeCheckType check) { | 896 PrototypeCheckType check) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 // Return the register containing the holder. | 999 // Return the register containing the holder. |
1033 return reg; | 1000 return reg; |
1034 } | 1001 } |
1035 | 1002 |
1036 | 1003 |
1037 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, | 1004 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
1038 Label* miss) { | 1005 Label* miss) { |
1039 if (!miss->is_unused()) { | 1006 if (!miss->is_unused()) { |
1040 __ jmp(success); | 1007 __ jmp(success); |
1041 __ bind(miss); | 1008 __ bind(miss); |
1042 GenerateLoadMiss(masm(), kind()); | 1009 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1043 } | 1010 } |
1044 } | 1011 } |
1045 | 1012 |
1046 | 1013 |
1047 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1014 Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
1048 Handle<JSObject> object, | 1015 Handle<JSObject> object, |
1049 Register object_reg, | 1016 Register object_reg, |
1050 Handle<JSObject> holder, | 1017 Handle<JSObject> holder, |
1051 Handle<Name> name, | 1018 Handle<Name> name, |
1052 Label* success, | 1019 Label* success, |
(...skipping 1348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2401 // Handle call cache miss. | 2368 // Handle call cache miss. |
2402 __ bind(&miss); | 2369 __ bind(&miss); |
2403 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2370 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
2404 GenerateMissBranch(); | 2371 GenerateMissBranch(); |
2405 | 2372 |
2406 // Return the generated code. | 2373 // Return the generated code. |
2407 return GetCode(Code::NORMAL, name); | 2374 return GetCode(Code::NORMAL, name); |
2408 } | 2375 } |
2409 | 2376 |
2410 | 2377 |
2411 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | |
2412 int index, | |
2413 Handle<Map> transition, | |
2414 Handle<Name> name) { | |
2415 // ----------- S t a t e ------------- | |
2416 // -- rax : value | |
2417 // -- rcx : name | |
2418 // -- rdx : receiver | |
2419 // -- rsp[0] : return address | |
2420 // ----------------------------------- | |
2421 Label miss; | |
2422 | |
2423 // Generate store field code. Preserves receiver and name on jump to miss. | |
2424 GenerateStoreField(masm(), | |
2425 object, | |
2426 index, | |
2427 transition, | |
2428 name, | |
2429 rdx, rcx, rbx, rdi, | |
2430 &miss); | |
2431 | |
2432 // Handle store cache miss. | |
2433 __ bind(&miss); | |
2434 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | |
2435 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2436 | |
2437 // Return the generated code. | |
2438 return GetCode(transition.is_null() | |
2439 ? Code::FIELD | |
2440 : Code::MAP_TRANSITION, name); | |
2441 } | |
2442 | |
2443 | |
2444 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2378 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2445 Handle<Name> name, | 2379 Handle<Name> name, |
2446 Handle<JSObject> receiver, | 2380 Handle<JSObject> receiver, |
2447 Handle<JSObject> holder, | 2381 Handle<JSObject> holder, |
2448 Handle<ExecutableAccessorInfo> callback) { | 2382 Handle<ExecutableAccessorInfo> callback) { |
2449 // ----------- S t a t e ------------- | 2383 // ----------- S t a t e ------------- |
2450 // -- rax : value | 2384 // -- rax : value |
2451 // -- rcx : name | 2385 // -- rcx : name |
2452 // -- rdx : receiver | 2386 // -- rdx : receiver |
2453 // -- rsp[0] : return address | 2387 // -- rsp[0] : return address |
(...skipping 13 matching lines...) Expand all Loading... |
2467 __ push(rax); // value | 2401 __ push(rax); // value |
2468 __ push(rbx); // restore return address | 2402 __ push(rbx); // restore return address |
2469 | 2403 |
2470 // Do tail-call to the runtime system. | 2404 // Do tail-call to the runtime system. |
2471 ExternalReference store_callback_property = | 2405 ExternalReference store_callback_property = |
2472 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2406 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
2473 __ TailCallExternalReference(store_callback_property, 4, 1); | 2407 __ TailCallExternalReference(store_callback_property, 4, 1); |
2474 | 2408 |
2475 // Handle store cache miss. | 2409 // Handle store cache miss. |
2476 __ bind(&miss); | 2410 __ bind(&miss); |
2477 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2411 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2478 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2479 | 2412 |
2480 // Return the generated code. | 2413 // Return the generated code. |
2481 return GetCode(Code::CALLBACKS, name); | 2414 return GetICCode(kind(), Code::CALLBACKS, name); |
2482 } | 2415 } |
2483 | 2416 |
2484 | 2417 |
2485 #undef __ | 2418 #undef __ |
2486 #define __ ACCESS_MASM(masm) | 2419 #define __ ACCESS_MASM(masm) |
2487 | 2420 |
2488 | 2421 |
2489 void StoreStubCompiler::GenerateStoreViaSetter( | 2422 void StoreStubCompiler::GenerateStoreViaSetter( |
2490 MacroAssembler* masm, | 2423 MacroAssembler* masm, |
2491 Handle<JSFunction> setter) { | 2424 Handle<JSFunction> setter) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2541 // ----------------------------------- | 2474 // ----------------------------------- |
2542 Label miss; | 2475 Label miss; |
2543 | 2476 |
2544 // Check that the maps haven't changed. | 2477 // Check that the maps haven't changed. |
2545 __ JumpIfSmi(rdx, &miss); | 2478 __ JumpIfSmi(rdx, &miss); |
2546 CheckPrototypes(receiver, rdx, holder, rbx, r8, rdi, name, &miss); | 2479 CheckPrototypes(receiver, rdx, holder, rbx, r8, rdi, name, &miss); |
2547 | 2480 |
2548 GenerateStoreViaSetter(masm(), setter); | 2481 GenerateStoreViaSetter(masm(), setter); |
2549 | 2482 |
2550 __ bind(&miss); | 2483 __ bind(&miss); |
2551 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2484 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2552 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2553 | 2485 |
2554 // Return the generated code. | 2486 // Return the generated code. |
2555 return GetCode(Code::CALLBACKS, name); | 2487 return GetICCode(kind(), Code::CALLBACKS, name); |
2556 } | 2488 } |
2557 | 2489 |
2558 | 2490 |
2559 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 2491 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
2560 Handle<JSObject> receiver, | 2492 Handle<JSObject> receiver, |
2561 Handle<Name> name) { | 2493 Handle<Name> name) { |
2562 // ----------- S t a t e ------------- | 2494 // ----------- S t a t e ------------- |
2563 // -- rax : value | 2495 // -- rax : value |
2564 // -- rcx : name | 2496 // -- rcx : name |
2565 // -- rdx : receiver | 2497 // -- rdx : receiver |
(...skipping 11 matching lines...) Expand all Loading... |
2577 } | 2509 } |
2578 | 2510 |
2579 // Stub never generated for non-global objects that require access | 2511 // Stub never generated for non-global objects that require access |
2580 // checks. | 2512 // checks. |
2581 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2513 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
2582 | 2514 |
2583 __ pop(rbx); // remove the return address | 2515 __ pop(rbx); // remove the return address |
2584 __ push(rdx); // receiver | 2516 __ push(rdx); // receiver |
2585 __ push(rcx); // name | 2517 __ push(rcx); // name |
2586 __ push(rax); // value | 2518 __ push(rax); // value |
2587 __ Push(Smi::FromInt(strict_mode_)); | 2519 __ Push(Smi::FromInt(strict_mode())); |
2588 __ push(rbx); // restore return address | 2520 __ push(rbx); // restore return address |
2589 | 2521 |
2590 // Do tail-call to the runtime system. | 2522 // Do tail-call to the runtime system. |
2591 ExternalReference store_ic_property = | 2523 ExternalReference store_ic_property = |
2592 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 2524 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
2593 __ TailCallExternalReference(store_ic_property, 4, 1); | 2525 __ TailCallExternalReference(store_ic_property, 4, 1); |
2594 | 2526 |
2595 // Handle store cache miss. | 2527 // Handle store cache miss. |
2596 __ bind(&miss); | 2528 __ bind(&miss); |
2597 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2529 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2598 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2599 | 2530 |
2600 // Return the generated code. | 2531 // Return the generated code. |
2601 return GetCode(Code::INTERCEPTOR, name); | 2532 return GetICCode(kind(), Code::INTERCEPTOR, name); |
2602 } | 2533 } |
2603 | 2534 |
2604 | 2535 |
2605 Handle<Code> StoreStubCompiler::CompileStoreGlobal( | 2536 Handle<Code> StoreStubCompiler::CompileStoreGlobal( |
2606 Handle<GlobalObject> object, | 2537 Handle<GlobalObject> object, |
2607 Handle<JSGlobalPropertyCell> cell, | 2538 Handle<JSGlobalPropertyCell> cell, |
2608 Handle<Name> name) { | 2539 Handle<Name> name) { |
2609 // ----------- S t a t e ------------- | 2540 // ----------- S t a t e ------------- |
2610 // -- rax : value | 2541 // -- rax : value |
2611 // -- rcx : name | 2542 // -- rcx : name |
(...skipping 23 matching lines...) Expand all Loading... |
2635 // Cells are always rescanned, so no write barrier here. | 2566 // Cells are always rescanned, so no write barrier here. |
2636 | 2567 |
2637 // Return the value (register rax). | 2568 // Return the value (register rax). |
2638 Counters* counters = isolate()->counters(); | 2569 Counters* counters = isolate()->counters(); |
2639 __ IncrementCounter(counters->named_store_global_inline(), 1); | 2570 __ IncrementCounter(counters->named_store_global_inline(), 1); |
2640 __ ret(0); | 2571 __ ret(0); |
2641 | 2572 |
2642 // Handle store cache miss. | 2573 // Handle store cache miss. |
2643 __ bind(&miss); | 2574 __ bind(&miss); |
2644 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); | 2575 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
2645 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2576 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2646 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2647 | 2577 |
2648 // Return the generated code. | 2578 // Return the generated code. |
2649 return GetCode(Code::NORMAL, name); | 2579 return GetICCode(kind(), Code::NORMAL, name); |
2650 } | 2580 } |
2651 | 2581 |
2652 | 2582 |
2653 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, | |
2654 int index, | |
2655 Handle<Map> transition, | |
2656 Handle<Name> name) { | |
2657 // ----------- S t a t e ------------- | |
2658 // -- rax : value | |
2659 // -- rcx : key | |
2660 // -- rdx : receiver | |
2661 // -- rsp[0] : return address | |
2662 // ----------------------------------- | |
2663 Label miss; | |
2664 | |
2665 Counters* counters = isolate()->counters(); | |
2666 __ IncrementCounter(counters->keyed_store_field(), 1); | |
2667 | |
2668 // Check that the name has not changed. | |
2669 __ Cmp(rcx, name); | |
2670 __ j(not_equal, &miss); | |
2671 | |
2672 // Generate store field code. Preserves receiver and name on jump to miss. | |
2673 GenerateStoreField(masm(), | |
2674 object, | |
2675 index, | |
2676 transition, | |
2677 name, | |
2678 rdx, rcx, rbx, rdi, | |
2679 &miss); | |
2680 | |
2681 // Handle store cache miss. | |
2682 __ bind(&miss); | |
2683 __ DecrementCounter(counters->keyed_store_field(), 1); | |
2684 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | |
2685 __ Jump(ic, RelocInfo::CODE_TARGET); | |
2686 | |
2687 // Return the generated code. | |
2688 return GetCode(transition.is_null() | |
2689 ? Code::FIELD | |
2690 : Code::MAP_TRANSITION, name); | |
2691 } | |
2692 | |
2693 | |
2694 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( | 2583 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
2695 Handle<Map> receiver_map) { | 2584 Handle<Map> receiver_map) { |
2696 // ----------- S t a t e ------------- | 2585 // ----------- S t a t e ------------- |
2697 // -- rax : value | 2586 // -- rax : value |
2698 // -- rcx : key | 2587 // -- rcx : key |
2699 // -- rdx : receiver | 2588 // -- rdx : receiver |
2700 // -- rsp[0] : return address | 2589 // -- rsp[0] : return address |
2701 // ----------------------------------- | 2590 // ----------------------------------- |
2702 | 2591 |
2703 ElementsKind elements_kind = receiver_map->elements_kind(); | 2592 ElementsKind elements_kind = receiver_map->elements_kind(); |
2704 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2593 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
2705 Handle<Code> stub = | 2594 Handle<Code> stub = |
2706 KeyedStoreElementStub(is_js_array, | 2595 KeyedStoreElementStub(is_js_array, |
2707 elements_kind, | 2596 elements_kind, |
2708 store_mode_).GetCode(isolate()); | 2597 store_mode_).GetCode(isolate()); |
2709 | 2598 |
2710 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); | 2599 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
2711 | 2600 |
2712 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2601 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2713 __ jmp(ic, RelocInfo::CODE_TARGET); | |
2714 | 2602 |
2715 // Return the generated code. | 2603 // Return the generated code. |
2716 return GetCode(Code::NORMAL, factory()->empty_string()); | 2604 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); |
2717 } | 2605 } |
2718 | 2606 |
2719 | 2607 |
2720 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 2608 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
2721 MapHandleList* receiver_maps, | 2609 MapHandleList* receiver_maps, |
2722 CodeHandleList* handler_stubs, | 2610 CodeHandleList* handler_stubs, |
2723 MapHandleList* transitioned_maps) { | 2611 MapHandleList* transitioned_maps) { |
2724 // ----------- S t a t e ------------- | 2612 // ----------- S t a t e ------------- |
2725 // -- rax : value | 2613 // -- rax : value |
2726 // -- rcx : key | 2614 // -- rcx : key |
(...skipping 13 matching lines...) Expand all Loading... |
2740 } else { | 2628 } else { |
2741 Label next_map; | 2629 Label next_map; |
2742 __ j(not_equal, &next_map, Label::kNear); | 2630 __ j(not_equal, &next_map, Label::kNear); |
2743 __ movq(rbx, transitioned_maps->at(i), RelocInfo::EMBEDDED_OBJECT); | 2631 __ movq(rbx, transitioned_maps->at(i), RelocInfo::EMBEDDED_OBJECT); |
2744 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 2632 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
2745 __ bind(&next_map); | 2633 __ bind(&next_map); |
2746 } | 2634 } |
2747 } | 2635 } |
2748 | 2636 |
2749 __ bind(&miss); | 2637 __ bind(&miss); |
2750 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2638 |
2751 __ jmp(ic, RelocInfo::CODE_TARGET); | 2639 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2752 | 2640 |
2753 // Return the generated code. | 2641 // Return the generated code. |
2754 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 2642 return GetICCode( |
| 2643 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
2755 } | 2644 } |
2756 | 2645 |
2757 | 2646 |
2758 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2647 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( |
2759 Handle<JSObject> object, | 2648 Handle<JSObject> object, |
2760 Handle<JSObject> last, | 2649 Handle<JSObject> last, |
2761 Handle<Name> name, | 2650 Handle<Name> name, |
2762 Handle<GlobalObject> global) { | 2651 Handle<GlobalObject> global) { |
2763 Label success; | 2652 Label success; |
2764 | 2653 |
(...skipping 17 matching lines...) Expand all Loading... |
2782 } | 2671 } |
2783 | 2672 |
2784 | 2673 |
2785 Register* KeyedLoadStubCompiler::registers() { | 2674 Register* KeyedLoadStubCompiler::registers() { |
2786 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 2675 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
2787 static Register registers[] = { rdx, rax, rbx, rcx, rdi, r8 }; | 2676 static Register registers[] = { rdx, rax, rbx, rcx, rdi, r8 }; |
2788 return registers; | 2677 return registers; |
2789 } | 2678 } |
2790 | 2679 |
2791 | 2680 |
| 2681 Register* StoreStubCompiler::registers() { |
| 2682 // receiver, name, value, scratch1, scratch2, scratch3. |
| 2683 static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 }; |
| 2684 return registers; |
| 2685 } |
| 2686 |
| 2687 |
| 2688 Register* KeyedStoreStubCompiler::registers() { |
| 2689 // receiver, name, value, scratch1, scratch2, scratch3. |
| 2690 static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 }; |
| 2691 return registers; |
| 2692 } |
| 2693 |
| 2694 |
2792 void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name, | 2695 void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name, |
2793 Register name_reg, | 2696 Register name_reg, |
2794 Label* miss) { | 2697 Label* miss) { |
2795 __ Cmp(name_reg, name); | 2698 __ Cmp(name_reg, name); |
2796 __ j(not_equal, miss); | 2699 __ j(not_equal, miss); |
2797 } | 2700 } |
2798 | 2701 |
2799 | 2702 |
| 2703 void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name, |
| 2704 Register name_reg, |
| 2705 Label* miss) { |
| 2706 __ Cmp(name_reg, name); |
| 2707 __ j(not_equal, miss); |
| 2708 } |
| 2709 |
| 2710 |
2800 #undef __ | 2711 #undef __ |
2801 #define __ ACCESS_MASM(masm) | 2712 #define __ ACCESS_MASM(masm) |
2802 | 2713 |
2803 | 2714 |
2804 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 2715 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, |
2805 Handle<JSFunction> getter) { | 2716 Handle<JSFunction> getter) { |
2806 // ----------- S t a t e ------------- | 2717 // ----------- S t a t e ------------- |
2807 // -- rax : receiver | 2718 // -- rax : receiver |
2808 // -- rcx : name | 2719 // -- rcx : name |
2809 // -- rsp[0] : return address | 2720 // -- rsp[0] : return address |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2888 Handle<Code> stub = KeyedLoadFastElementStub( | 2799 Handle<Code> stub = KeyedLoadFastElementStub( |
2889 receiver_map->instance_type() == JS_ARRAY_TYPE, | 2800 receiver_map->instance_type() == JS_ARRAY_TYPE, |
2890 elements_kind).GetCode(isolate()); | 2801 elements_kind).GetCode(isolate()); |
2891 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); | 2802 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
2892 } else { | 2803 } else { |
2893 Handle<Code> stub = | 2804 Handle<Code> stub = |
2894 KeyedLoadDictionaryElementStub().GetCode(isolate()); | 2805 KeyedLoadDictionaryElementStub().GetCode(isolate()); |
2895 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); | 2806 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
2896 } | 2807 } |
2897 | 2808 |
2898 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2809 TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss); |
2899 | 2810 |
2900 // Return the generated code. | 2811 // Return the generated code. |
2901 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); | 2812 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); |
2902 } | 2813 } |
2903 | 2814 |
2904 | 2815 |
2905 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( | 2816 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
2906 MapHandleList* receiver_maps, | 2817 MapHandleList* receiver_maps, |
2907 CodeHandleList* handlers, | 2818 CodeHandleList* handlers, |
2908 Handle<Name> name, | 2819 Handle<Name> name, |
2909 Code::StubType type, | 2820 Code::StubType type, |
2910 IcCheckType check) { | 2821 IcCheckType check) { |
2911 Label miss; | 2822 Label miss; |
2912 | 2823 |
2913 if (check == PROPERTY) { | 2824 if (check == PROPERTY) { |
2914 GenerateNameCheck(name, this->name(), &miss); | 2825 GenerateNameCheck(name, this->name(), &miss); |
2915 } | 2826 } |
2916 | 2827 |
2917 __ JumpIfSmi(receiver(), &miss); | 2828 __ JumpIfSmi(receiver(), &miss); |
2918 Register map_reg = scratch1(); | 2829 Register map_reg = scratch1(); |
2919 __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | 2830 __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
2920 int receiver_count = receiver_maps->length(); | 2831 int receiver_count = receiver_maps->length(); |
2921 for (int current = 0; current < receiver_count; ++current) { | 2832 for (int current = 0; current < receiver_count; ++current) { |
2922 // Check map and tail call if there's a match | 2833 // Check map and tail call if there's a match |
2923 __ Cmp(map_reg, receiver_maps->at(current)); | 2834 __ Cmp(map_reg, receiver_maps->at(current)); |
2924 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); | 2835 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); |
2925 } | 2836 } |
2926 | 2837 |
2927 __ bind(&miss); | 2838 __ bind(&miss); |
2928 GenerateLoadMiss(masm(), kind()); | 2839 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2929 | 2840 |
2930 // Return the generated code. | 2841 // Return the generated code. |
2931 InlineCacheState state = | 2842 InlineCacheState state = |
2932 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; | 2843 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; |
2933 return GetICCode(kind(), type, name, state); | 2844 return GetICCode(kind(), type, name, state); |
2934 } | 2845 } |
2935 | 2846 |
2936 | 2847 |
2937 // Specialized stub for constructing objects from functions which only have only | 2848 // Specialized stub for constructing objects from functions which only have only |
2938 // simple assignments of the form this.x = ...; in their body. | 2849 // simple assignments of the form this.x = ...; in their body. |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3094 // rcx: elements | 3005 // rcx: elements |
3095 __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); | 3006 __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); |
3096 __ ret(0); | 3007 __ ret(0); |
3097 | 3008 |
3098 __ bind(&slow); | 3009 __ bind(&slow); |
3099 // ----------- S t a t e ------------- | 3010 // ----------- S t a t e ------------- |
3100 // -- rax : key | 3011 // -- rax : key |
3101 // -- rdx : receiver | 3012 // -- rdx : receiver |
3102 // -- rsp[0] : return address | 3013 // -- rsp[0] : return address |
3103 // ----------------------------------- | 3014 // ----------------------------------- |
3104 Handle<Code> slow_ic = | 3015 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
3105 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | |
3106 __ jmp(slow_ic, RelocInfo::CODE_TARGET); | |
3107 | 3016 |
3108 __ bind(&miss_force_generic); | 3017 __ bind(&miss_force_generic); |
3109 // ----------- S t a t e ------------- | 3018 // ----------- S t a t e ------------- |
3110 // -- rax : key | 3019 // -- rax : key |
3111 // -- rdx : receiver | 3020 // -- rdx : receiver |
3112 // -- rsp[0] : return address | 3021 // -- rsp[0] : return address |
3113 // ----------------------------------- | 3022 // ----------------------------------- |
3114 Handle<Code> miss_ic = | 3023 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
3115 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
3116 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
3117 } | 3024 } |
3118 | 3025 |
3119 | 3026 |
3120 static void GenerateSmiKeyCheck(MacroAssembler* masm, | 3027 static void GenerateSmiKeyCheck(MacroAssembler* masm, |
3121 Register key, | 3028 Register key, |
3122 Register scratch, | 3029 Register scratch, |
3123 XMMRegister xmm_scratch0, | 3030 XMMRegister xmm_scratch0, |
3124 XMMRegister xmm_scratch1, | 3031 XMMRegister xmm_scratch1, |
3125 Label* fail) { | 3032 Label* fail) { |
3126 // Check that key is a smi or a heap number containing a smi and branch | 3033 // Check that key is a smi or a heap number containing a smi and branch |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3304 | 3211 |
3305 // Slow case: call runtime. | 3212 // Slow case: call runtime. |
3306 __ bind(&slow); | 3213 __ bind(&slow); |
3307 | 3214 |
3308 // ----------- S t a t e ------------- | 3215 // ----------- S t a t e ------------- |
3309 // -- rax : value | 3216 // -- rax : value |
3310 // -- rcx : key | 3217 // -- rcx : key |
3311 // -- rdx : receiver | 3218 // -- rdx : receiver |
3312 // -- rsp[0] : return address | 3219 // -- rsp[0] : return address |
3313 // ----------------------------------- | 3220 // ----------------------------------- |
3314 | 3221 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3315 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | |
3316 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3317 | 3222 |
3318 // Miss case: call runtime. | 3223 // Miss case: call runtime. |
3319 __ bind(&miss_force_generic); | 3224 __ bind(&miss_force_generic); |
3320 | 3225 |
3321 // ----------- S t a t e ------------- | 3226 // ----------- S t a t e ------------- |
3322 // -- rax : value | 3227 // -- rax : value |
3323 // -- rcx : key | 3228 // -- rcx : key |
3324 // -- rdx : receiver | 3229 // -- rdx : receiver |
3325 // -- rsp[0] : return address | 3230 // -- rsp[0] : return address |
3326 // ----------------------------------- | 3231 // ----------------------------------- |
3327 | 3232 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric); |
3328 Handle<Code> miss_ic = | |
3329 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
3330 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
3331 } | 3233 } |
3332 | 3234 |
3333 | 3235 |
3334 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3236 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3335 MacroAssembler* masm, | 3237 MacroAssembler* masm, |
3336 bool is_js_array, | 3238 bool is_js_array, |
3337 ElementsKind elements_kind, | 3239 ElementsKind elements_kind, |
3338 KeyedAccessStoreMode store_mode) { | 3240 KeyedAccessStoreMode store_mode) { |
3339 // ----------- S t a t e ------------- | 3241 // ----------- S t a t e ------------- |
3340 // -- rax : value | 3242 // -- rax : value |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3389 // Make sure to preserve the value in register rax. | 3291 // Make sure to preserve the value in register rax. |
3390 __ movq(rbx, rax); | 3292 __ movq(rbx, rax); |
3391 __ RecordWrite(rdi, rcx, rbx, kDontSaveFPRegs); | 3293 __ RecordWrite(rdi, rcx, rbx, kDontSaveFPRegs); |
3392 } | 3294 } |
3393 | 3295 |
3394 // Done. | 3296 // Done. |
3395 __ ret(0); | 3297 __ ret(0); |
3396 | 3298 |
3397 // Handle store cache miss. | 3299 // Handle store cache miss. |
3398 __ bind(&miss_force_generic); | 3300 __ bind(&miss_force_generic); |
3399 Handle<Code> ic_force_generic = | 3301 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric); |
3400 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
3401 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | |
3402 | 3302 |
3403 __ bind(&transition_elements_kind); | 3303 __ bind(&transition_elements_kind); |
3404 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3304 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss); |
3405 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | |
3406 | 3305 |
3407 if (is_js_array && IsGrowStoreMode(store_mode)) { | 3306 if (is_js_array && IsGrowStoreMode(store_mode)) { |
3408 // Grow the array by a single element if possible. | 3307 // Grow the array by a single element if possible. |
3409 __ bind(&grow); | 3308 __ bind(&grow); |
3410 | 3309 |
3411 // Make sure the array is only growing by a single element, anything else | 3310 // Make sure the array is only growing by a single element, anything else |
3412 // must be handled by the runtime. Flags are already set by previous | 3311 // must be handled by the runtime. Flags are already set by previous |
3413 // compare. | 3312 // compare. |
3414 __ j(not_equal, &miss_force_generic); | 3313 __ j(not_equal, &miss_force_generic); |
3415 | 3314 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3461 // Make sure that the backing store can hold additional elements. | 3360 // Make sure that the backing store can hold additional elements. |
3462 __ cmpq(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); | 3361 __ cmpq(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); |
3463 __ j(above_equal, &slow); | 3362 __ j(above_equal, &slow); |
3464 | 3363 |
3465 // Grow the array and finish the store. | 3364 // Grow the array and finish the store. |
3466 __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), | 3365 __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), |
3467 Smi::FromInt(1)); | 3366 Smi::FromInt(1)); |
3468 __ jmp(&finish_store); | 3367 __ jmp(&finish_store); |
3469 | 3368 |
3470 __ bind(&slow); | 3369 __ bind(&slow); |
3471 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | 3370 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3472 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | |
3473 } | 3371 } |
3474 } | 3372 } |
3475 | 3373 |
3476 | 3374 |
3477 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( | 3375 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
3478 MacroAssembler* masm, | 3376 MacroAssembler* masm, |
3479 bool is_js_array, | 3377 bool is_js_array, |
3480 KeyedAccessStoreMode store_mode) { | 3378 KeyedAccessStoreMode store_mode) { |
3481 // ----------- S t a t e ------------- | 3379 // ----------- S t a t e ------------- |
3482 // -- rax : value | 3380 // -- rax : value |
(...skipping 29 matching lines...) Expand all Loading... |
3512 | 3410 |
3513 // Handle smi values specially | 3411 // Handle smi values specially |
3514 __ bind(&finish_store); | 3412 __ bind(&finish_store); |
3515 __ SmiToInteger32(rcx, rcx); | 3413 __ SmiToInteger32(rcx, rcx); |
3516 __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, | 3414 __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, |
3517 &restore_key_transition_elements_kind); | 3415 &restore_key_transition_elements_kind); |
3518 __ ret(0); | 3416 __ ret(0); |
3519 | 3417 |
3520 // Handle store cache miss, replacing the ic with the generic stub. | 3418 // Handle store cache miss, replacing the ic with the generic stub. |
3521 __ bind(&miss_force_generic); | 3419 __ bind(&miss_force_generic); |
3522 Handle<Code> ic_force_generic = | 3420 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric); |
3523 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
3524 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | |
3525 | 3421 |
3526 __ bind(&restore_key_transition_elements_kind); | 3422 __ bind(&restore_key_transition_elements_kind); |
3527 // Restore smi-tagging of rcx. | 3423 // Restore smi-tagging of rcx. |
3528 __ Integer32ToSmi(rcx, rcx); | 3424 __ Integer32ToSmi(rcx, rcx); |
3529 __ bind(&transition_elements_kind); | 3425 __ bind(&transition_elements_kind); |
3530 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3426 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss); |
3531 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | |
3532 | 3427 |
3533 if (is_js_array && IsGrowStoreMode(store_mode)) { | 3428 if (is_js_array && IsGrowStoreMode(store_mode)) { |
3534 // Grow the array by a single element if possible. | 3429 // Grow the array by a single element if possible. |
3535 __ bind(&grow); | 3430 __ bind(&grow); |
3536 | 3431 |
3537 // Make sure the array is only growing by a single element, anything else | 3432 // Make sure the array is only growing by a single element, anything else |
3538 // must be handled by the runtime. Flags are already set by previous | 3433 // must be handled by the runtime. Flags are already set by previous |
3539 // compare. | 3434 // compare. |
3540 __ j(not_equal, &miss_force_generic); | 3435 __ j(not_equal, &miss_force_generic); |
3541 | 3436 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3595 // Make sure that the backing store can hold additional elements. | 3490 // Make sure that the backing store can hold additional elements. |
3596 __ cmpq(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); | 3491 __ cmpq(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); |
3597 __ j(above_equal, &slow); | 3492 __ j(above_equal, &slow); |
3598 | 3493 |
3599 // Grow the array and finish the store. | 3494 // Grow the array and finish the store. |
3600 __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), | 3495 __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), |
3601 Smi::FromInt(1)); | 3496 Smi::FromInt(1)); |
3602 __ jmp(&finish_store); | 3497 __ jmp(&finish_store); |
3603 | 3498 |
3604 __ bind(&slow); | 3499 __ bind(&slow); |
3605 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | 3500 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3606 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | |
3607 } | 3501 } |
3608 } | 3502 } |
3609 | 3503 |
3610 | 3504 |
3611 #undef __ | 3505 #undef __ |
3612 | 3506 |
3613 } } // namespace v8::internal | 3507 } } // namespace v8::internal |
3614 | 3508 |
3615 #endif // V8_TARGET_ARCH_X64 | 3509 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |