| 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 |