| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 // Generate runtime call. | 605 // Generate runtime call. |
| 606 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. | 606 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. |
| 607 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. | 607 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. |
| 608 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 608 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 609 __ pushl(EAX); // Push the instance. | 609 __ pushl(EAX); // Push the instance. |
| 610 __ PushObject(type); // Push the type. | 610 __ PushObject(type); // Push the type. |
| 611 __ pushl(ECX); // Instantiator. | 611 __ pushl(ECX); // Instantiator. |
| 612 __ pushl(EDX); // Instantiator type arguments. | 612 __ pushl(EDX); // Instantiator type arguments. |
| 613 __ LoadObject(EAX, test_cache); | 613 __ LoadObject(EAX, test_cache); |
| 614 __ pushl(EAX); | 614 __ pushl(EAX); |
| 615 GenerateCallRuntime(token_pos, | 615 GenerateRuntimeCall(token_pos, |
| 616 deopt_id, | 616 deopt_id, |
| 617 kInstanceofRuntimeEntry, | 617 kInstanceofRuntimeEntry, |
| 618 5, | 618 5, |
| 619 locs); | 619 locs); |
| 620 // Pop the parameters supplied to the runtime entry. The result of the | 620 // Pop the parameters supplied to the runtime entry. The result of the |
| 621 // instanceof runtime call will be left as the result of the operation. | 621 // instanceof runtime call will be left as the result of the operation. |
| 622 __ Drop(5); | 622 __ Drop(5); |
| 623 if (negate_result) { | 623 if (negate_result) { |
| 624 __ popl(EDX); | 624 __ popl(EDX); |
| 625 __ LoadObject(EAX, Bool::True()); | 625 __ LoadObject(EAX, Bool::True()); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 } else { | 693 } else { |
| 694 const bool is_malbounded = dst_type.IsMalboundedWithError(&error); | 694 const bool is_malbounded = dst_type.IsMalboundedWithError(&error); |
| 695 ASSERT(is_malbounded); | 695 ASSERT(is_malbounded); |
| 696 } | 696 } |
| 697 const String& error_message = String::ZoneHandle( | 697 const String& error_message = String::ZoneHandle( |
| 698 Symbols::New(error.ToErrorCString())); | 698 Symbols::New(error.ToErrorCString())); |
| 699 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 699 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 700 __ pushl(EAX); // Push the source object. | 700 __ pushl(EAX); // Push the source object. |
| 701 __ PushObject(dst_name); // Push the name of the destination. | 701 __ PushObject(dst_name); // Push the name of the destination. |
| 702 __ PushObject(error_message); | 702 __ PushObject(error_message); |
| 703 GenerateCallRuntime(token_pos, | 703 GenerateRuntimeCall(token_pos, |
| 704 deopt_id, | 704 deopt_id, |
| 705 kMalformedTypeErrorRuntimeEntry, | 705 kMalformedTypeErrorRuntimeEntry, |
| 706 3, | 706 3, |
| 707 locs); | 707 locs); |
| 708 // We should never return here. | 708 // We should never return here. |
| 709 __ int3(); | 709 __ int3(); |
| 710 | 710 |
| 711 __ Bind(&is_assignable); // For a null object. | 711 __ Bind(&is_assignable); // For a null object. |
| 712 __ popl(EDX); // Remove pushed instantiator type arguments. | 712 __ popl(EDX); // Remove pushed instantiator type arguments. |
| 713 __ popl(ECX); // Remove pushed instantiator. | 713 __ popl(ECX); // Remove pushed instantiator. |
| 714 return; | 714 return; |
| 715 } | 715 } |
| 716 | 716 |
| 717 // Generate inline type check, linking to runtime call if not assignable. | 717 // Generate inline type check, linking to runtime call if not assignable. |
| 718 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); | 718 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); |
| 719 test_cache = GenerateInlineInstanceof(token_pos, dst_type, | 719 test_cache = GenerateInlineInstanceof(token_pos, dst_type, |
| 720 &is_assignable, &runtime_call); | 720 &is_assignable, &runtime_call); |
| 721 | 721 |
| 722 __ Bind(&runtime_call); | 722 __ Bind(&runtime_call); |
| 723 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. | 723 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. |
| 724 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. | 724 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. |
| 725 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 725 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 726 __ pushl(EAX); // Push the source object. | 726 __ pushl(EAX); // Push the source object. |
| 727 __ PushObject(dst_type); // Push the type of the destination. | 727 __ PushObject(dst_type); // Push the type of the destination. |
| 728 __ pushl(ECX); // Instantiator. | 728 __ pushl(ECX); // Instantiator. |
| 729 __ pushl(EDX); // Instantiator type arguments. | 729 __ pushl(EDX); // Instantiator type arguments. |
| 730 __ PushObject(dst_name); // Push the name of the destination. | 730 __ PushObject(dst_name); // Push the name of the destination. |
| 731 __ LoadObject(EAX, test_cache); | 731 __ LoadObject(EAX, test_cache); |
| 732 __ pushl(EAX); | 732 __ pushl(EAX); |
| 733 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); | 733 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); |
| 734 // Pop the parameters supplied to the runtime entry. The result of the | 734 // Pop the parameters supplied to the runtime entry. The result of the |
| 735 // type check runtime call is the checked value. | 735 // type check runtime call is the checked value. |
| 736 __ Drop(6); | 736 __ Drop(6); |
| 737 __ popl(EAX); | 737 __ popl(EAX); |
| 738 | 738 |
| 739 __ Bind(&is_assignable); | 739 __ Bind(&is_assignable); |
| 740 __ popl(EDX); // Remove pushed instantiator type arguments. | 740 __ popl(EDX); // Remove pushed instantiator type arguments. |
| 741 __ popl(ECX); // Remove pushed instantiator. | 741 __ popl(ECX); // Remove pushed instantiator. |
| 742 } | 742 } |
| 743 | 743 |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1230 if (is_optimizing()) { | 1230 if (is_optimizing()) { |
| 1231 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1231 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
| 1232 } else { | 1232 } else { |
| 1233 // Add deoptimization continuation point after the call and before the | 1233 // Add deoptimization continuation point after the call and before the |
| 1234 // arguments are removed. | 1234 // arguments are removed. |
| 1235 AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_after, token_pos); | 1235 AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_after, token_pos); |
| 1236 } | 1236 } |
| 1237 } | 1237 } |
| 1238 | 1238 |
| 1239 | 1239 |
| 1240 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, | 1240 void FlowGraphCompiler::GenerateRuntimeCall(intptr_t token_pos, |
| 1241 intptr_t deopt_id, | 1241 intptr_t deopt_id, |
| 1242 const RuntimeEntry& entry, | 1242 const RuntimeEntry& entry, |
| 1243 intptr_t argument_count, | 1243 intptr_t argument_count, |
| 1244 LocationSummary* locs) { | 1244 LocationSummary* locs) { |
| 1245 __ CallRuntime(entry, argument_count); | 1245 __ CallRuntime(entry, argument_count); |
| 1246 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); | 1246 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); |
| 1247 RecordSafepoint(locs); | 1247 RecordSafepoint(locs); |
| 1248 if (deopt_id != Isolate::kNoDeoptId) { | 1248 if (deopt_id != Isolate::kNoDeoptId) { |
| 1249 // Marks either the continuation point in unoptimized code or the | 1249 // Marks either the continuation point in unoptimized code or the |
| 1250 // deoptimization point in optimized code, after call. | 1250 // deoptimization point in optimized code, after call. |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1498 token_pos); | 1498 token_pos); |
| 1499 // Stub returns result in flags (result of a cmpl, we need ZF computed). | 1499 // Stub returns result in flags (result of a cmpl, we need ZF computed). |
| 1500 __ popl(right); | 1500 __ popl(right); |
| 1501 __ popl(left); | 1501 __ popl(left); |
| 1502 } else { | 1502 } else { |
| 1503 __ cmpl(left, right); | 1503 __ cmpl(left, right); |
| 1504 } | 1504 } |
| 1505 } | 1505 } |
| 1506 | 1506 |
| 1507 | 1507 |
| 1508 // This function must be in sync with FlowGraphCompiler::RecordSafepoint. | 1508 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and |
| 1509 // FlowGraphCompiler::SlowPathEnvironmentFor. |
| 1509 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { | 1510 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| 1510 // TODO(vegorov): consider saving only caller save (volatile) registers. | 1511 // TODO(vegorov): consider saving only caller save (volatile) registers. |
| 1511 const intptr_t xmm_regs_count = locs->live_registers()->fpu_regs_count(); | 1512 const intptr_t xmm_regs_count = locs->live_registers()->FpuRegisterCount(); |
| 1512 if (xmm_regs_count > 0) { | 1513 if (xmm_regs_count > 0) { |
| 1513 __ subl(ESP, Immediate(xmm_regs_count * kFpuRegisterSize)); | 1514 __ subl(ESP, Immediate(xmm_regs_count * kFpuRegisterSize)); |
| 1514 // Store XMM registers with the lowest register number at the lowest | 1515 // Store XMM registers with the lowest register number at the lowest |
| 1515 // address. | 1516 // address. |
| 1516 intptr_t offset = 0; | 1517 intptr_t offset = 0; |
| 1517 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 1518 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1518 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 1519 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1519 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { | 1520 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { |
| 1520 __ movups(Address(ESP, offset), xmm_reg); | 1521 __ movups(Address(ESP, offset), xmm_reg); |
| 1521 offset += kFpuRegisterSize; | 1522 offset += kFpuRegisterSize; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1538 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { | 1539 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { |
| 1539 // General purpose registers have the highest register number at the | 1540 // General purpose registers have the highest register number at the |
| 1540 // lowest address. | 1541 // lowest address. |
| 1541 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { | 1542 for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) { |
| 1542 Register reg = static_cast<Register>(reg_idx); | 1543 Register reg = static_cast<Register>(reg_idx); |
| 1543 if (locs->live_registers()->ContainsRegister(reg)) { | 1544 if (locs->live_registers()->ContainsRegister(reg)) { |
| 1544 __ popl(reg); | 1545 __ popl(reg); |
| 1545 } | 1546 } |
| 1546 } | 1547 } |
| 1547 | 1548 |
| 1548 const intptr_t xmm_regs_count = locs->live_registers()->fpu_regs_count(); | 1549 const intptr_t xmm_regs_count = locs->live_registers()->FpuRegisterCount(); |
| 1549 if (xmm_regs_count > 0) { | 1550 if (xmm_regs_count > 0) { |
| 1550 // XMM registers have the lowest register number at the lowest address. | 1551 // XMM registers have the lowest register number at the lowest address. |
| 1551 intptr_t offset = 0; | 1552 intptr_t offset = 0; |
| 1552 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 1553 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 1553 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 1554 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 1554 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { | 1555 if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) { |
| 1555 __ movups(xmm_reg, Address(ESP, offset)); | 1556 __ movups(xmm_reg, Address(ESP, offset)); |
| 1556 offset += kFpuRegisterSize; | 1557 offset += kFpuRegisterSize; |
| 1557 } | 1558 } |
| 1558 } | 1559 } |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1915 __ movups(reg, Address(ESP, 0)); | 1916 __ movups(reg, Address(ESP, 0)); |
| 1916 __ addl(ESP, Immediate(kFpuRegisterSize)); | 1917 __ addl(ESP, Immediate(kFpuRegisterSize)); |
| 1917 } | 1918 } |
| 1918 | 1919 |
| 1919 | 1920 |
| 1920 #undef __ | 1921 #undef __ |
| 1921 | 1922 |
| 1922 } // namespace dart | 1923 } // namespace dart |
| 1923 | 1924 |
| 1924 #endif // defined TARGET_ARCH_IA32 | 1925 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |