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 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 __ JmpPatchable(&stub_code->FixAllocateArrayStubTargetLabel(), new_pp); | 694 __ JmpPatchable(&stub_code->FixAllocateArrayStubTargetLabel(), new_pp); |
695 } | 695 } |
696 | 696 |
697 | 697 |
698 // Called when invoking Dart code from C++ (VM code). | 698 // Called when invoking Dart code from C++ (VM code). |
699 // Input parameters: | 699 // Input parameters: |
700 // RSP : points to return address. | 700 // RSP : points to return address. |
701 // RDI : entrypoint of the Dart function to call. | 701 // RDI : entrypoint of the Dart function to call. |
702 // RSI : arguments descriptor array. | 702 // RSI : arguments descriptor array. |
703 // RDX : arguments array. | 703 // RDX : arguments array. |
704 // RCX : new context containing the current isolate pointer. | 704 // RCX : current thread. |
705 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | 705 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
706 // Save frame pointer coming in. | 706 // Save frame pointer coming in. |
707 __ EnterFrame(0); | 707 __ EnterFrame(0); |
708 | 708 |
709 const Register kEntryPointReg = CallingConventions::kArg1Reg; | 709 const Register kEntryPointReg = CallingConventions::kArg1Reg; |
710 const Register kArgDescReg = CallingConventions::kArg2Reg; | 710 const Register kArgDescReg = CallingConventions::kArg2Reg; |
711 const Register kArgsReg = CallingConventions::kArg3Reg; | 711 const Register kArgsReg = CallingConventions::kArg3Reg; |
| 712 const Register kThreadReg = CallingConventions::kArg4Reg; |
712 | 713 |
713 // At this point, the stack looks like: | 714 // At this point, the stack looks like: |
714 // | saved RBP | <-- RBP | 715 // | saved RBP | <-- RBP |
715 // | saved PC (return to DartEntry::InvokeFunction) | | 716 // | saved PC (return to DartEntry::InvokeFunction) | |
716 | 717 |
717 const intptr_t kInitialOffset = 1; | 718 const intptr_t kInitialOffset = 1; |
718 // Save arguments descriptor array. | 719 // Save arguments descriptor array. |
719 const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize; | 720 const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize; |
720 __ pushq(kArgDescReg); | 721 __ pushq(kArgDescReg); |
721 | 722 |
722 // Save C++ ABI callee-saved registers. | 723 // Save C++ ABI callee-saved registers. |
723 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters, | 724 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters, |
724 CallingConventions::kCalleeSaveXmmRegisters); | 725 CallingConventions::kCalleeSaveXmmRegisters); |
725 | 726 |
726 // We now load the pool pointer(PP) as we are about to invoke dart code and we | 727 // We now load the pool pointer(PP) as we are about to invoke dart code and we |
727 // could potentially invoke some intrinsic functions which need the PP to be | 728 // could potentially invoke some intrinsic functions which need the PP to be |
728 // set up. | 729 // set up. |
729 __ LoadPoolPointer(PP); | 730 __ LoadPoolPointer(PP); |
730 | 731 |
731 // If any additional (or fewer) values are pushed, the offsets in | 732 // If any additional (or fewer) values are pushed, the offsets in |
732 // kExitLinkSlotFromEntryFp will need to be changed. | 733 // kExitLinkSlotFromEntryFp will need to be changed. |
733 | 734 |
| 735 // Set up THR, which caches the current thread in Dart code. |
| 736 if (THR != kThreadReg) { |
| 737 __ movq(THR, kThreadReg); |
| 738 } |
734 // Load Isolate pointer into kIsolateReg. | 739 // Load Isolate pointer into kIsolateReg. |
735 const Register kIsolateReg = RBX; | 740 const Register kIsolateReg = RBX; |
736 __ LoadIsolate(kIsolateReg); | 741 __ LoadIsolate(kIsolateReg); |
737 | 742 |
738 // Save the current VMTag on the stack. | 743 // Save the current VMTag on the stack. |
739 __ movq(RAX, Address(kIsolateReg, Isolate::vm_tag_offset())); | 744 __ movq(RAX, Address(kIsolateReg, Isolate::vm_tag_offset())); |
740 __ pushq(RAX); | 745 __ pushq(RAX); |
741 | 746 |
742 // Mark that the isolate is executing Dart code. | 747 // Mark that the isolate is executing Dart code. |
743 __ movq(Address(kIsolateReg, Isolate::vm_tag_offset()), | 748 __ movq(Address(kIsolateReg, Isolate::vm_tag_offset()), |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1298 __ Bind(&error); | 1303 __ Bind(&error); |
1299 __ Stop("Incorrect IC data"); | 1304 __ Stop("Incorrect IC data"); |
1300 __ Bind(&ok); | 1305 __ Bind(&ok); |
1301 #endif | 1306 #endif |
1302 | 1307 |
1303 if (FLAG_optimization_counter_threshold >= 0) { | 1308 if (FLAG_optimization_counter_threshold >= 0) { |
1304 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1309 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1305 // Update counter. | 1310 // Update counter. |
1306 __ movq(R8, Address(R12, count_offset)); | 1311 __ movq(R8, Address(R12, count_offset)); |
1307 __ addq(R8, Immediate(Smi::RawValue(1))); | 1312 __ addq(R8, Immediate(Smi::RawValue(1))); |
1308 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1313 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1309 __ cmovnoq(R9, R8); | 1314 __ cmovnoq(R13, R8); |
1310 __ StoreIntoSmiField(Address(R12, count_offset), R9); | 1315 __ StoreIntoSmiField(Address(R12, count_offset), R13); |
1311 } | 1316 } |
1312 | 1317 |
1313 __ ret(); | 1318 __ ret(); |
1314 } | 1319 } |
1315 | 1320 |
1316 | 1321 |
1317 // Generate inline cache check for 'num_args'. | 1322 // Generate inline cache check for 'num_args'. |
1318 // RBX: Inline cache data object. | 1323 // RBX: Inline cache data object. |
1319 // TOS(0): return address | 1324 // TOS(0): return address |
1320 // Control flow: | 1325 // Control flow: |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 // R12: Pointer to an IC data check group. | 1469 // R12: Pointer to an IC data check group. |
1465 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1470 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
1466 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1471 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1467 __ movq(RAX, Address(R12, target_offset)); | 1472 __ movq(RAX, Address(R12, target_offset)); |
1468 | 1473 |
1469 if (FLAG_optimization_counter_threshold >= 0) { | 1474 if (FLAG_optimization_counter_threshold >= 0) { |
1470 // Update counter. | 1475 // Update counter. |
1471 __ Comment("Update caller's counter"); | 1476 __ Comment("Update caller's counter"); |
1472 __ movq(R8, Address(R12, count_offset)); | 1477 __ movq(R8, Address(R12, count_offset)); |
1473 __ addq(R8, Immediate(Smi::RawValue(1))); | 1478 __ addq(R8, Immediate(Smi::RawValue(1))); |
1474 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1479 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1475 __ cmovnoq(R9, R8); | 1480 __ cmovnoq(R13, R8); |
1476 __ StoreIntoSmiField(Address(R12, count_offset), R9); | 1481 __ StoreIntoSmiField(Address(R12, count_offset), R13); |
1477 } | 1482 } |
1478 | 1483 |
1479 __ Comment("Call target"); | 1484 __ Comment("Call target"); |
1480 __ Bind(&call_target_function); | 1485 __ Bind(&call_target_function); |
1481 // RAX: Target function. | 1486 // RAX: Target function. |
1482 Label is_compiled; | 1487 Label is_compiled; |
1483 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); | 1488 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); |
1484 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1489 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
1485 if (range_collection_mode == kCollectRanges) { | 1490 if (range_collection_mode == kCollectRanges) { |
1486 __ movq(R8, Address(RSP, + 1 * kWordSize)); | 1491 __ movq(R8, Address(RSP, + 1 * kWordSize)); |
1487 if (num_args == 2) { | 1492 if (num_args == 2) { |
1488 __ movq(R9, Address(RSP, + 2 * kWordSize)); | 1493 __ movq(R13, Address(RSP, + 2 * kWordSize)); |
1489 } | 1494 } |
1490 __ EnterStubFrame(); | 1495 __ EnterStubFrame(); |
1491 __ pushq(RBX); | 1496 __ pushq(RBX); |
1492 if (num_args == 2) { | 1497 if (num_args == 2) { |
1493 __ pushq(R9); | 1498 __ pushq(R13); |
1494 } | 1499 } |
1495 __ pushq(R8); | 1500 __ pushq(R8); |
1496 __ call(RCX); | 1501 __ call(RCX); |
1497 | 1502 |
1498 Label done; | 1503 Label done; |
1499 __ movq(RDX, RAX); | 1504 __ movq(RDX, RAX); |
1500 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); | 1505 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); |
1501 __ UpdateRangeFeedback(RDX, 2, RBX, RCX, &done); | 1506 __ UpdateRangeFeedback(RDX, 2, RBX, RCX, &done); |
1502 __ Bind(&done); | 1507 __ Bind(&done); |
1503 __ LeaveStubFrame(); | 1508 __ LeaveStubFrame(); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1682 // R12: ic_data_array with entries: target functions and count. | 1687 // R12: ic_data_array with entries: target functions and count. |
1683 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1688 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
1684 // R12: points directly to the first ic data array element. | 1689 // R12: points directly to the first ic data array element. |
1685 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1690 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1686 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1691 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1687 | 1692 |
1688 if (FLAG_optimization_counter_threshold >= 0) { | 1693 if (FLAG_optimization_counter_threshold >= 0) { |
1689 // Increment count for this call. | 1694 // Increment count for this call. |
1690 __ movq(R8, Address(R12, count_offset)); | 1695 __ movq(R8, Address(R12, count_offset)); |
1691 __ addq(R8, Immediate(Smi::RawValue(1))); | 1696 __ addq(R8, Immediate(Smi::RawValue(1))); |
1692 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1697 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1693 __ cmovnoq(R9, R8); | 1698 __ cmovnoq(R13, R8); |
1694 __ StoreIntoSmiField(Address(R12, count_offset), R9); | 1699 __ StoreIntoSmiField(Address(R12, count_offset), R13); |
1695 } | 1700 } |
1696 | 1701 |
1697 // Load arguments descriptor into R10. | 1702 // Load arguments descriptor into R10. |
1698 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 1703 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
1699 | 1704 |
1700 // Get function and call it, if possible. | 1705 // Get function and call it, if possible. |
1701 __ movq(RAX, Address(R12, target_offset)); | 1706 __ movq(RAX, Address(R12, target_offset)); |
1702 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); | 1707 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); |
1703 // RCX: Target instructions. | 1708 // RCX: Target instructions. |
1704 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1709 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1966 | 1971 |
1967 #if defined(_WIN64) | 1972 #if defined(_WIN64) |
1968 Register stacktrace_reg = RBX; | 1973 Register stacktrace_reg = RBX; |
1969 __ movq(stacktrace_reg, Address(RSP, 5 * kWordSize)); | 1974 __ movq(stacktrace_reg, Address(RSP, 5 * kWordSize)); |
1970 Register isolate_reg = RDI; | 1975 Register isolate_reg = RDI; |
1971 __ movq(isolate_reg, Address(RSP, 6 * kWordSize)); | 1976 __ movq(isolate_reg, Address(RSP, 6 * kWordSize)); |
1972 #else | 1977 #else |
1973 Register stacktrace_reg = CallingConventions::kArg5Reg; | 1978 Register stacktrace_reg = CallingConventions::kArg5Reg; |
1974 Register isolate_reg = CallingConventions::kArg6Reg; | 1979 Register isolate_reg = CallingConventions::kArg6Reg; |
1975 #endif | 1980 #endif |
1976 | 1981 // TODO(koda): Pass thread instead of isolate. |
| 1982 __ movq(THR, Address(isolate_reg, Isolate::mutator_thread_offset())); |
1977 __ movq(RBP, CallingConventions::kArg3Reg); | 1983 __ movq(RBP, CallingConventions::kArg3Reg); |
1978 __ movq(RSP, CallingConventions::kArg2Reg); | 1984 __ movq(RSP, CallingConventions::kArg2Reg); |
1979 __ movq(kStackTraceObjectReg, stacktrace_reg); | 1985 __ movq(kStackTraceObjectReg, stacktrace_reg); |
1980 __ movq(kExceptionObjectReg, CallingConventions::kArg4Reg); | 1986 __ movq(kExceptionObjectReg, CallingConventions::kArg4Reg); |
1981 // Set the tag. | 1987 // Set the tag. |
1982 __ movq(Address(isolate_reg, Isolate::vm_tag_offset()), | 1988 __ movq(Address(isolate_reg, Isolate::vm_tag_offset()), |
1983 Immediate(VMTag::kDartTagId)); | 1989 Immediate(VMTag::kDartTagId)); |
1984 // Clear top exit frame. | 1990 // Clear top exit frame. |
1985 __ movq(Address(isolate_reg, Isolate::top_exit_frame_info_offset()), | 1991 __ movq(Address(isolate_reg, Isolate::top_exit_frame_info_offset()), |
1986 Immediate(0)); | 1992 Immediate(0)); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2174 // Result: | 2180 // Result: |
2175 // RCX: entry point. | 2181 // RCX: entry point. |
2176 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2182 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2177 EmitMegamorphicLookup(assembler, RDI, RBX, RCX); | 2183 EmitMegamorphicLookup(assembler, RDI, RBX, RCX); |
2178 __ ret(); | 2184 __ ret(); |
2179 } | 2185 } |
2180 | 2186 |
2181 } // namespace dart | 2187 } // namespace dart |
2182 | 2188 |
2183 #endif // defined TARGET_ARCH_X64 | 2189 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |