| 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 1281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1292 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); | 1292 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); |
| 1293 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1293 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1294 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); | 1294 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); |
| 1295 __ cmpl(EBX, Immediate(num_args)); | 1295 __ cmpl(EBX, Immediate(num_args)); |
| 1296 __ j(EQUAL, &ok, Assembler::kNearJump); | 1296 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1297 __ Stop("Incorrect stub for IC data"); | 1297 __ Stop("Incorrect stub for IC data"); |
| 1298 __ Bind(&ok); | 1298 __ Bind(&ok); |
| 1299 } | 1299 } |
| 1300 #endif // DEBUG | 1300 #endif // DEBUG |
| 1301 | 1301 |
| 1302 #if !defined(PRODUCT) |
| 1302 Label stepping, done_stepping; | 1303 Label stepping, done_stepping; |
| 1303 if (FLAG_support_debugger && !optimized) { | 1304 if (!optimized) { |
| 1304 __ Comment("Check single stepping"); | 1305 __ Comment("Check single stepping"); |
| 1305 __ LoadIsolate(EAX); | 1306 __ LoadIsolate(EAX); |
| 1306 __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0)); | 1307 __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0)); |
| 1307 __ j(NOT_EQUAL, &stepping); | 1308 __ j(NOT_EQUAL, &stepping); |
| 1308 __ Bind(&done_stepping); | 1309 __ Bind(&done_stepping); |
| 1309 } | 1310 } |
| 1311 #endif |
| 1310 Label not_smi_or_overflow; | 1312 Label not_smi_or_overflow; |
| 1311 if (kind != Token::kILLEGAL) { | 1313 if (kind != Token::kILLEGAL) { |
| 1312 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1314 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
| 1313 } | 1315 } |
| 1314 __ Bind(¬_smi_or_overflow); | 1316 __ Bind(¬_smi_or_overflow); |
| 1315 | 1317 |
| 1316 __ Comment("Extract ICData initial values and receiver cid"); | 1318 __ Comment("Extract ICData initial values and receiver cid"); |
| 1317 // ECX: IC data object (preserved). | 1319 // ECX: IC data object (preserved). |
| 1318 // Load arguments descriptor into EDX. | 1320 // Load arguments descriptor into EDX. |
| 1319 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); | 1321 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); | 1427 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); |
| 1426 } | 1428 } |
| 1427 | 1429 |
| 1428 __ movl(EAX, Address(EBX, target_offset)); | 1430 __ movl(EAX, Address(EBX, target_offset)); |
| 1429 __ Bind(&call_target_function); | 1431 __ Bind(&call_target_function); |
| 1430 __ Comment("Call target"); | 1432 __ Comment("Call target"); |
| 1431 // EAX: Target function. | 1433 // EAX: Target function. |
| 1432 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); | 1434 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); |
| 1433 __ jmp(EBX); | 1435 __ jmp(EBX); |
| 1434 | 1436 |
| 1435 if (FLAG_support_debugger && !optimized) { | 1437 #if !defined(PRODUCT) |
| 1438 if (!optimized) { |
| 1436 __ Bind(&stepping); | 1439 __ Bind(&stepping); |
| 1437 __ EnterStubFrame(); | 1440 __ EnterStubFrame(); |
| 1438 __ pushl(ECX); | 1441 __ pushl(ECX); |
| 1439 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1442 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1440 __ popl(ECX); | 1443 __ popl(ECX); |
| 1441 __ LeaveFrame(); | 1444 __ LeaveFrame(); |
| 1442 __ jmp(&done_stepping); | 1445 __ jmp(&done_stepping); |
| 1443 } | 1446 } |
| 1447 #endif |
| 1444 } | 1448 } |
| 1445 | 1449 |
| 1446 // Use inline cache data array to invoke the target or continue in inline | 1450 // Use inline cache data array to invoke the target or continue in inline |
| 1447 // cache miss handler. Stub for 1-argument check (receiver class). | 1451 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1448 // ECX: Inline cache data object. | 1452 // ECX: Inline cache data object. |
| 1449 // TOS(0): Return address. | 1453 // TOS(0): Return address. |
| 1450 // Inline cache data object structure: | 1454 // Inline cache data object structure: |
| 1451 // 0: function-name | 1455 // 0: function-name |
| 1452 // 1: N, number of arguments checked. | 1456 // 1: N, number of arguments checked. |
| 1453 // 2 .. (length - 1): group of checks, each check containing: | 1457 // 2 .. (length - 1): group of checks, each check containing: |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1524 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1528 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
| 1525 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); | 1529 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); |
| 1526 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1530 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1527 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); | 1531 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); |
| 1528 __ cmpl(EBX, Immediate(0)); | 1532 __ cmpl(EBX, Immediate(0)); |
| 1529 __ j(EQUAL, &ok, Assembler::kNearJump); | 1533 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1530 __ Stop("Incorrect IC data for unoptimized static call"); | 1534 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1531 __ Bind(&ok); | 1535 __ Bind(&ok); |
| 1532 } | 1536 } |
| 1533 #endif // DEBUG | 1537 #endif // DEBUG |
| 1538 |
| 1539 #if !defined(PRODUCT) |
| 1534 // Check single stepping. | 1540 // Check single stepping. |
| 1535 Label stepping, done_stepping; | 1541 Label stepping, done_stepping; |
| 1536 if (FLAG_support_debugger) { | 1542 __ LoadIsolate(EAX); |
| 1537 __ LoadIsolate(EAX); | 1543 __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0)); |
| 1538 __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0)); | 1544 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); |
| 1539 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); | 1545 __ Bind(&done_stepping); |
| 1540 __ Bind(&done_stepping); | 1546 #endif |
| 1541 } | |
| 1542 | 1547 |
| 1543 // ECX: IC data object (preserved). | 1548 // ECX: IC data object (preserved). |
| 1544 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1549 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1545 // EBX: ic_data_array with entries: target functions and count. | 1550 // EBX: ic_data_array with entries: target functions and count. |
| 1546 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1551 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1547 // EBX: points directly to the first ic data array element. | 1552 // EBX: points directly to the first ic data array element. |
| 1548 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1553 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1549 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1554 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1550 | 1555 |
| 1551 if (FLAG_optimization_counter_threshold >= 0) { | 1556 if (FLAG_optimization_counter_threshold >= 0) { |
| 1552 // Increment count for this call, ignore overflow. | 1557 // Increment count for this call, ignore overflow. |
| 1553 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); | 1558 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); |
| 1554 } | 1559 } |
| 1555 | 1560 |
| 1556 // Load arguments descriptor into EDX. | 1561 // Load arguments descriptor into EDX. |
| 1557 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); | 1562 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
| 1558 | 1563 |
| 1559 // Get function and call it, if possible. | 1564 // Get function and call it, if possible. |
| 1560 __ movl(EAX, Address(EBX, target_offset)); | 1565 __ movl(EAX, Address(EBX, target_offset)); |
| 1561 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); | 1566 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); |
| 1562 __ jmp(EBX); | 1567 __ jmp(EBX); |
| 1563 | 1568 |
| 1564 if (FLAG_support_debugger) { | 1569 #if !defined(PRODUCT) |
| 1565 __ Bind(&stepping); | 1570 __ Bind(&stepping); |
| 1566 __ EnterStubFrame(); | 1571 __ EnterStubFrame(); |
| 1567 __ pushl(ECX); | 1572 __ pushl(ECX); |
| 1568 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1573 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1569 __ popl(ECX); | 1574 __ popl(ECX); |
| 1570 __ LeaveFrame(); | 1575 __ LeaveFrame(); |
| 1571 __ jmp(&done_stepping, Assembler::kNearJump); | 1576 __ jmp(&done_stepping, Assembler::kNearJump); |
| 1572 } | 1577 #endif |
| 1573 } | 1578 } |
| 1574 | 1579 |
| 1575 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1580 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1576 GenerateUsageCounterIncrement(assembler, EBX); | 1581 GenerateUsageCounterIncrement(assembler, EBX); |
| 1577 GenerateNArgsCheckInlineCacheStub( | 1582 GenerateNArgsCheckInlineCacheStub( |
| 1578 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1583 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
| 1579 } | 1584 } |
| 1580 | 1585 |
| 1581 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1586 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1582 GenerateUsageCounterIncrement(assembler, EBX); | 1587 GenerateUsageCounterIncrement(assembler, EBX); |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1921 __ Bind(&done); | 1926 __ Bind(&done); |
| 1922 } | 1927 } |
| 1923 | 1928 |
| 1924 // Called only from unoptimized code. All relevant registers have been saved. | 1929 // Called only from unoptimized code. All relevant registers have been saved. |
| 1925 // TOS + 0: return address | 1930 // TOS + 0: return address |
| 1926 // TOS + 1: right argument. | 1931 // TOS + 1: right argument. |
| 1927 // TOS + 2: left argument. | 1932 // TOS + 2: left argument. |
| 1928 // Returns ZF set. | 1933 // Returns ZF set. |
| 1929 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 1934 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 1930 Assembler* assembler) { | 1935 Assembler* assembler) { |
| 1936 #if !defined(PRODUCT) |
| 1931 // Check single stepping. | 1937 // Check single stepping. |
| 1932 Label stepping, done_stepping; | 1938 Label stepping, done_stepping; |
| 1933 if (FLAG_support_debugger) { | 1939 __ LoadIsolate(EAX); |
| 1934 __ LoadIsolate(EAX); | 1940 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); |
| 1935 __ movzxb(EAX, Address(EAX, Isolate::single_step_offset())); | 1941 __ cmpl(EAX, Immediate(0)); |
| 1936 __ cmpl(EAX, Immediate(0)); | 1942 __ j(NOT_EQUAL, &stepping); |
| 1937 __ j(NOT_EQUAL, &stepping); | 1943 __ Bind(&done_stepping); |
| 1938 __ Bind(&done_stepping); | 1944 #endif |
| 1939 } | |
| 1940 | 1945 |
| 1941 const Register left = EAX; | 1946 const Register left = EAX; |
| 1942 const Register right = EDX; | 1947 const Register right = EDX; |
| 1943 const Register temp = ECX; | 1948 const Register temp = ECX; |
| 1944 __ movl(left, Address(ESP, 2 * kWordSize)); | 1949 __ movl(left, Address(ESP, 2 * kWordSize)); |
| 1945 __ movl(right, Address(ESP, 1 * kWordSize)); | 1950 __ movl(right, Address(ESP, 1 * kWordSize)); |
| 1946 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1951 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 1947 __ ret(); | 1952 __ ret(); |
| 1948 | 1953 |
| 1949 if (FLAG_support_debugger) { | 1954 #if !defined(PRODUCT) |
| 1950 __ Bind(&stepping); | 1955 __ Bind(&stepping); |
| 1951 __ EnterStubFrame(); | 1956 __ EnterStubFrame(); |
| 1952 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1957 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1953 __ LeaveFrame(); | 1958 __ LeaveFrame(); |
| 1954 __ jmp(&done_stepping); | 1959 __ jmp(&done_stepping); |
| 1955 } | 1960 #endif |
| 1956 } | 1961 } |
| 1957 | 1962 |
| 1958 // Called from optimized code only. | 1963 // Called from optimized code only. |
| 1959 // TOS + 0: return address | 1964 // TOS + 0: return address |
| 1960 // TOS + 1: right argument. | 1965 // TOS + 1: right argument. |
| 1961 // TOS + 2: left argument. | 1966 // TOS + 2: left argument. |
| 1962 // Returns ZF set. | 1967 // Returns ZF set. |
| 1963 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 1968 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
| 1964 Assembler* assembler) { | 1969 Assembler* assembler) { |
| 1965 const Register left = EAX; | 1970 const Register left = EAX; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2070 __ int3(); | 2075 __ int3(); |
| 2071 } | 2076 } |
| 2072 | 2077 |
| 2073 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { | 2078 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { |
| 2074 __ int3(); | 2079 __ int3(); |
| 2075 } | 2080 } |
| 2076 | 2081 |
| 2077 } // namespace dart | 2082 } // namespace dart |
| 2078 | 2083 |
| 2079 #endif // defined TARGET_ARCH_IA32 | 2084 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |