diff options
author | Vladimir Marko <vmarko@google.com> | 2015-02-16 13:05:59 +0000 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2015-02-19 17:08:25 +0000 |
commit | 6ce3eba0f2e6e505ed408cdc40d213c8a512238d (patch) | |
tree | 5f7ced5c710ada776fa2e2624a05a0d414ed8b39 /compiler/dex/quick/x86/call_x86.cc | |
parent | 1b472546657d31d38883373d8340d1441281a6a5 (diff) | |
download | android_art-6ce3eba0f2e6e505ed408cdc40d213c8a512238d.tar.gz android_art-6ce3eba0f2e6e505ed408cdc40d213c8a512238d.tar.bz2 android_art-6ce3eba0f2e6e505ed408cdc40d213c8a512238d.zip |
Add suspend checks to special methods.
Generate suspend checks at the beginning of special methods.
If we need to call to runtime, go to the slow path where we
create a simplified but valid frame, spill all arguments,
call art_quick_test_suspend, restore necessary arguments and
return back to the fast path. This keeps the fast path
overhead to a minimum.
Bug: 19245639
Change-Id: I3de5aee783943941322a49c4cf2c4c94411dbaa2
Diffstat (limited to 'compiler/dex/quick/x86/call_x86.cc')
-rw-r--r-- | compiler/dex/quick/x86/call_x86.cc | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc index 284e8f6c0a..f964691dac 100644 --- a/compiler/dex/quick/x86/call_x86.cc +++ b/compiler/dex/quick/x86/call_x86.cc @@ -272,6 +272,41 @@ void X86Mir2Lir::GenSpecialExitSequence() { NewLIR0(kX86Ret); } +void X86Mir2Lir::GenSpecialEntryForSuspend() { + // Keep 16-byte stack alignment, there's already the return address, so + // - for 32-bit push EAX, i.e. ArtMethod*, ESI, EDI, + // - for 64-bit push RAX, i.e. ArtMethod*. + if (!cu_->target64) { + DCHECK(!IsTemp(rs_rSI)); + DCHECK(!IsTemp(rs_rDI)); + core_spill_mask_ = + (1u << rs_rSI.GetRegNum()) | (1u << rs_rSI.GetRegNum()) | (1u << rs_rRET.GetRegNum()); + num_core_spills_ = 3u; + } else { + core_spill_mask_ = (1u << rs_rRET.GetRegNum()); + num_core_spills_ = 1u; + } + fp_spill_mask_ = 0u; + num_fp_spills_ = 0u; + frame_size_ = 16u; + core_vmap_table_.clear(); + fp_vmap_table_.clear(); + if (!cu_->target64) { + NewLIR1(kX86Push32R, rs_rDI.GetReg()); + NewLIR1(kX86Push32R, rs_rSI.GetReg()); + } + NewLIR1(kX86Push32R, TargetReg(kArg0, kRef).GetReg()); // ArtMethod* +} + +void X86Mir2Lir::GenSpecialExitForSuspend() { + // Pop the frame. (ArtMethod* no longer needed but restore it anyway.) + NewLIR1(kX86Pop32R, TargetReg(kArg0, kRef).GetReg()); // ArtMethod* + if (!cu_->target64) { + NewLIR1(kX86Pop32R, rs_rSI.GetReg()); + NewLIR1(kX86Pop32R, rs_rDI.GetReg()); + } +} + void X86Mir2Lir::GenImplicitNullCheck(RegStorage reg, int opt_flags) { if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) { return; |