diff options
| author | 2015-10-28 12:19:06 -0500 | |
|---|---|---|
| committer | 2015-10-28 20:16:06 -0500 | |
| commit | efc3f02504e8e3768cc18ab5347c5a6d19d6a935 (patch) | |
| tree | 43dcd255401c6270b83ef83a95a5ab00416ad535 | |
| parent | 5f2e628b280dfc5f8385e489d44cc0960fcea484 (diff) | |
ART: Fix deopt from optimized code under inlining
Deoptimization of inlined frames would use the outer method's
vreg map, thus starting interpreter in bogus state.
Bug: 25331616
Change-Id: I1d4aefc731bb1386f3e6186a89b59981836480b3
| -rw-r--r-- | runtime/quick_exception_handler.cc | 7 | ||||
| -rw-r--r-- | runtime/stack.h | 4 | ||||
| -rw-r--r-- | test/541-regression-inlined-deopt/expected.txt | 0 | ||||
| -rw-r--r-- | test/541-regression-inlined-deopt/info.txt | 4 | ||||
| -rw-r--r-- | test/541-regression-inlined-deopt/smali/TestCase.smali | 55 | ||||
| -rw-r--r-- | test/541-regression-inlined-deopt/src/Main.java | 36 |
6 files changed, 105 insertions, 1 deletions
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index 53b4f3a3b5..1552318c1e 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -372,9 +372,14 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { StackMapEncoding encoding = code_info.ExtractEncoding(); StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding); const size_t number_of_vregs = m->GetCodeItem()->registers_size_; - DexRegisterMap vreg_map = code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_vregs); MemoryRegion stack_mask = stack_map.GetStackMask(encoding); uint32_t register_mask = stack_map.GetRegisterMask(encoding); + DexRegisterMap vreg_map = IsInInlinedFrame() + ? code_info.GetDexRegisterMapAtDepth(GetCurrentInliningDepth() - 1, + code_info.GetInlineInfoOf(stack_map, encoding), + encoding, + number_of_vregs) + : code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_vregs); for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) { if (updated_vregs != nullptr && updated_vregs[vreg]) { diff --git a/runtime/stack.h b/runtime/stack.h index 1276b244e7..aa7b6160fe 100644 --- a/runtime/stack.h +++ b/runtime/stack.h @@ -698,6 +698,10 @@ class StackVisitor { return current_inlining_depth_ != 0; } + size_t GetCurrentInliningDepth() const { + return current_inlining_depth_; + } + uintptr_t GetCurrentQuickFramePc() const { return cur_quick_frame_pc_; } diff --git a/test/541-regression-inlined-deopt/expected.txt b/test/541-regression-inlined-deopt/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/541-regression-inlined-deopt/expected.txt diff --git a/test/541-regression-inlined-deopt/info.txt b/test/541-regression-inlined-deopt/info.txt new file mode 100644 index 0000000000..209588fe05 --- /dev/null +++ b/test/541-regression-inlined-deopt/info.txt @@ -0,0 +1,4 @@ +Regression test for deopt from optimized code which would use the top-level +stack map for deopting inlined frames. Test case is written in smali for full +control over vregs because the previous test 449 would pass because the vreg +maps at the various inlining depths were similar. diff --git a/test/541-regression-inlined-deopt/smali/TestCase.smali b/test/541-regression-inlined-deopt/smali/TestCase.smali new file mode 100644 index 0000000000..a109775dfe --- /dev/null +++ b/test/541-regression-inlined-deopt/smali/TestCase.smali @@ -0,0 +1,55 @@ +# Copyright (C) 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.class public LTestCase; +.super Ljava/lang/Object; + +.method private static $inline$depth1([I)V + .registers 3 + + # Expects array in v2. + + const v0, 0x0 + + const v1, 0x3 + aput v0, p0, v1 + + const v1, 0x4 + aput v0, p0, v1 + + return-void +.end method + +.method private static $inline$depth0([I)V + .registers 1 + + # Expects array in v0. + + invoke-static {p0}, LTestCase;->$inline$depth1([I)V + return-void +.end method + +.method public static foo()V + .registers 10 + + # Create a new array short enough to throw AIOOB in $inline$depth1. + # Make sure the reference is not stored in the same vreg as used by + # the inlined methods. + + const v5, 0x3 + new-array v6, v5, [I + + invoke-static {v6}, LTestCase;->$inline$depth0([I)V + return-void +.end method diff --git a/test/541-regression-inlined-deopt/src/Main.java b/test/541-regression-inlined-deopt/src/Main.java new file mode 100644 index 0000000000..fa79590e65 --- /dev/null +++ b/test/541-regression-inlined-deopt/src/Main.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.lang.reflect.*; + +public class Main { + + // Workaround for b/18051191. + class InnerClass {} + + public static void main(String[] args) throws Throwable { + try { + Class<?> c = Class.forName("TestCase"); + Method m = c.getMethod("foo"); + m.invoke(null, (Object[]) null); + } catch (InvocationTargetException ex) { + // Code should have thrown AIOOB. + if (!(ex.getCause() instanceof ArrayIndexOutOfBoundsException)) { + throw ex; + } + } + } +} |