diff options
author | Vladimir Kostyukov <vladimir.kostyukov@intel.com> | 2014-04-02 18:42:20 +0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2014-04-07 09:39:16 -0700 |
commit | 1dd61ba3081a52c3e2efdc78d64f5c134eea7895 (patch) | |
tree | 3d708c62ffacf62d1ecd2019ea7a183411ff5787 /runtime/entrypoints/quick | |
parent | 427ca38b0a6c6fd7dc0dbb380619e2b91b56cf1c (diff) | |
download | art-1dd61ba3081a52c3e2efdc78d64f5c134eea7895.zip art-1dd61ba3081a52c3e2efdc78d64f5c134eea7895.tar.gz art-1dd61ba3081a52c3e2efdc78d64f5c134eea7895.tar.bz2 |
ART: A workaround for a wrongly-read caller's frame
The quick-trampoline treats caller's frame in a different way
then it was formed by quck-invoke stub for hard float ABI targets
such as x86_64 and aarch64. The patch workarounds the issue of
wrongly-read stack arguments due to no contract between quick-invoke
stub and quick-trampoline/shadow-frame-builder regarding the reg-
spill area.
Change-Id: I302f212b4ea5e38632527a5ace03f136b21ef806
Signed-off-by: Vladimir Kostyukov <vladimir.kostyukov@intel.com>
Diffstat (limited to 'runtime/entrypoints/quick')
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 107 |
1 files changed, 32 insertions, 75 deletions
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index fcbcac2..2b29591 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -250,6 +250,7 @@ class QuickArgumentVisitor { if ((kNumQuickFprArgs != 0) && (fpr_index_ + 1 < kNumQuickFprArgs + 1)) { return fpr_args_ + (fpr_index_ * kBytesPerFprSpillLocation); } + return stack_args_ + (stack_index_ * kBytesStackArgLocation); } } if (gpr_index_ < kNumQuickGprArgs) { @@ -283,6 +284,12 @@ class QuickArgumentVisitor { } void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + // This implementation doesn't support reg-spill area for hard float + // ABI targets such as x86_64 and aarch64. So, for those targets whose + // 'kQuickSoftFloatAbi' is 'false': + // (a) 'stack_args_' should point to the first method's argument + // (b) whatever the argument type it is, the 'stack_index_' should + // be moved forward along with every visiting. gpr_index_ = 0; fpr_index_ = 0; stack_index_ = 0; @@ -290,10 +297,11 @@ class QuickArgumentVisitor { cur_type_ = Primitive::kPrimNot; is_split_long_or_double_ = false; Visit(); + if (!kQuickSoftFloatAbi || kNumQuickGprArgs == 0) { + stack_index_++; + } if (kNumQuickGprArgs > 0) { gpr_index_++; - } else { - stack_index_++; } } for (uint32_t shorty_index = 1; shorty_index < shorty_len_; ++shorty_index) { @@ -307,10 +315,11 @@ class QuickArgumentVisitor { case Primitive::kPrimInt: is_split_long_or_double_ = false; Visit(); + if (!kQuickSoftFloatAbi || kNumQuickGprArgs == gpr_index_) { + stack_index_++; + } if (gpr_index_ < kNumQuickGprArgs) { gpr_index_++; - } else { - stack_index_++; } break; case Primitive::kPrimFloat: @@ -325,9 +334,8 @@ class QuickArgumentVisitor { } else { if ((kNumQuickFprArgs != 0) && (fpr_index_ + 1 < kNumQuickFprArgs + 1)) { fpr_index_++; - } else { - stack_index_++; } + stack_index_++; } break; case Primitive::kPrimDouble: @@ -336,22 +344,23 @@ class QuickArgumentVisitor { is_split_long_or_double_ = (kBytesPerGprSpillLocation == 4) && ((gpr_index_ + 1) == kNumQuickGprArgs); Visit(); + if (!kQuickSoftFloatAbi || kNumQuickGprArgs == gpr_index_) { + if (kBytesStackArgLocation == 4) { + stack_index_+= 2; + } else { + CHECK_EQ(kBytesStackArgLocation, 8U); + stack_index_++; + } + } if (gpr_index_ < kNumQuickGprArgs) { gpr_index_++; if (kBytesPerGprSpillLocation == 4) { if (gpr_index_ < kNumQuickGprArgs) { gpr_index_++; - } else { + } else if (kQuickSoftFloatAbi) { stack_index_++; } } - } else { - if (kBytesStackArgLocation == 4) { - stack_index_+= 2; - } else { - CHECK_EQ(kBytesStackArgLocation, 8U); - stack_index_++; - } } } else { is_split_long_or_double_ = (kBytesPerFprSpillLocation == 4) && @@ -362,17 +371,14 @@ class QuickArgumentVisitor { if (kBytesPerFprSpillLocation == 4) { if ((kNumQuickFprArgs != 0) && (fpr_index_ + 1 < kNumQuickFprArgs + 1)) { fpr_index_++; - } else { - stack_index_++; } } + } + if (kBytesStackArgLocation == 4) { + stack_index_+= 2; } else { - if (kBytesStackArgLocation == 4) { - stack_index_+= 2; - } else { - CHECK_EQ(kBytesStackArgLocation, 8U); - stack_index_++; - } + CHECK_EQ(kBytesStackArgLocation, 8U); + stack_index_++; } } break; @@ -389,59 +395,10 @@ class QuickArgumentVisitor { CHECK_EQ(kNumQuickFprArgs, 0U); return (kNumQuickGprArgs * kBytesPerGprSpillLocation) + kBytesPerGprSpillLocation /* ArtMethod* */; } else { - size_t offset = kBytesPerGprSpillLocation; // Skip Method*. - size_t gprs_seen = 0; - size_t fprs_seen = 0; - if (!is_static && (gprs_seen < kNumQuickGprArgs)) { - gprs_seen++; - offset += kBytesStackArgLocation; - } - for (uint32_t i = 1; i < shorty_len; ++i) { - switch (shorty[i]) { - case 'Z': - case 'B': - case 'C': - case 'S': - case 'I': - case 'L': - if (gprs_seen < kNumQuickGprArgs) { - gprs_seen++; - offset += kBytesStackArgLocation; - } - break; - case 'J': - if (gprs_seen < kNumQuickGprArgs) { - gprs_seen++; - offset += 2 * kBytesStackArgLocation; - if (kBytesPerGprSpillLocation == 4) { - if (gprs_seen < kNumQuickGprArgs) { - gprs_seen++; - } - } - } - break; - case 'F': - if ((kNumQuickFprArgs != 0) && (fprs_seen + 1 < kNumQuickFprArgs + 1)) { - fprs_seen++; - offset += kBytesStackArgLocation; - } - break; - case 'D': - if ((kNumQuickFprArgs != 0) && (fprs_seen + 1 < kNumQuickFprArgs + 1)) { - fprs_seen++; - offset += 2 * kBytesStackArgLocation; - if (kBytesPerFprSpillLocation == 4) { - if ((kNumQuickFprArgs != 0) && (fprs_seen + 1 < kNumQuickFprArgs + 1)) { - fprs_seen++; - } - } - } - break; - default: - LOG(FATAL) << "Unexpected shorty character: " << shorty[i] << " in " << shorty; - } - } - return offset; + // For now, there is no reg-spill area for the targets with + // hard float ABI. So, the offset pointing to the first method's + // parameter ('this' for non-static methods) should be returned. + return kBytesPerGprSpillLocation; // Skip Method*. } } |