| 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" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 // Generate runtime call. | 592 // Generate runtime call. |
| 593 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 593 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 594 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. | 594 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. |
| 595 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. | 595 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. |
| 596 __ pushq(RAX); // Push the instance. | 596 __ pushq(RAX); // Push the instance. |
| 597 __ PushObject(type, PP); // Push the type. | 597 __ PushObject(type, PP); // Push the type. |
| 598 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null. | 598 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null. |
| 599 __ pushq(RDX); // Instantiator type arguments. | 599 __ pushq(RDX); // Instantiator type arguments. |
| 600 __ LoadObject(RAX, test_cache, PP); | 600 __ LoadObject(RAX, test_cache, PP); |
| 601 __ pushq(RAX); | 601 __ pushq(RAX); |
| 602 GenerateCallRuntime(token_pos, | 602 GenerateRuntimeCall(token_pos, |
| 603 deopt_id, | 603 deopt_id, |
| 604 kInstanceofRuntimeEntry, | 604 kInstanceofRuntimeEntry, |
| 605 5, | 605 5, |
| 606 locs); | 606 locs); |
| 607 // Pop the parameters supplied to the runtime entry. The result of the | 607 // Pop the parameters supplied to the runtime entry. The result of the |
| 608 // instanceof runtime call will be left as the result of the operation. | 608 // instanceof runtime call will be left as the result of the operation. |
| 609 __ Drop(5); | 609 __ Drop(5); |
| 610 if (negate_result) { | 610 if (negate_result) { |
| 611 __ popq(RDX); | 611 __ popq(RDX); |
| 612 __ LoadObject(RAX, Bool::True(), PP); | 612 __ LoadObject(RAX, Bool::True(), PP); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 } else { | 675 } else { |
| 676 const bool is_malbounded = dst_type.IsMalboundedWithError(&error); | 676 const bool is_malbounded = dst_type.IsMalboundedWithError(&error); |
| 677 ASSERT(is_malbounded); | 677 ASSERT(is_malbounded); |
| 678 } | 678 } |
| 679 const String& error_message = String::ZoneHandle( | 679 const String& error_message = String::ZoneHandle( |
| 680 Symbols::New(error.ToErrorCString())); | 680 Symbols::New(error.ToErrorCString())); |
| 681 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. | 681 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. |
| 682 __ pushq(RAX); // Push the source object. | 682 __ pushq(RAX); // Push the source object. |
| 683 __ PushObject(dst_name, PP); // Push the name of the destination. | 683 __ PushObject(dst_name, PP); // Push the name of the destination. |
| 684 __ PushObject(error_message, PP); | 684 __ PushObject(error_message, PP); |
| 685 GenerateCallRuntime(token_pos, | 685 GenerateRuntimeCall(token_pos, |
| 686 deopt_id, | 686 deopt_id, |
| 687 kMalformedTypeErrorRuntimeEntry, | 687 kMalformedTypeErrorRuntimeEntry, |
| 688 3, | 688 3, |
| 689 locs); | 689 locs); |
| 690 // We should never return here. | 690 // We should never return here. |
| 691 __ int3(); | 691 __ int3(); |
| 692 | 692 |
| 693 __ Bind(&is_assignable); // For a null object. | 693 __ Bind(&is_assignable); // For a null object. |
| 694 __ popq(RDX); // Remove pushed instantiator type arguments. | 694 __ popq(RDX); // Remove pushed instantiator type arguments. |
| 695 __ popq(RCX); // Remove pushed instantiator. | 695 __ popq(RCX); // Remove pushed instantiator. |
| 696 return; | 696 return; |
| 697 } | 697 } |
| 698 | 698 |
| 699 // Generate inline type check, linking to runtime call if not assignable. | 699 // Generate inline type check, linking to runtime call if not assignable. |
| 700 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); | 700 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); |
| 701 test_cache = GenerateInlineInstanceof(token_pos, dst_type, | 701 test_cache = GenerateInlineInstanceof(token_pos, dst_type, |
| 702 &is_assignable, &runtime_call); | 702 &is_assignable, &runtime_call); |
| 703 | 703 |
| 704 __ Bind(&runtime_call); | 704 __ Bind(&runtime_call); |
| 705 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 705 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 706 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. | 706 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. |
| 707 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. | 707 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. |
| 708 __ pushq(RAX); // Push the source object. | 708 __ pushq(RAX); // Push the source object. |
| 709 __ PushObject(dst_type, PP); // Push the type of the destination. | 709 __ PushObject(dst_type, PP); // Push the type of the destination. |
| 710 __ pushq(RCX); // Instantiator. | 710 __ pushq(RCX); // Instantiator. |
| 711 __ pushq(RDX); // Instantiator type arguments. | 711 __ pushq(RDX); // Instantiator type arguments. |
| 712 __ PushObject(dst_name, PP); // Push the name of the destination. | 712 __ PushObject(dst_name, PP); // Push the name of the destination. |
| 713 __ LoadObject(RAX, test_cache, PP); | 713 __ LoadObject(RAX, test_cache, PP); |
| 714 __ pushq(RAX); | 714 __ pushq(RAX); |
| 715 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); | 715 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); |
| 716 // Pop the parameters supplied to the runtime entry. The result of the | 716 // Pop the parameters supplied to the runtime entry. The result of the |
| 717 // type check runtime call is the checked value. | 717 // type check runtime call is the checked value. |
| 718 __ Drop(6); | 718 __ Drop(6); |
| 719 __ popq(RAX); | 719 __ popq(RAX); |
| 720 | 720 |
| 721 __ Bind(&is_assignable); | 721 __ Bind(&is_assignable); |
| 722 __ popq(RDX); // Remove pushed instantiator type arguments. | 722 __ popq(RDX); // Remove pushed instantiator type arguments. |
| 723 __ popq(RCX); // Remove pushed instantiator. | 723 __ popq(RCX); // Remove pushed instantiator. |
| 724 } | 724 } |
| 725 | 725 |
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 if (is_optimizing()) { | 1265 if (is_optimizing()) { |
| 1266 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1266 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
| 1267 } else { | 1267 } else { |
| 1268 // Add deoptimization continuation point after the call and before the | 1268 // Add deoptimization continuation point after the call and before the |
| 1269 // arguments are removed. | 1269 // arguments are removed. |
| 1270 AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_after, token_pos); | 1270 AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_after, token_pos); |
| 1271 } | 1271 } |
| 1272 } | 1272 } |
| 1273 | 1273 |
| 1274 | 1274 |
| 1275 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, | 1275 void FlowGraphCompiler::GenerateRuntimeCall(intptr_t token_pos, |
| 1276 intptr_t deopt_id, | 1276 intptr_t deopt_id, |
| 1277 const RuntimeEntry& entry, | 1277 const RuntimeEntry& entry, |
| 1278 intptr_t argument_count, | 1278 intptr_t argument_count, |
| 1279 LocationSummary* locs) { | 1279 LocationSummary* locs) { |
| 1280 __ CallRuntime(entry, argument_count); | 1280 __ CallRuntime(entry, argument_count); |
| 1281 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); | 1281 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); |
| 1282 RecordSafepoint(locs); | 1282 RecordSafepoint(locs); |
| 1283 if (deopt_id != Isolate::kNoDeoptId) { | 1283 if (deopt_id != Isolate::kNoDeoptId) { |
| 1284 // Marks either the continuation point in unoptimized code or the | 1284 // Marks either the continuation point in unoptimized code or the |
| 1285 // deoptimization point in optimized code, after call. | 1285 // deoptimization point in optimized code, after call. |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 token_pos); | 1534 token_pos); |
| 1535 // Stub returns result in flags (result of a cmpl, we need ZF computed). | 1535 // Stub returns result in flags (result of a cmpl, we need ZF computed). |
| 1536 __ popq(right); | 1536 __ popq(right); |
| 1537 __ popq(left); | 1537 __ popq(left); |
| 1538 } else { | 1538 } else { |
| 1539 __ cmpl(left, right); | 1539 __ cmpl(left, right); |
| 1540 } | 1540 } |
| 1541 } | 1541 } |
| 1542 | 1542 |
| 1543 | 1543 |
| 1544 // This function must be in sync with FlowGraphCompiler::RecordSafepoint. | 1544 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and |
| 1545 // FlowGraphCompiler::SlowPathEnvironmentFor. |
| 1545 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { | 1546 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| 1546 // TODO(vegorov): consider saving only caller save (volatile) registers. | 1547 // TODO(vegorov): consider saving only caller save (volatile) registers. |
| 1547 const intptr_t xmm_regs_count = locs->live_registers()->fpu_regs_count(); | 1548 const intptr_t xmm_regs_count = locs->live_registers()->FpuRegisterCount(); |
| 1548 if (xmm_regs_count > 0) { | 1549 if (xmm_regs_count > 0) { |
| 1549 __ AddImmediate(RSP, Immediate(-xmm_regs_count * kFpuRegisterSize), PP); | 1550 __ AddImmediate(RSP, Immediate(-xmm_regs_count * kFpuRegisterSize), PP); |
| 1550 // Store XMM registers with the lowest register number at the lowest | 1551 // Store XMM registers with the lowest register number at the lowest |
| 1551 // address. | 1552 // address. |
| 1552 intptr_t offset = 0; | 1553 intptr_t offset = 0; |
| 1553 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 1554 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1554 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 1555 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1555 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { | 1556 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { |
| 1556 __ movups(Address(RSP, offset), xmm_reg); | 1557 __ movups(Address(RSP, offset), xmm_reg); |
| 1557 offset += kFpuRegisterSize; | 1558 offset += kFpuRegisterSize; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1574 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { | 1575 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { |
| 1575 // General purpose registers have the highest register number at the | 1576 // General purpose registers have the highest register number at the |
| 1576 // lowest address. | 1577 // lowest address. |
| 1577 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { | 1578 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { |
| 1578 Register reg = static_cast<Register>(reg_idx); | 1579 Register reg = static_cast<Register>(reg_idx); |
| 1579 if (locs->live_registers()->ContainsRegister(reg)) { | 1580 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1580 __ popq(reg); | 1581 __ popq(reg); |
| 1581 } | 1582 } |
| 1582 } | 1583 } |
| 1583 | 1584 |
| 1584 const intptr_t xmm_regs_count = locs->live_registers()->fpu_regs_count(); | 1585 const intptr_t xmm_regs_count = locs->live_registers()->FpuRegisterCount(); |
| 1585 if (xmm_regs_count > 0) { | 1586 if (xmm_regs_count > 0) { |
| 1586 // XMM registers have the lowest register number at the lowest address. | 1587 // XMM registers have the lowest register number at the lowest address. |
| 1587 intptr_t offset = 0; | 1588 intptr_t offset = 0; |
| 1588 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 1589 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1589 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 1590 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1590 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { | 1591 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { |
| 1591 __ movups(xmm_reg, Address(RSP, offset)); | 1592 __ movups(xmm_reg, Address(RSP, offset)); |
| 1592 offset += kFpuRegisterSize; | 1593 offset += kFpuRegisterSize; |
| 1593 } | 1594 } |
| 1594 } | 1595 } |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1934 __ movups(reg, Address(RSP, 0)); | 1935 __ movups(reg, Address(RSP, 0)); |
| 1935 __ AddImmediate(RSP, Immediate(kFpuRegisterSize), PP); | 1936 __ AddImmediate(RSP, Immediate(kFpuRegisterSize), PP); |
| 1936 } | 1937 } |
| 1937 | 1938 |
| 1938 | 1939 |
| 1939 #undef __ | 1940 #undef __ |
| 1940 | 1941 |
| 1941 } // namespace dart | 1942 } // namespace dart |
| 1942 | 1943 |
| 1943 #endif // defined TARGET_ARCH_X64 | 1944 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |