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" |
(...skipping 1337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); | 1348 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); |
1349 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1349 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1350 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); | 1350 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); |
1351 __ cmpq(RCX, Immediate(num_args)); | 1351 __ cmpq(RCX, Immediate(num_args)); |
1352 __ j(EQUAL, &ok, Assembler::kNearJump); | 1352 __ j(EQUAL, &ok, Assembler::kNearJump); |
1353 __ Stop("Incorrect stub for IC data"); | 1353 __ Stop("Incorrect stub for IC data"); |
1354 __ Bind(&ok); | 1354 __ Bind(&ok); |
1355 } | 1355 } |
1356 #endif // DEBUG | 1356 #endif // DEBUG |
1357 | 1357 |
| 1358 #if !defined(PRODUCT) |
1358 Label stepping, done_stepping; | 1359 Label stepping, done_stepping; |
1359 if (FLAG_support_debugger && !optimized) { | 1360 if (!optimized) { |
1360 __ Comment("Check single stepping"); | 1361 __ Comment("Check single stepping"); |
1361 __ LoadIsolate(RAX); | 1362 __ LoadIsolate(RAX); |
1362 __ cmpb(Address(RAX, Isolate::single_step_offset()), Immediate(0)); | 1363 __ cmpb(Address(RAX, Isolate::single_step_offset()), Immediate(0)); |
1363 __ j(NOT_EQUAL, &stepping); | 1364 __ j(NOT_EQUAL, &stepping); |
1364 __ Bind(&done_stepping); | 1365 __ Bind(&done_stepping); |
1365 } | 1366 } |
| 1367 #endif |
1366 | 1368 |
1367 Label not_smi_or_overflow; | 1369 Label not_smi_or_overflow; |
1368 if (kind != Token::kILLEGAL) { | 1370 if (kind != Token::kILLEGAL) { |
1369 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1371 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
1370 } | 1372 } |
1371 __ Bind(¬_smi_or_overflow); | 1373 __ Bind(¬_smi_or_overflow); |
1372 | 1374 |
1373 __ Comment("Extract ICData initial values and receiver cid"); | 1375 __ Comment("Extract ICData initial values and receiver cid"); |
1374 // Load arguments descriptor into R10. | 1376 // Load arguments descriptor into R10. |
1375 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 1377 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1471 __ addq(Address(R13, count_offset), Immediate(Smi::RawValue(1))); | 1473 __ addq(Address(R13, count_offset), Immediate(Smi::RawValue(1))); |
1472 } | 1474 } |
1473 | 1475 |
1474 __ Comment("Call target"); | 1476 __ Comment("Call target"); |
1475 __ Bind(&call_target_function); | 1477 __ Bind(&call_target_function); |
1476 // RAX: Target function. | 1478 // RAX: Target function. |
1477 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 1479 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
1478 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); | 1480 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); |
1479 __ jmp(RCX); | 1481 __ jmp(RCX); |
1480 | 1482 |
1481 if (FLAG_support_debugger && !optimized) { | 1483 #if !defined(PRODUCT) |
| 1484 if (!optimized) { |
1482 __ Bind(&stepping); | 1485 __ Bind(&stepping); |
1483 __ EnterStubFrame(); | 1486 __ EnterStubFrame(); |
1484 __ pushq(RBX); | 1487 __ pushq(RBX); |
1485 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1488 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1486 __ popq(RBX); | 1489 __ popq(RBX); |
1487 __ RestoreCodePointer(); | 1490 __ RestoreCodePointer(); |
1488 __ LeaveStubFrame(); | 1491 __ LeaveStubFrame(); |
1489 __ jmp(&done_stepping); | 1492 __ jmp(&done_stepping); |
1490 } | 1493 } |
| 1494 #endif |
1491 } | 1495 } |
1492 | 1496 |
1493 // Use inline cache data array to invoke the target or continue in inline | 1497 // Use inline cache data array to invoke the target or continue in inline |
1494 // cache miss handler. Stub for 1-argument check (receiver class). | 1498 // cache miss handler. Stub for 1-argument check (receiver class). |
1495 // RBX: Inline cache data object. | 1499 // RBX: Inline cache data object. |
1496 // TOS(0): Return address. | 1500 // TOS(0): Return address. |
1497 // Inline cache data object structure: | 1501 // Inline cache data object structure: |
1498 // 0: function-name | 1502 // 0: function-name |
1499 // 1: N, number of arguments checked. | 1503 // 1: N, number of arguments checked. |
1500 // 2 .. (length - 1): group of checks, each check containing: | 1504 // 2 .. (length - 1): group of checks, each check containing: |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1571 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); | 1575 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); |
1572 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1576 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1573 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); | 1577 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); |
1574 __ cmpq(RCX, Immediate(0)); | 1578 __ cmpq(RCX, Immediate(0)); |
1575 __ j(EQUAL, &ok, Assembler::kNearJump); | 1579 __ j(EQUAL, &ok, Assembler::kNearJump); |
1576 __ Stop("Incorrect IC data for unoptimized static call"); | 1580 __ Stop("Incorrect IC data for unoptimized static call"); |
1577 __ Bind(&ok); | 1581 __ Bind(&ok); |
1578 } | 1582 } |
1579 #endif // DEBUG | 1583 #endif // DEBUG |
1580 | 1584 |
| 1585 #if !defined(PRODUCT) |
1581 // Check single stepping. | 1586 // Check single stepping. |
1582 Label stepping, done_stepping; | 1587 Label stepping, done_stepping; |
1583 if (FLAG_support_debugger) { | 1588 __ LoadIsolate(RAX); |
1584 __ LoadIsolate(RAX); | 1589 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
1585 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1590 __ cmpq(RAX, Immediate(0)); |
1586 __ cmpq(RAX, Immediate(0)); | |
1587 #if defined(DEBUG) | 1591 #if defined(DEBUG) |
1588 static const bool kJumpLength = Assembler::kFarJump; | 1592 static const bool kJumpLength = Assembler::kFarJump; |
1589 #else | 1593 #else |
1590 static const bool kJumpLength = Assembler::kNearJump; | 1594 static const bool kJumpLength = Assembler::kNearJump; |
1591 #endif // DEBUG | 1595 #endif // DEBUG |
1592 __ j(NOT_EQUAL, &stepping, kJumpLength); | 1596 __ j(NOT_EQUAL, &stepping, kJumpLength); |
1593 __ Bind(&done_stepping); | 1597 __ Bind(&done_stepping); |
1594 } | 1598 #endif |
1595 | 1599 |
1596 // RBX: IC data object (preserved). | 1600 // RBX: IC data object (preserved). |
1597 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); | 1601 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
1598 // R12: ic_data_array with entries: target functions and count. | 1602 // R12: ic_data_array with entries: target functions and count. |
1599 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1603 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
1600 // R12: points directly to the first ic data array element. | 1604 // R12: points directly to the first ic data array element. |
1601 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1605 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1602 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1606 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1603 | 1607 |
1604 if (FLAG_optimization_counter_threshold >= 0) { | 1608 if (FLAG_optimization_counter_threshold >= 0) { |
1605 // Increment count for this call, ignore overflow. | 1609 // Increment count for this call, ignore overflow. |
1606 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); | 1610 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); |
1607 } | 1611 } |
1608 | 1612 |
1609 // Load arguments descriptor into R10. | 1613 // Load arguments descriptor into R10. |
1610 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 1614 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
1611 | 1615 |
1612 // Get function and call it, if possible. | 1616 // Get function and call it, if possible. |
1613 __ movq(RAX, Address(R12, target_offset)); | 1617 __ movq(RAX, Address(R12, target_offset)); |
1614 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 1618 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
1615 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); | 1619 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); |
1616 __ jmp(RCX); | 1620 __ jmp(RCX); |
1617 | 1621 |
1618 if (FLAG_support_debugger) { | 1622 #if !defined(PRODUCT) |
1619 __ Bind(&stepping); | 1623 __ Bind(&stepping); |
1620 __ EnterStubFrame(); | 1624 __ EnterStubFrame(); |
1621 __ pushq(RBX); // Preserve IC data object. | 1625 __ pushq(RBX); // Preserve IC data object. |
1622 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1626 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1623 __ popq(RBX); | 1627 __ popq(RBX); |
1624 __ RestoreCodePointer(); | 1628 __ RestoreCodePointer(); |
1625 __ LeaveStubFrame(); | 1629 __ LeaveStubFrame(); |
1626 __ jmp(&done_stepping, Assembler::kNearJump); | 1630 __ jmp(&done_stepping, Assembler::kNearJump); |
1627 } | 1631 #endif |
1628 } | 1632 } |
1629 | 1633 |
1630 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1634 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
1631 GenerateUsageCounterIncrement(assembler, RCX); | 1635 GenerateUsageCounterIncrement(assembler, RCX); |
1632 GenerateNArgsCheckInlineCacheStub( | 1636 GenerateNArgsCheckInlineCacheStub( |
1633 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1637 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
1634 } | 1638 } |
1635 | 1639 |
1636 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1640 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1637 GenerateUsageCounterIncrement(assembler, RCX); | 1641 GenerateUsageCounterIncrement(assembler, RCX); |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1974 __ Bind(&done); | 1978 __ Bind(&done); |
1975 } | 1979 } |
1976 | 1980 |
1977 // Called only from unoptimized code. All relevant registers have been saved. | 1981 // Called only from unoptimized code. All relevant registers have been saved. |
1978 // TOS + 0: return address | 1982 // TOS + 0: return address |
1979 // TOS + 1: right argument. | 1983 // TOS + 1: right argument. |
1980 // TOS + 2: left argument. | 1984 // TOS + 2: left argument. |
1981 // Returns ZF set. | 1985 // Returns ZF set. |
1982 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 1986 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
1983 Assembler* assembler) { | 1987 Assembler* assembler) { |
| 1988 #if !defined(PRODUCT) |
1984 // Check single stepping. | 1989 // Check single stepping. |
1985 Label stepping, done_stepping; | 1990 Label stepping, done_stepping; |
1986 if (FLAG_support_debugger) { | 1991 __ LoadIsolate(RAX); |
1987 __ LoadIsolate(RAX); | 1992 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
1988 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1993 __ cmpq(RAX, Immediate(0)); |
1989 __ cmpq(RAX, Immediate(0)); | 1994 __ j(NOT_EQUAL, &stepping); |
1990 __ j(NOT_EQUAL, &stepping); | 1995 __ Bind(&done_stepping); |
1991 __ Bind(&done_stepping); | 1996 #endif |
1992 } | |
1993 | 1997 |
1994 const Register left = RAX; | 1998 const Register left = RAX; |
1995 const Register right = RDX; | 1999 const Register right = RDX; |
1996 | 2000 |
1997 __ movq(left, Address(RSP, 2 * kWordSize)); | 2001 __ movq(left, Address(RSP, 2 * kWordSize)); |
1998 __ movq(right, Address(RSP, 1 * kWordSize)); | 2002 __ movq(right, Address(RSP, 1 * kWordSize)); |
1999 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2003 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
2000 __ ret(); | 2004 __ ret(); |
2001 | 2005 |
2002 if (FLAG_support_debugger) { | 2006 #if !defined(PRODUCT) |
2003 __ Bind(&stepping); | 2007 __ Bind(&stepping); |
2004 __ EnterStubFrame(); | 2008 __ EnterStubFrame(); |
2005 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 2009 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
2006 __ RestoreCodePointer(); | 2010 __ RestoreCodePointer(); |
2007 __ LeaveStubFrame(); | 2011 __ LeaveStubFrame(); |
2008 __ jmp(&done_stepping); | 2012 __ jmp(&done_stepping); |
2009 } | 2013 #endif |
2010 } | 2014 } |
2011 | 2015 |
2012 // Called from optimized code only. | 2016 // Called from optimized code only. |
2013 // TOS + 0: return address | 2017 // TOS + 0: return address |
2014 // TOS + 1: right argument. | 2018 // TOS + 1: right argument. |
2015 // TOS + 2: left argument. | 2019 // TOS + 2: left argument. |
2016 // Returns ZF set. | 2020 // Returns ZF set. |
2017 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 2021 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
2018 Assembler* assembler) { | 2022 Assembler* assembler) { |
2019 const Register left = RAX; | 2023 const Register left = RAX; |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2256 __ int3(); | 2260 __ int3(); |
2257 } | 2261 } |
2258 | 2262 |
2259 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { | 2263 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { |
2260 __ int3(); | 2264 __ int3(); |
2261 } | 2265 } |
2262 | 2266 |
2263 } // namespace dart | 2267 } // namespace dart |
2264 | 2268 |
2265 #endif // defined TARGET_ARCH_X64 | 2269 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |