| 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" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/heap.h" | 12 #include "vm/heap.h" |
| 13 #include "vm/instructions.h" | 13 #include "vm/instructions.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/resolver.h" | 15 #include "vm/resolver.h" |
| 16 #include "vm/scavenger.h" | 16 #include "vm/scavenger.h" |
| 17 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
| 18 #include "vm/stub_code.h" | 18 #include "vm/stub_code.h" |
| 19 #include "vm/tags.h" | 19 #include "vm/tags.h" |
| 20 | 20 |
| 21 #define __ assembler-> | 21 #define __ assembler-> |
| 22 | 22 |
| 23 namespace dart { | 23 namespace dart { |
| 24 | 24 |
| 25 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); | 25 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); |
| 26 DEFINE_FLAG(bool, use_slow_path, false, | 26 DEFINE_FLAG(bool, use_slow_path, false, |
| 27 "Set to true for debugging & verifying the slow paths."); | 27 "Set to true for debugging & verifying the slow paths."); |
| 28 DECLARE_FLAG(bool, trace_optimized_ic_calls); | 28 DECLARE_FLAG(bool, trace_optimized_ic_calls); |
| 29 | 29 |
| 30 DECLARE_FLAG(bool, enable_debugger); | |
| 31 | |
| 32 // Input parameters: | 30 // Input parameters: |
| 33 // RSP : points to return address. | 31 // RSP : points to return address. |
| 34 // RSP + 8 : address of last argument in argument array. | 32 // RSP + 8 : address of last argument in argument array. |
| 35 // RSP + 8*R10 : address of first argument in argument array. | 33 // RSP + 8*R10 : address of first argument in argument array. |
| 36 // RSP + 8*R10 + 8 : address of return value. | 34 // RSP + 8*R10 + 8 : address of return value. |
| 37 // RBX : address of the runtime function to call. | 35 // RBX : address of the runtime function to call. |
| 38 // R10 : number of arguments to the call. | 36 // R10 : number of arguments to the call. |
| 39 // Must preserve callee saved registers R12 and R13. | 37 // Must preserve callee saved registers R12 and R13. |
| 40 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 38 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
| 41 ASSERT((R12 != CTX) && (R13 != CTX)); | 39 ASSERT((R12 != CTX) && (R13 != CTX)); |
| (...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1259 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1262 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); | 1260 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); |
| 1263 __ cmpq(RCX, Immediate(num_args)); | 1261 __ cmpq(RCX, Immediate(num_args)); |
| 1264 __ j(EQUAL, &ok, Assembler::kNearJump); | 1262 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1265 __ Stop("Incorrect stub for IC data"); | 1263 __ Stop("Incorrect stub for IC data"); |
| 1266 __ Bind(&ok); | 1264 __ Bind(&ok); |
| 1267 } | 1265 } |
| 1268 #endif // DEBUG | 1266 #endif // DEBUG |
| 1269 | 1267 |
| 1270 Label stepping, done_stepping; | 1268 Label stepping, done_stepping; |
| 1271 if (FLAG_enable_debugger) { | 1269 // Check single stepping. |
| 1272 // Check single stepping. | 1270 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| 1273 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 1271 __ cmpb(Address(RAX, Isolate::single_step_offset()), Immediate(0)); |
| 1274 __ cmpb(Address(RAX, Isolate::single_step_offset()), Immediate(0)); | 1272 __ j(NOT_EQUAL, &stepping); |
| 1275 __ j(NOT_EQUAL, &stepping); | 1273 __ Bind(&done_stepping); |
| 1276 __ Bind(&done_stepping); | |
| 1277 } | |
| 1278 | 1274 |
| 1279 // Load arguments descriptor into R10. | 1275 // Load arguments descriptor into R10. |
| 1280 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 1276 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
| 1281 // Loop that checks if there is an IC data match. | 1277 // Loop that checks if there is an IC data match. |
| 1282 Label loop, update, test, found; | 1278 Label loop, update, test, found; |
| 1283 // RBX: IC data object (preserved). | 1279 // RBX: IC data object (preserved). |
| 1284 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); | 1280 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
| 1285 // R12: ic_data_array with check entries: classes and target functions. | 1281 // R12: ic_data_array with check entries: classes and target functions. |
| 1286 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1282 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
| 1287 // R12: points directly to the first ic data array element. | 1283 // R12: points directly to the first ic data array element. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1371 __ cmovnoq(R9, R8); | 1367 __ cmovnoq(R9, R8); |
| 1372 __ movq(Address(R12, count_offset), R9); | 1368 __ movq(Address(R12, count_offset), R9); |
| 1373 | 1369 |
| 1374 __ Bind(&call_target_function); | 1370 __ Bind(&call_target_function); |
| 1375 // RAX: Target function. | 1371 // RAX: Target function. |
| 1376 Label is_compiled; | 1372 Label is_compiled; |
| 1377 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); | 1373 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); |
| 1378 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1374 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1379 __ jmp(RCX); | 1375 __ jmp(RCX); |
| 1380 | 1376 |
| 1381 if (FLAG_enable_debugger) { | 1377 __ Bind(&stepping); |
| 1382 __ Bind(&stepping); | 1378 __ EnterStubFrame(); |
| 1383 __ EnterStubFrame(); | 1379 __ pushq(RBX); |
| 1384 __ pushq(RBX); | 1380 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1385 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1381 __ popq(RBX); |
| 1386 __ popq(RBX); | 1382 __ LeaveStubFrame(); |
| 1387 __ LeaveStubFrame(); | 1383 __ jmp(&done_stepping); |
| 1388 __ jmp(&done_stepping); | |
| 1389 } | |
| 1390 } | 1384 } |
| 1391 | 1385 |
| 1392 | 1386 |
| 1393 // Use inline cache data array to invoke the target or continue in inline | 1387 // Use inline cache data array to invoke the target or continue in inline |
| 1394 // cache miss handler. Stub for 1-argument check (receiver class). | 1388 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1395 // RBX: Inline cache data object. | 1389 // RBX: Inline cache data object. |
| 1396 // TOS(0): Return address. | 1390 // TOS(0): Return address. |
| 1397 // Inline cache data object structure: | 1391 // Inline cache data object structure: |
| 1398 // 0: function-name | 1392 // 0: function-name |
| 1399 // 1: N, number of arguments checked. | 1393 // 1: N, number of arguments checked. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1474 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); | 1468 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); |
| 1475 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1469 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1476 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); | 1470 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); |
| 1477 __ cmpq(RCX, Immediate(0)); | 1471 __ cmpq(RCX, Immediate(0)); |
| 1478 __ j(EQUAL, &ok, Assembler::kNearJump); | 1472 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1479 __ Stop("Incorrect IC data for unoptimized static call"); | 1473 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1480 __ Bind(&ok); | 1474 __ Bind(&ok); |
| 1481 } | 1475 } |
| 1482 #endif // DEBUG | 1476 #endif // DEBUG |
| 1483 | 1477 |
| 1484 if (FLAG_enable_debugger) { | 1478 // Check single stepping. |
| 1485 // Check single stepping. | 1479 Label not_stepping; |
| 1486 Label not_stepping; | 1480 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| 1487 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 1481 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
| 1488 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1482 __ cmpq(RAX, Immediate(0)); |
| 1489 __ cmpq(RAX, Immediate(0)); | 1483 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); |
| 1490 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); | 1484 __ EnterStubFrame(); |
| 1491 __ EnterStubFrame(); | 1485 __ pushq(RBX); // Preserve IC data object. |
| 1492 __ pushq(RBX); // Preserve IC data object. | 1486 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1493 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1487 __ popq(RBX); |
| 1494 __ popq(RBX); | 1488 __ LeaveStubFrame(); |
| 1495 __ LeaveStubFrame(); | 1489 __ Bind(¬_stepping); |
| 1496 __ Bind(¬_stepping); | |
| 1497 } | |
| 1498 | 1490 |
| 1499 // RBX: IC data object (preserved). | 1491 // RBX: IC data object (preserved). |
| 1500 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); | 1492 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
| 1501 // R12: ic_data_array with entries: target functions and count. | 1493 // R12: ic_data_array with entries: target functions and count. |
| 1502 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1494 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
| 1503 // R12: points directly to the first ic data array element. | 1495 // R12: points directly to the first ic data array element. |
| 1504 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1496 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1505 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1497 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1506 | 1498 |
| 1507 // Increment count for this call. | 1499 // Increment count for this call. |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1601 __ pushq(R12); // Room for result. | 1593 __ pushq(R12); // Room for result. |
| 1602 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1594 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
| 1603 __ popq(RAX); // Address of original. | 1595 __ popq(RAX); // Address of original. |
| 1604 __ LeaveStubFrame(); | 1596 __ LeaveStubFrame(); |
| 1605 __ jmp(RAX); // Jump to original stub. | 1597 __ jmp(RAX); // Jump to original stub. |
| 1606 } | 1598 } |
| 1607 | 1599 |
| 1608 | 1600 |
| 1609 // Called only from unoptimized code. | 1601 // Called only from unoptimized code. |
| 1610 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1602 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
| 1611 if (FLAG_enable_debugger) { | 1603 // Check single stepping. |
| 1612 // Check single stepping. | 1604 Label not_stepping; |
| 1613 Label not_stepping; | 1605 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| 1614 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 1606 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
| 1615 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1607 __ cmpq(RAX, Immediate(0)); |
| 1616 __ cmpq(RAX, Immediate(0)); | 1608 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); |
| 1617 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); | |
| 1618 | 1609 |
| 1619 __ EnterStubFrame(); | 1610 __ EnterStubFrame(); |
| 1620 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1611 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1621 __ LeaveStubFrame(); | 1612 __ LeaveStubFrame(); |
| 1622 __ Bind(¬_stepping); | 1613 __ Bind(¬_stepping); |
| 1623 } | 1614 |
| 1624 __ ret(); | 1615 __ ret(); |
| 1625 } | 1616 } |
| 1626 | 1617 |
| 1627 | 1618 |
| 1628 // Used to check class and type arguments. Arguments passed on stack: | 1619 // Used to check class and type arguments. Arguments passed on stack: |
| 1629 // TOS + 0: return address. | 1620 // TOS + 0: return address. |
| 1630 // TOS + 1: instantiator type arguments (can be NULL). | 1621 // TOS + 1: instantiator type arguments (can be NULL). |
| 1631 // TOS + 2: instance. | 1622 // TOS + 2: instance. |
| 1632 // TOS + 3: SubtypeTestCache. | 1623 // TOS + 3: SubtypeTestCache. |
| 1633 // Result in RCX: null -> not found, otherwise result (true or false). | 1624 // Result in RCX: null -> not found, otherwise result (true or false). |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1868 } | 1859 } |
| 1869 | 1860 |
| 1870 | 1861 |
| 1871 // Called only from unoptimized code. All relevant registers have been saved. | 1862 // Called only from unoptimized code. All relevant registers have been saved. |
| 1872 // TOS + 0: return address | 1863 // TOS + 0: return address |
| 1873 // TOS + 1: right argument. | 1864 // TOS + 1: right argument. |
| 1874 // TOS + 2: left argument. | 1865 // TOS + 2: left argument. |
| 1875 // Returns ZF set. | 1866 // Returns ZF set. |
| 1876 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 1867 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 1877 Assembler* assembler) { | 1868 Assembler* assembler) { |
| 1878 if (FLAG_enable_debugger) { | 1869 // Check single stepping. |
| 1879 // Check single stepping. | 1870 Label not_stepping; |
| 1880 Label not_stepping; | 1871 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| 1881 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 1872 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
| 1882 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1873 __ cmpq(RAX, Immediate(0)); |
| 1883 __ cmpq(RAX, Immediate(0)); | 1874 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); |
| 1884 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); | 1875 __ EnterStubFrame(); |
| 1885 __ EnterStubFrame(); | 1876 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1886 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1877 __ LeaveStubFrame(); |
| 1887 __ LeaveStubFrame(); | 1878 __ Bind(¬_stepping); |
| 1888 __ Bind(¬_stepping); | |
| 1889 } | |
| 1890 | 1879 |
| 1891 const Register left = RAX; | 1880 const Register left = RAX; |
| 1892 const Register right = RDX; | 1881 const Register right = RDX; |
| 1893 | 1882 |
| 1894 __ movq(left, Address(RSP, 2 * kWordSize)); | 1883 __ movq(left, Address(RSP, 2 * kWordSize)); |
| 1895 __ movq(right, Address(RSP, 1 * kWordSize)); | 1884 __ movq(right, Address(RSP, 1 * kWordSize)); |
| 1896 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 1885 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
| 1897 __ ret(); | 1886 __ ret(); |
| 1898 } | 1887 } |
| 1899 | 1888 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1910 | 1899 |
| 1911 __ movq(left, Address(RSP, 2 * kWordSize)); | 1900 __ movq(left, Address(RSP, 2 * kWordSize)); |
| 1912 __ movq(right, Address(RSP, 1 * kWordSize)); | 1901 __ movq(right, Address(RSP, 1 * kWordSize)); |
| 1913 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 1902 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
| 1914 __ ret(); | 1903 __ ret(); |
| 1915 } | 1904 } |
| 1916 | 1905 |
| 1917 } // namespace dart | 1906 } // namespace dart |
| 1918 | 1907 |
| 1919 #endif // defined TARGET_ARCH_X64 | 1908 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |