| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 // structure. Cache the Context pointer in the CTX register so that it is | 738 // structure. Cache the Context pointer in the CTX register so that it is |
| 739 // available in generated code and calls to Isolate::Current() need not be | 739 // available in generated code and calls to Isolate::Current() need not be |
| 740 // done. The assumption is that this register will never be clobbered by | 740 // done. The assumption is that this register will never be clobbered by |
| 741 // compiled or runtime stub code. | 741 // compiled or runtime stub code. |
| 742 | 742 |
| 743 // Cache the new Context pointer into CTX while executing Dart code. | 743 // Cache the new Context pointer into CTX while executing Dart code. |
| 744 __ movq(CTX, Address(kNewContextReg, VMHandles::kOffsetOfRawPtrInHandle)); | 744 __ movq(CTX, Address(kNewContextReg, VMHandles::kOffsetOfRawPtrInHandle)); |
| 745 | 745 |
| 746 const Register kIsolateReg = RBX; | 746 const Register kIsolateReg = RBX; |
| 747 | 747 |
| 748 // Load Isolate pointer from Context structure into R8. | 748 // Load Isolate pointer into kIsolateReg. |
| 749 __ movq(kIsolateReg, FieldAddress(CTX, Context::isolate_offset())); | 749 __ movq(kIsolateReg, Immediate(Isolate::CurrentAddress())); |
| 750 | 750 |
| 751 // Save the current VMTag on the stack. | 751 // Save the current VMTag on the stack. |
| 752 __ movq(RAX, Address(kIsolateReg, Isolate::vm_tag_offset())); | 752 __ movq(RAX, Address(kIsolateReg, Isolate::vm_tag_offset())); |
| 753 __ pushq(RAX); | 753 __ pushq(RAX); |
| 754 #if defined(DEBUG) | 754 #if defined(DEBUG) |
| 755 { | 755 { |
| 756 Label ok; | 756 Label ok; |
| 757 __ leaq(RAX, Address(RBP, kSavedVMTagSlotFromEntryFp * kWordSize)); | 757 __ leaq(RAX, Address(RBP, kSavedVMTagSlotFromEntryFp * kWordSize)); |
| 758 __ cmpq(RAX, RSP); | 758 __ cmpq(RAX, RSP); |
| 759 __ j(EQUAL, &ok); | 759 __ j(EQUAL, &ok); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 __ movq(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); | 841 __ movq(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 842 | 842 |
| 843 // Read the saved arguments descriptor array to obtain the number of passed | 843 // Read the saved arguments descriptor array to obtain the number of passed |
| 844 // arguments. | 844 // arguments. |
| 845 __ movq(kArgDescReg, Address(RBP, kArgumentsDescOffset)); | 845 __ movq(kArgDescReg, Address(RBP, kArgumentsDescOffset)); |
| 846 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle)); | 846 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle)); |
| 847 __ movq(RDX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 847 __ movq(RDX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 848 // Get rid of arguments pushed on the stack. | 848 // Get rid of arguments pushed on the stack. |
| 849 __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi. | 849 __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi. |
| 850 | 850 |
| 851 // Load Isolate pointer from Context structure into CTX. Drop Context. | 851 __ movq(kIsolateReg, Immediate(Isolate::CurrentAddress())); |
| 852 __ movq(kIsolateReg, FieldAddress(CTX, Context::isolate_offset())); | |
| 853 | |
| 854 // Restore the saved Context pointer into the Isolate structure. | 852 // Restore the saved Context pointer into the Isolate structure. |
| 855 __ popq(RDX); | 853 __ popq(Address(kIsolateReg, Isolate::top_context_offset())); |
| 856 __ movq(Address(kIsolateReg, Isolate::top_context_offset()), RDX); | |
| 857 | 854 |
| 858 // Restore the saved top exit frame info back into the Isolate structure. | 855 // Restore the saved top exit frame info back into the Isolate structure. |
| 859 __ popq(RDX); | 856 __ popq(Address(kIsolateReg, Isolate::top_exit_frame_info_offset())); |
| 860 __ movq(Address(kIsolateReg, Isolate::top_exit_frame_info_offset()), RDX); | |
| 861 | 857 |
| 862 // Restore the current VMTag from the stack. | 858 // Restore the current VMTag from the stack. |
| 863 __ popq(RDX); | 859 __ popq(Address(kIsolateReg, Isolate::vm_tag_offset())); |
| 864 __ movq(Address(kIsolateReg, Isolate::vm_tag_offset()), RDX); | |
| 865 | 860 |
| 866 // Restore C++ ABI callee-saved registers. | 861 // Restore C++ ABI callee-saved registers. |
| 867 __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters, | 862 __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters, |
| 868 CallingConventions::kCalleeSaveXmmRegisters); | 863 CallingConventions::kCalleeSaveXmmRegisters); |
| 869 | 864 |
| 870 // Restore the frame pointer. | 865 // Restore the frame pointer. |
| 871 __ LeaveFrame(); | 866 __ LeaveFrame(); |
| 872 | 867 |
| 873 __ ret(); | 868 __ ret(); |
| 874 } | 869 } |
| 875 | 870 |
| 876 | 871 |
| 877 // Called for inline allocation of contexts. | 872 // Called for inline allocation of contexts. |
| 878 // Input: | 873 // Input: |
| 879 // R10: number of context variables. | 874 // R10: number of context variables. |
| 880 // Output: | 875 // Output: |
| 881 // RAX: new allocated RawContext object. | 876 // RAX: new allocated RawContext object. |
| 882 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 877 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 883 __ LoadObject(R12, Object::null_object(), PP); | 878 __ LoadObject(R12, Object::null_object(), PP); |
| 884 if (FLAG_inline_alloc) { | 879 if (FLAG_inline_alloc) { |
| 885 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 880 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 886 Label slow_case; | 881 Label slow_case; |
| 887 Heap* heap = Isolate::Current()->heap(); | 882 Isolate* isolate = Isolate::Current(); |
| 883 Heap* heap = isolate->heap(); |
| 888 // First compute the rounded instance size. | 884 // First compute the rounded instance size. |
| 889 // R10: number of context variables. | 885 // R10: number of context variables. |
| 890 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); | 886 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
| 891 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); | 887 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
| 892 __ andq(R13, Immediate(-kObjectAlignment)); | 888 __ andq(R13, Immediate(-kObjectAlignment)); |
| 893 | 889 |
| 894 // Now allocate the object. | 890 // Now allocate the object. |
| 895 // R10: number of context variables. | 891 // R10: number of context variables. |
| 896 __ movq(RAX, Immediate(heap->TopAddress())); | 892 __ movq(RAX, Immediate(heap->TopAddress())); |
| 897 __ movq(RAX, Address(RAX, 0)); | 893 __ movq(RAX, Address(RAX, 0)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 944 Immediate(RawObject::ClassIdTag::encode(context_class.id()))); | 940 Immediate(RawObject::ClassIdTag::encode(context_class.id()))); |
| 945 __ movq(FieldAddress(RAX, Context::tags_offset()), R13); // Tags. | 941 __ movq(FieldAddress(RAX, Context::tags_offset()), R13); // Tags. |
| 946 } | 942 } |
| 947 | 943 |
| 948 // Setup up number of context variables field. | 944 // Setup up number of context variables field. |
| 949 // RAX: new object. | 945 // RAX: new object. |
| 950 // R10: number of context variables as integer value (not object). | 946 // R10: number of context variables as integer value (not object). |
| 951 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); | 947 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); |
| 952 | 948 |
| 953 // Setup isolate field. | 949 // Setup isolate field. |
| 954 // Load Isolate pointer from Context structure into R13. | |
| 955 // RAX: new object. | 950 // RAX: new object. |
| 956 // R10: number of context variables. | 951 // R10: number of context variables. |
| 957 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); | |
| 958 // R13: Isolate, not an object. | 952 // R13: Isolate, not an object. |
| 959 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); | 953 __ movq(FieldAddress(RAX, Context::isolate_offset()), |
| 954 Immediate(Isolate::CurrentAddress())); |
| 960 | 955 |
| 961 // Setup the parent field. | 956 // Setup the parent field. |
| 962 // RAX: new object. | 957 // RAX: new object. |
| 963 // R10: number of context variables. | 958 // R10: number of context variables. |
| 964 __ movq(FieldAddress(RAX, Context::parent_offset()), R12); | 959 __ movq(FieldAddress(RAX, Context::parent_offset()), R12); |
| 965 | 960 |
| 966 // Initialize the context variables. | 961 // Initialize the context variables. |
| 967 // RAX: new object. | 962 // RAX: new object. |
| 968 // R10: number of context variables. | 963 // R10: number of context variables. |
| 969 { | 964 { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1019 __ testq(RCX, Immediate(1 << RawObject::kRememberedBit)); | 1014 __ testq(RCX, Immediate(1 << RawObject::kRememberedBit)); |
| 1020 __ j(EQUAL, &add_to_buffer, Assembler::kNearJump); | 1015 __ j(EQUAL, &add_to_buffer, Assembler::kNearJump); |
| 1021 __ popq(RCX); | 1016 __ popq(RCX); |
| 1022 __ popq(RDX); | 1017 __ popq(RDX); |
| 1023 __ ret(); | 1018 __ ret(); |
| 1024 | 1019 |
| 1025 __ Bind(&add_to_buffer); | 1020 __ Bind(&add_to_buffer); |
| 1026 __ orq(RCX, Immediate(1 << RawObject::kRememberedBit)); | 1021 __ orq(RCX, Immediate(1 << RawObject::kRememberedBit)); |
| 1027 __ movq(FieldAddress(RAX, Object::tags_offset()), RCX); | 1022 __ movq(FieldAddress(RAX, Object::tags_offset()), RCX); |
| 1028 | 1023 |
| 1029 // Load the isolate out of the context. | 1024 // Load the isolate. |
| 1030 // RAX: Address being stored | 1025 // RAX: Address being stored |
| 1031 __ movq(RDX, FieldAddress(CTX, Context::isolate_offset())); | 1026 __ movq(RDX, Immediate(Isolate::CurrentAddress())); |
| 1032 | 1027 |
| 1033 // Load the StoreBuffer block out of the isolate. Then load top_ out of the | 1028 // Load the StoreBuffer block out of the isolate. Then load top_ out of the |
| 1034 // StoreBufferBlock and add the address to the pointers_. | 1029 // StoreBufferBlock and add the address to the pointers_. |
| 1035 // RAX: Address being stored | 1030 // RAX: Address being stored |
| 1036 // RDX: Isolate | 1031 // RDX: Isolate |
| 1037 __ movq(RDX, Address(RDX, Isolate::store_buffer_offset())); | 1032 __ movq(RDX, Address(RDX, Isolate::store_buffer_offset())); |
| 1038 __ movl(RCX, Address(RDX, StoreBufferBlock::top_offset())); | 1033 __ movl(RCX, Address(RDX, StoreBufferBlock::top_offset())); |
| 1039 __ movq(Address(RDX, RCX, TIMES_8, StoreBufferBlock::pointers_offset()), RAX); | 1034 __ movq(Address(RDX, RCX, TIMES_8, StoreBufferBlock::pointers_offset()), RAX); |
| 1040 | 1035 |
| 1041 // Increment top_ and check for overflow. | 1036 // Increment top_ and check for overflow. |
| 1042 // RCX: top_ | 1037 // RCX: top_ |
| 1043 // RDX: StoreBufferBlock | 1038 // RDX: StoreBufferBlock |
| 1044 Label L; | 1039 Label L; |
| 1045 __ incq(RCX); | 1040 __ incq(RCX); |
| 1046 __ movl(Address(RDX, StoreBufferBlock::top_offset()), RCX); | 1041 __ movl(Address(RDX, StoreBufferBlock::top_offset()), RCX); |
| 1047 __ cmpl(RCX, Immediate(StoreBufferBlock::kSize)); | 1042 __ cmpl(RCX, Immediate(StoreBufferBlock::kSize)); |
| 1048 // Restore values. | 1043 // Restore values. |
| 1049 __ popq(RCX); | 1044 __ popq(RCX); |
| 1050 __ popq(RDX); | 1045 __ popq(RDX); |
| 1051 __ j(EQUAL, &L, Assembler::kNearJump); | 1046 __ j(EQUAL, &L, Assembler::kNearJump); |
| 1052 __ ret(); | 1047 __ ret(); |
| 1053 | 1048 |
| 1054 // Handle overflow: Call the runtime leaf function. | 1049 // Handle overflow: Call the runtime leaf function. |
| 1055 __ Bind(&L); | 1050 __ Bind(&L); |
| 1056 // Setup frame, push callee-saved registers. | 1051 // Setup frame, push callee-saved registers. |
| 1057 __ EnterCallRuntimeFrame(0); | 1052 __ EnterCallRuntimeFrame(0); |
| 1058 __ movq(CallingConventions::kArg1Reg, | 1053 __ movq(CallingConventions::kArg1Reg, Immediate(Isolate::CurrentAddress())); |
| 1059 FieldAddress(CTX, Context::isolate_offset())); | |
| 1060 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); | 1054 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); |
| 1061 __ LeaveCallRuntimeFrame(); | 1055 __ LeaveCallRuntimeFrame(); |
| 1062 __ ret(); | 1056 __ ret(); |
| 1063 } | 1057 } |
| 1064 | 1058 |
| 1065 | 1059 |
| 1066 // Called for inline allocation of objects. | 1060 // Called for inline allocation of objects. |
| 1067 // Input parameters: | 1061 // Input parameters: |
| 1068 // RSP + 8 : type arguments object (only if class is parameterized). | 1062 // RSP + 8 : type arguments object (only if class is parameterized). |
| 1069 // RSP : points to return address. | 1063 // RSP : points to return address. |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); | 1346 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); |
| 1353 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1347 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1354 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); | 1348 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); |
| 1355 __ cmpq(RCX, Immediate(num_args)); | 1349 __ cmpq(RCX, Immediate(num_args)); |
| 1356 __ j(EQUAL, &ok, Assembler::kNearJump); | 1350 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1357 __ Stop("Incorrect stub for IC data"); | 1351 __ Stop("Incorrect stub for IC data"); |
| 1358 __ Bind(&ok); | 1352 __ Bind(&ok); |
| 1359 } | 1353 } |
| 1360 #endif // DEBUG | 1354 #endif // DEBUG |
| 1361 | 1355 |
| 1356 // Check single stepping. |
| 1362 Label stepping, done_stepping; | 1357 Label stepping, done_stepping; |
| 1363 // Check single stepping. | 1358 __ movq(RAX, Immediate(Isolate::CurrentAddress())); |
| 1364 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | |
| 1365 __ cmpb(Address(RAX, Isolate::single_step_offset()), Immediate(0)); | 1359 __ cmpb(Address(RAX, Isolate::single_step_offset()), Immediate(0)); |
| 1366 __ j(NOT_EQUAL, &stepping); | 1360 __ j(NOT_EQUAL, &stepping); |
| 1367 __ Bind(&done_stepping); | 1361 __ Bind(&done_stepping); |
| 1368 | 1362 |
| 1369 if (kind != Token::kILLEGAL) { | 1363 if (kind != Token::kILLEGAL) { |
| 1370 Label not_smi_or_overflow; | 1364 Label not_smi_or_overflow; |
| 1371 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1365 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
| 1372 __ Bind(¬_smi_or_overflow); | 1366 __ Bind(¬_smi_or_overflow); |
| 1373 } | 1367 } |
| 1374 | 1368 |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1585 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); | 1579 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); |
| 1586 __ cmpq(RCX, Immediate(0)); | 1580 __ cmpq(RCX, Immediate(0)); |
| 1587 __ j(EQUAL, &ok, Assembler::kNearJump); | 1581 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1588 __ Stop("Incorrect IC data for unoptimized static call"); | 1582 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1589 __ Bind(&ok); | 1583 __ Bind(&ok); |
| 1590 } | 1584 } |
| 1591 #endif // DEBUG | 1585 #endif // DEBUG |
| 1592 | 1586 |
| 1593 // Check single stepping. | 1587 // Check single stepping. |
| 1594 Label stepping, done_stepping; | 1588 Label stepping, done_stepping; |
| 1595 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 1589 __ movq(RAX, Immediate(Isolate::CurrentAddress())); |
| 1596 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1590 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
| 1597 __ cmpq(RAX, Immediate(0)); | 1591 __ cmpq(RAX, Immediate(0)); |
| 1598 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); | 1592 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); |
| 1599 __ Bind(&done_stepping); | 1593 __ Bind(&done_stepping); |
| 1600 | 1594 |
| 1601 // RBX: IC data object (preserved). | 1595 // RBX: IC data object (preserved). |
| 1602 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); | 1596 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
| 1603 // R12: ic_data_array with entries: target functions and count. | 1597 // R12: ic_data_array with entries: target functions and count. |
| 1604 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1598 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
| 1605 // R12: points directly to the first ic data array element. | 1599 // R12: points directly to the first ic data array element. |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2027 | 2021 |
| 2028 __ movq(left, Address(RSP, 2 * kWordSize)); | 2022 __ movq(left, Address(RSP, 2 * kWordSize)); |
| 2029 __ movq(right, Address(RSP, 1 * kWordSize)); | 2023 __ movq(right, Address(RSP, 1 * kWordSize)); |
| 2030 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2024 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
| 2031 __ ret(); | 2025 __ ret(); |
| 2032 } | 2026 } |
| 2033 | 2027 |
| 2034 } // namespace dart | 2028 } // namespace dart |
| 2035 | 2029 |
| 2036 #endif // defined TARGET_ARCH_X64 | 2030 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |