Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(846)

Side by Side Diff: runtime/vm/flow_graph_compiler_arm.cc

Issue 26823006: Record a correct deoptimization environment for slow-path code. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Use an environment value's representation to decide its size. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
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
592 // Generate runtime call. 592 // Generate runtime call.
593 // Load instantiator (R2) and its type arguments (R1). 593 // Load instantiator (R2) and its type arguments (R1).
594 __ ldm(IA, SP, (1 << R1) | (1 << R2)); 594 __ ldm(IA, SP, (1 << R1) | (1 << R2));
595 __ PushObject(Object::ZoneHandle()); // Make room for the result. 595 __ PushObject(Object::ZoneHandle()); // Make room for the result.
596 __ Push(R0); // Push the instance. 596 __ Push(R0); // Push the instance.
597 __ PushObject(type); // Push the type. 597 __ PushObject(type); // Push the type.
598 // Push instantiator (R2) and its type arguments (R1). 598 // Push instantiator (R2) and its type arguments (R1).
599 __ PushList((1 << R1) | (1 << R2)); 599 __ PushList((1 << R1) | (1 << R2));
600 __ LoadObject(R0, test_cache); 600 __ LoadObject(R0, test_cache);
601 __ Push(R0); 601 __ Push(R0);
602 GenerateCallRuntime(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs); 602 GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
603 // Pop the parameters supplied to the runtime entry. The result of the 603 // Pop the parameters supplied to the runtime entry. The result of the
604 // instanceof runtime call will be left as the result of the operation. 604 // instanceof runtime call will be left as the result of the operation.
605 __ Drop(5); 605 __ Drop(5);
606 if (negate_result) { 606 if (negate_result) {
607 __ Pop(R1); 607 __ Pop(R1);
608 __ LoadObject(R0, Bool::True()); 608 __ LoadObject(R0, Bool::True());
609 __ cmp(R1, ShifterOperand(R0)); 609 __ cmp(R1, ShifterOperand(R0));
610 __ b(&done, NE); 610 __ b(&done, NE);
611 __ LoadObject(R0, Bool::False()); 611 __ LoadObject(R0, Bool::False());
612 } else { 612 } else {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 } else { 671 } else {
672 const bool is_malbounded = dst_type.IsMalboundedWithError(&error); 672 const bool is_malbounded = dst_type.IsMalboundedWithError(&error);
673 ASSERT(is_malbounded); 673 ASSERT(is_malbounded);
674 } 674 }
675 const String& error_message = String::ZoneHandle( 675 const String& error_message = String::ZoneHandle(
676 Symbols::New(error.ToErrorCString())); 676 Symbols::New(error.ToErrorCString()));
677 __ PushObject(Object::ZoneHandle()); // Make room for the result. 677 __ PushObject(Object::ZoneHandle()); // Make room for the result.
678 __ Push(R0); // Push the source object. 678 __ Push(R0); // Push the source object.
679 __ PushObject(dst_name); // Push the name of the destination. 679 __ PushObject(dst_name); // Push the name of the destination.
680 __ PushObject(error_message); 680 __ PushObject(error_message);
681 GenerateCallRuntime(token_pos, 681 GenerateRuntimeCall(token_pos,
682 deopt_id, 682 deopt_id,
683 kMalformedTypeErrorRuntimeEntry, 683 kMalformedTypeErrorRuntimeEntry,
684 3, 684 3,
685 locs); 685 locs);
686 // We should never return here. 686 // We should never return here.
687 __ bkpt(0); 687 __ bkpt(0);
688 688
689 __ Bind(&is_assignable); // For a null object. 689 __ Bind(&is_assignable); // For a null object.
690 // Restore instantiator (R2) and its type arguments (R1). 690 // Restore instantiator (R2) and its type arguments (R1).
691 __ PopList((1 << R1) | (1 << R2)); 691 __ PopList((1 << R1) | (1 << R2));
692 return; 692 return;
693 } 693 }
694 694
695 // Generate inline type check, linking to runtime call if not assignable. 695 // Generate inline type check, linking to runtime call if not assignable.
696 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 696 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
697 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 697 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
698 &is_assignable, &runtime_call); 698 &is_assignable, &runtime_call);
699 699
700 __ Bind(&runtime_call); 700 __ Bind(&runtime_call);
701 // Load instantiator (R2) and its type arguments (R1). 701 // Load instantiator (R2) and its type arguments (R1).
702 __ ldm(IA, SP, (1 << R1) | (1 << R2)); 702 __ ldm(IA, SP, (1 << R1) | (1 << R2));
703 __ PushObject(Object::ZoneHandle()); // Make room for the result. 703 __ PushObject(Object::ZoneHandle()); // Make room for the result.
704 __ Push(R0); // Push the source object. 704 __ Push(R0); // Push the source object.
705 __ PushObject(dst_type); // Push the type of the destination. 705 __ PushObject(dst_type); // Push the type of the destination.
706 // Push instantiator (R2) and its type arguments (R1). 706 // Push instantiator (R2) and its type arguments (R1).
707 __ PushList((1 << R1) | (1 << R2)); 707 __ PushList((1 << R1) | (1 << R2));
708 __ PushObject(dst_name); // Push the name of the destination. 708 __ PushObject(dst_name); // Push the name of the destination.
709 __ LoadObject(R0, test_cache); 709 __ LoadObject(R0, test_cache);
710 __ Push(R0); 710 __ Push(R0);
711 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); 711 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
712 // Pop the parameters supplied to the runtime entry. The result of the 712 // Pop the parameters supplied to the runtime entry. The result of the
713 // type check runtime call is the checked value. 713 // type check runtime call is the checked value.
714 __ Drop(6); 714 __ Drop(6);
715 __ Pop(R0); 715 __ Pop(R0);
716 716
717 __ Bind(&is_assignable); 717 __ Bind(&is_assignable);
718 // Restore instantiator (R2) and its type arguments (R1). 718 // Restore instantiator (R2) and its type arguments (R1).
719 __ PopList((1 << R1) | (1 << R2)); 719 __ PopList((1 << R1) | (1 << R2));
720 } 720 }
721 721
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 if (is_optimizing()) { 1221 if (is_optimizing()) {
1222 AddDeoptIndexAtCall(deopt_id_after, token_pos); 1222 AddDeoptIndexAtCall(deopt_id_after, token_pos);
1223 } else { 1223 } else {
1224 // Add deoptimization continuation point after the call and before the 1224 // Add deoptimization continuation point after the call and before the
1225 // arguments are removed. 1225 // arguments are removed.
1226 AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_after, token_pos); 1226 AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_after, token_pos);
1227 } 1227 }
1228 } 1228 }
1229 1229
1230 1230
1231 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, 1231 void FlowGraphCompiler::GenerateRuntimeCall(intptr_t token_pos,
1232 intptr_t deopt_id, 1232 intptr_t deopt_id,
1233 const RuntimeEntry& entry, 1233 const RuntimeEntry& entry,
1234 intptr_t argument_count, 1234 intptr_t argument_count,
1235 LocationSummary* locs) { 1235 LocationSummary* locs) {
1236 __ CallRuntime(entry, argument_count); 1236 __ CallRuntime(entry, argument_count);
1237 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); 1237 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos);
1238 RecordSafepoint(locs); 1238 RecordSafepoint(locs);
1239 if (deopt_id != Isolate::kNoDeoptId) { 1239 if (deopt_id != Isolate::kNoDeoptId) {
1240 // Marks either the continuation point in unoptimized code or the 1240 // Marks either the continuation point in unoptimized code or the
1241 // deoptimization point in optimized code, after call. 1241 // deoptimization point in optimized code, after call.
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 token_pos); 1488 token_pos);
1489 // Stub returns result in flags (result of a cmpl, we need ZF computed). 1489 // Stub returns result in flags (result of a cmpl, we need ZF computed).
1490 __ Pop(right); 1490 __ Pop(right);
1491 __ Pop(left); 1491 __ Pop(left);
1492 } else { 1492 } else {
1493 __ cmp(left, ShifterOperand(right)); 1493 __ cmp(left, ShifterOperand(right));
1494 } 1494 }
1495 } 1495 }
1496 1496
1497 1497
1498 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and
1499 // FlowGraphCompiler::SlowPathEnvironmentFor.
1498 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { 1500 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
1499 // TODO(vegorov): consider saving only caller save (volatile) registers. 1501 // TODO(vegorov): consider saving only caller save (volatile) registers.
1500 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); 1502 const intptr_t fpu_regs_count = locs->live_registers()->FpuRegisterCount();
1501 if (fpu_regs_count > 0) { 1503 if (fpu_regs_count > 0) {
1502 __ AddImmediate(SP, -(fpu_regs_count * kFpuRegisterSize)); 1504 __ AddImmediate(SP, -(fpu_regs_count * kFpuRegisterSize));
1503 // Store fpu registers with the lowest register number at the lowest 1505 // Store fpu registers with the lowest register number at the lowest
1504 // address. 1506 // address.
1505 intptr_t offset = 0; 1507 intptr_t offset = 0;
1506 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { 1508 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) {
1507 QRegister fpu_reg = static_cast<QRegister>(reg_idx); 1509 QRegister fpu_reg = static_cast<QRegister>(reg_idx);
1508 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { 1510 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
1509 DRegister d1 = EvenDRegisterOf(fpu_reg); 1511 DRegister d1 = EvenDRegisterOf(fpu_reg);
1510 DRegister d2 = OddDRegisterOf(fpu_reg); 1512 DRegister d2 = OddDRegisterOf(fpu_reg);
(...skipping 18 matching lines...) Expand all
1529 1531
1530 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { 1532 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
1531 // General purpose registers have the lowest register number at the 1533 // General purpose registers have the lowest register number at the
1532 // lowest address. 1534 // lowest address.
1533 const intptr_t cpu_registers = locs->live_registers()->cpu_registers(); 1535 const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
1534 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); 1536 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
1535 if (cpu_registers != 0) { 1537 if (cpu_registers != 0) {
1536 __ PopList(cpu_registers); 1538 __ PopList(cpu_registers);
1537 } 1539 }
1538 1540
1539 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); 1541 const intptr_t fpu_regs_count = locs->live_registers()->FpuRegisterCount();
1540 if (fpu_regs_count > 0) { 1542 if (fpu_regs_count > 0) {
1541 // Fpu registers have the lowest register number at the lowest address. 1543 // Fpu registers have the lowest register number at the lowest address.
1542 intptr_t offset = 0; 1544 intptr_t offset = 0;
1543 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { 1545 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) {
1544 QRegister fpu_reg = static_cast<QRegister>(reg_idx); 1546 QRegister fpu_reg = static_cast<QRegister>(reg_idx);
1545 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { 1547 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
1546 DRegister d1 = EvenDRegisterOf(fpu_reg); 1548 DRegister d1 = EvenDRegisterOf(fpu_reg);
1547 DRegister d2 = OddDRegisterOf(fpu_reg); 1549 DRegister d2 = OddDRegisterOf(fpu_reg);
1548 // TOOD(regis): merge loads using vldmd instruction. 1550 // TOOD(regis): merge loads using vldmd instruction.
1549 __ vldrd(d1, Address(SP, offset)); 1551 __ vldrd(d1, Address(SP, offset));
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1911 DRegister dreg = EvenDRegisterOf(reg); 1913 DRegister dreg = EvenDRegisterOf(reg);
1912 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); 1914 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex));
1913 } 1915 }
1914 1916
1915 1917
1916 #undef __ 1918 #undef __
1917 1919
1918 } // namespace dart 1920 } // namespace dart
1919 1921
1920 #endif // defined TARGET_ARCH_ARM 1922 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698