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