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 |