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_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
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 11 matching lines...) Expand all Loading... |
22 #define __ assembler-> | 22 #define __ assembler-> |
23 | 23 |
24 namespace dart { | 24 namespace dart { |
25 | 25 |
26 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); | 26 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); |
27 DEFINE_FLAG(bool, use_slow_path, false, | 27 DEFINE_FLAG(bool, use_slow_path, false, |
28 "Set to true for debugging & verifying the slow paths."); | 28 "Set to true for debugging & verifying the slow paths."); |
29 DECLARE_FLAG(bool, trace_optimized_ic_calls); | 29 DECLARE_FLAG(bool, trace_optimized_ic_calls); |
30 DEFINE_FLAG(bool, verify_incoming_contexts, false, ""); | 30 DEFINE_FLAG(bool, verify_incoming_contexts, false, ""); |
31 | 31 |
32 DECLARE_FLAG(bool, enable_debugger); | |
33 | |
34 // Input parameters: | 32 // Input parameters: |
35 // ESP : points to return address. | 33 // ESP : points to return address. |
36 // ESP + 4 : address of last argument in argument array. | 34 // ESP + 4 : address of last argument in argument array. |
37 // ESP + 4*EDX : address of first argument in argument array. | 35 // ESP + 4*EDX : address of first argument in argument array. |
38 // ESP + 4*EDX + 4 : address of return value. | 36 // ESP + 4*EDX + 4 : address of return value. |
39 // ECX : address of the runtime function to call. | 37 // ECX : address of the runtime function to call. |
40 // EDX : number of arguments to the call. | 38 // EDX : number of arguments to the call. |
41 // Must preserve callee saved registers EDI and EBX. | 39 // Must preserve callee saved registers EDI and EBX. |
42 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 40 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
43 const intptr_t isolate_offset = NativeArguments::isolate_offset(); | 41 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
(...skipping 1243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1287 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1285 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1288 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); | 1286 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); |
1289 __ cmpl(EBX, Immediate(num_args)); | 1287 __ cmpl(EBX, Immediate(num_args)); |
1290 __ j(EQUAL, &ok, Assembler::kNearJump); | 1288 __ j(EQUAL, &ok, Assembler::kNearJump); |
1291 __ Stop("Incorrect stub for IC data"); | 1289 __ Stop("Incorrect stub for IC data"); |
1292 __ Bind(&ok); | 1290 __ Bind(&ok); |
1293 } | 1291 } |
1294 #endif // DEBUG | 1292 #endif // DEBUG |
1295 | 1293 |
1296 Label stepping, done_stepping; | 1294 Label stepping, done_stepping; |
1297 if (FLAG_enable_debugger) { | 1295 // Check single stepping. |
1298 // Check single stepping. | 1296 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); |
1299 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 1297 __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0)); |
1300 __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0)); | 1298 __ j(NOT_EQUAL, &stepping); |
1301 __ j(NOT_EQUAL, &stepping); | 1299 __ Bind(&done_stepping); |
1302 __ Bind(&done_stepping); | |
1303 } | |
1304 | 1300 |
1305 // ECX: IC data object (preserved). | 1301 // ECX: IC data object (preserved). |
1306 // Load arguments descriptor into EDX. | 1302 // Load arguments descriptor into EDX. |
1307 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); | 1303 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
1308 // Loop that checks if there is an IC data match. | 1304 // Loop that checks if there is an IC data match. |
1309 Label loop, update, test, found; | 1305 Label loop, update, test, found; |
1310 // ECX: IC data object (preserved). | 1306 // ECX: IC data object (preserved). |
1311 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1307 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
1312 // EBX: ic_data_array with check entries: classes and target functions. | 1308 // EBX: ic_data_array with check entries: classes and target functions. |
1313 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1309 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1403 __ movl(Address(EBX, count_offset), EDI); | 1399 __ movl(Address(EBX, count_offset), EDI); |
1404 | 1400 |
1405 __ movl(EAX, Address(EBX, target_offset)); | 1401 __ movl(EAX, Address(EBX, target_offset)); |
1406 __ Bind(&call_target_function); | 1402 __ Bind(&call_target_function); |
1407 // EAX: Target function. | 1403 // EAX: Target function. |
1408 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 1404 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); |
1409 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1405 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
1410 __ jmp(EBX); | 1406 __ jmp(EBX); |
1411 __ int3(); | 1407 __ int3(); |
1412 | 1408 |
1413 if (FLAG_enable_debugger) { | 1409 __ Bind(&stepping); |
1414 __ Bind(&stepping); | 1410 __ EnterStubFrame(); |
1415 __ EnterStubFrame(); | 1411 __ pushl(ECX); |
1416 __ pushl(ECX); | 1412 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1417 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1413 __ popl(ECX); |
1418 __ popl(ECX); | 1414 __ LeaveFrame(); |
1419 __ LeaveFrame(); | 1415 __ jmp(&done_stepping); |
1420 __ jmp(&done_stepping); | |
1421 } | |
1422 } | 1416 } |
1423 | 1417 |
1424 | 1418 |
1425 // Use inline cache data array to invoke the target or continue in inline | 1419 // Use inline cache data array to invoke the target or continue in inline |
1426 // cache miss handler. Stub for 1-argument check (receiver class). | 1420 // cache miss handler. Stub for 1-argument check (receiver class). |
1427 // ECX: Inline cache data object. | 1421 // ECX: Inline cache data object. |
1428 // TOS(0): Return address. | 1422 // TOS(0): Return address. |
1429 // Inline cache data object structure: | 1423 // Inline cache data object structure: |
1430 // 0: function-name | 1424 // 0: function-name |
1431 // 1: N, number of arguments checked. | 1425 // 1: N, number of arguments checked. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1507 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1501 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
1508 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); | 1502 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); |
1509 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1503 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1510 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); | 1504 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); |
1511 __ cmpl(EBX, Immediate(0)); | 1505 __ cmpl(EBX, Immediate(0)); |
1512 __ j(EQUAL, &ok, Assembler::kNearJump); | 1506 __ j(EQUAL, &ok, Assembler::kNearJump); |
1513 __ Stop("Incorrect IC data for unoptimized static call"); | 1507 __ Stop("Incorrect IC data for unoptimized static call"); |
1514 __ Bind(&ok); | 1508 __ Bind(&ok); |
1515 } | 1509 } |
1516 #endif // DEBUG | 1510 #endif // DEBUG |
1517 if (FLAG_enable_debugger) { | 1511 // Check single stepping. |
1518 // Check single stepping. | 1512 Label not_stepping; |
1519 Label not_stepping; | 1513 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); |
1520 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 1514 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); |
1521 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); | 1515 __ cmpl(EAX, Immediate(0)); |
1522 __ cmpl(EAX, Immediate(0)); | 1516 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); |
1523 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); | |
1524 | 1517 |
1525 __ EnterStubFrame(); | 1518 __ EnterStubFrame(); |
1526 __ pushl(ECX); | 1519 __ pushl(ECX); |
1527 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1520 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1528 __ popl(ECX); | 1521 __ popl(ECX); |
1529 __ LeaveFrame(); | 1522 __ LeaveFrame(); |
1530 __ Bind(¬_stepping); | 1523 __ Bind(¬_stepping); |
1531 } | |
1532 | 1524 |
1533 // ECX: IC data object (preserved). | 1525 // ECX: IC data object (preserved). |
1534 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1526 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
1535 // EBX: ic_data_array with entries: target functions and count. | 1527 // EBX: ic_data_array with entries: target functions and count. |
1536 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1528 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
1537 // EBX: points directly to the first ic data array element. | 1529 // EBX: points directly to the first ic data array element. |
1538 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1530 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1539 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1531 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1540 | 1532 |
1541 // Increment count for this call. | 1533 // Increment count for this call. |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1635 __ pushl(raw_null); // Room for result. | 1627 __ pushl(raw_null); // Room for result. |
1636 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1628 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1637 __ popl(EAX); // Address of original stub. | 1629 __ popl(EAX); // Address of original stub. |
1638 __ LeaveFrame(); | 1630 __ LeaveFrame(); |
1639 __ jmp(EAX); // Jump to original stub. | 1631 __ jmp(EAX); // Jump to original stub. |
1640 } | 1632 } |
1641 | 1633 |
1642 | 1634 |
1643 // Called only from unoptimized code. | 1635 // Called only from unoptimized code. |
1644 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1636 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
1645 if (FLAG_enable_debugger) { | 1637 // Check single stepping. |
1646 // Check single stepping. | 1638 Label not_stepping; |
1647 Label not_stepping; | 1639 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); |
1648 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 1640 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); |
1649 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); | 1641 __ cmpl(EAX, Immediate(0)); |
1650 __ cmpl(EAX, Immediate(0)); | 1642 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); |
1651 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); | |
1652 | 1643 |
1653 __ EnterStubFrame(); | 1644 __ EnterStubFrame(); |
1654 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1645 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1655 __ LeaveFrame(); | 1646 __ LeaveFrame(); |
1656 __ Bind(¬_stepping); | 1647 __ Bind(¬_stepping); |
1657 } | 1648 |
1658 __ ret(); | 1649 __ ret(); |
1659 } | 1650 } |
1660 | 1651 |
1661 | 1652 |
1662 // Used to check class and type arguments. Arguments passed on stack: | 1653 // Used to check class and type arguments. Arguments passed on stack: |
1663 // TOS + 0: return address. | 1654 // TOS + 0: return address. |
1664 // TOS + 1: instantiator type arguments (can be NULL). | 1655 // TOS + 1: instantiator type arguments (can be NULL). |
1665 // TOS + 2: instance. | 1656 // TOS + 2: instance. |
1666 // TOS + 3: SubtypeTestCache. | 1657 // TOS + 3: SubtypeTestCache. |
1667 // Result in ECX: null -> not found, otherwise result (true or false). | 1658 // Result in ECX: null -> not found, otherwise result (true or false). |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1897 } | 1888 } |
1898 | 1889 |
1899 | 1890 |
1900 // Called only from unoptimized code. All relevant registers have been saved. | 1891 // Called only from unoptimized code. All relevant registers have been saved. |
1901 // TOS + 0: return address | 1892 // TOS + 0: return address |
1902 // TOS + 1: right argument. | 1893 // TOS + 1: right argument. |
1903 // TOS + 2: left argument. | 1894 // TOS + 2: left argument. |
1904 // Returns ZF set. | 1895 // Returns ZF set. |
1905 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 1896 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
1906 Assembler* assembler) { | 1897 Assembler* assembler) { |
1907 if (FLAG_enable_debugger) { | 1898 // Check single stepping. |
1908 // Check single stepping. | 1899 Label not_stepping; |
1909 Label not_stepping; | 1900 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); |
1910 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 1901 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); |
1911 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); | 1902 __ cmpl(EAX, Immediate(0)); |
1912 __ cmpl(EAX, Immediate(0)); | 1903 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); |
1913 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); | |
1914 | 1904 |
1915 __ EnterStubFrame(); | 1905 __ EnterStubFrame(); |
1916 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1906 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1917 __ LeaveFrame(); | 1907 __ LeaveFrame(); |
1918 __ Bind(¬_stepping); | 1908 __ Bind(¬_stepping); |
1919 } | |
1920 | 1909 |
1921 const Register left = EAX; | 1910 const Register left = EAX; |
1922 const Register right = EDX; | 1911 const Register right = EDX; |
1923 const Register temp = ECX; | 1912 const Register temp = ECX; |
1924 __ movl(left, Address(ESP, 2 * kWordSize)); | 1913 __ movl(left, Address(ESP, 2 * kWordSize)); |
1925 __ movl(right, Address(ESP, 1 * kWordSize)); | 1914 __ movl(right, Address(ESP, 1 * kWordSize)); |
1926 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1915 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
1927 __ ret(); | 1916 __ ret(); |
1928 } | 1917 } |
1929 | 1918 |
(...skipping 10 matching lines...) Expand all Loading... |
1940 const Register temp = ECX; | 1929 const Register temp = ECX; |
1941 __ movl(left, Address(ESP, 2 * kWordSize)); | 1930 __ movl(left, Address(ESP, 2 * kWordSize)); |
1942 __ movl(right, Address(ESP, 1 * kWordSize)); | 1931 __ movl(right, Address(ESP, 1 * kWordSize)); |
1943 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1932 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
1944 __ ret(); | 1933 __ ret(); |
1945 } | 1934 } |
1946 | 1935 |
1947 } // namespace dart | 1936 } // namespace dart |
1948 | 1937 |
1949 #endif // defined TARGET_ARCH_IA32 | 1938 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |