diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2017-09-19 07:26:56 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-09-19 07:26:56 +0000 |
commit | 112f3ae232f90ecf5b9b1ac9393029aebebc21cd (patch) | |
tree | 340851feead9293899fafc975ed6eb4d251ddb99 | |
parent | 171693533c0d80eb7d5d88edb75db691582a54ad (diff) | |
parent | 476b11204e9ea611a0b7099d64320749453c64f4 (diff) | |
download | art-112f3ae232f90ecf5b9b1ac9393029aebebc21cd.tar.gz |
release-request-336ddfb0-c762-4bda-8684-20198669642d-for-git_oc-mr1-release-4346879 snap-temp-L51800000104038734
Change-Id: I888ce08f03dac01d0a5b22df9ca927830c081d62
10 files changed, 185 insertions, 38 deletions
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 6d4f77b95d..036f912ced 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -1251,44 +1251,6 @@ extern "C" const void* artQuickResolutionTrampoline( CHECK(called != nullptr) << orig_called->PrettyMethod() << " " << mirror::Object::PrettyTypeOf(receiver) << " " << invoke_type << " " << orig_called->GetVtableIndex(); - - // We came here because of sharpening. Ensure the dex cache is up-to-date on the method index - // of the sharpened method avoiding dirtying the dex cache if possible. - // Note, called_method.dex_method_index references the dex method before the - // FindVirtualMethodFor... This is ok for FindDexMethodIndexInOtherDexFile that only cares - // about the name and signature. - uint32_t update_dex_cache_method_index = called->GetDexMethodIndex(); - if (!called->HasSameDexCacheResolvedMethods(caller, kRuntimePointerSize)) { - // Calling from one dex file to another, need to compute the method index appropriate to - // the caller's dex file. Since we get here only if the original called was a runtime - // method, we've got the correct dex_file and a dex_method_idx from above. - DCHECK(!called_method_known_on_entry); - DCHECK_EQ(caller->GetDexFile(), called_method.dex_file); - const DexFile* caller_dex_file = called_method.dex_file; - uint32_t caller_method_name_and_sig_index = called_method.dex_method_index; - update_dex_cache_method_index = - called->FindDexMethodIndexInOtherDexFile(*caller_dex_file, - caller_method_name_and_sig_index); - } - if ((update_dex_cache_method_index != DexFile::kDexNoIndex) && - (caller->GetDexCacheResolvedMethod( - update_dex_cache_method_index, kRuntimePointerSize) != called)) { - caller->SetDexCacheResolvedMethod(update_dex_cache_method_index, - called, - kRuntimePointerSize); - } - } else if (invoke_type == kStatic) { - const auto called_dex_method_idx = called->GetDexMethodIndex(); - // For static invokes, we may dispatch to the static method in the superclass but resolve - // using the subclass. To prevent getting slow paths on each invoke, we force set the - // resolved method for the super class dex method index if we are in the same dex file. - // b/19175856 - if (called->GetDexFile() == called_method.dex_file && - called_method.dex_method_index != called_dex_method_idx) { - called->GetDexCache()->SetResolvedMethod(called_dex_method_idx, - called, - kRuntimePointerSize); - } } // Ensure that the called method's class is initialized. diff --git a/test/164-resolution-trampoline-dex-cache/expected.txt b/test/164-resolution-trampoline-dex-cache/expected.txt new file mode 100644 index 0000000000..d549cb1664 --- /dev/null +++ b/test/164-resolution-trampoline-dex-cache/expected.txt @@ -0,0 +1,3 @@ +JNI_OnLoad called +Base.foo() on MostDerived +MostDerived.test(.) done. diff --git a/test/164-resolution-trampoline-dex-cache/info.txt b/test/164-resolution-trampoline-dex-cache/info.txt new file mode 100644 index 0000000000..4e4d82ae5b --- /dev/null +++ b/test/164-resolution-trampoline-dex-cache/info.txt @@ -0,0 +1,3 @@ +Regression test for artQuickResolutionTrampoline() erroneously storing an +ArtMethod to a DexCache for a MethodId referencing a class missing from the +associated ClassTable. This discrepancy then led to a crash when JITting. diff --git a/test/164-resolution-trampoline-dex-cache/profile b/test/164-resolution-trampoline-dex-cache/profile new file mode 100644 index 0000000000..d232ff20ca --- /dev/null +++ b/test/164-resolution-trampoline-dex-cache/profile @@ -0,0 +1 @@ +LMostDerived;->test(Ljava/lang/Class;)V diff --git a/test/164-resolution-trampoline-dex-cache/run b/test/164-resolution-trampoline-dex-cache/run new file mode 100644 index 0000000000..5e77cd56ed --- /dev/null +++ b/test/164-resolution-trampoline-dex-cache/run @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Copyright (C) 2017 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. + +# Use the --secondary switch to add secondary dex file to class path. +# Make sure we compile the required method using speed-profile compiler filter. +# Enable JIT through runtime option to avoid the compiler filter set by --jit. +exec ${RUN} "${@}" --secondary \ + -Xcompiler-option --compiler-filter=speed-profile --profile \ + --runtime-option -Xusejit:true diff --git a/test/164-resolution-trampoline-dex-cache/src-ex/MostDerived.java b/test/164-resolution-trampoline-dex-cache/src-ex/MostDerived.java new file mode 100644 index 0000000000..0c85528b55 --- /dev/null +++ b/test/164-resolution-trampoline-dex-cache/src-ex/MostDerived.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 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. + */ + +public class MostDerived extends Derived { + public static void test(Class main) { + // The defining class loader of MostDerived (MDCL) is also the initiating loader of + // superclass Derived but delegates the loading to its parent class loader (PCL) which + // defines both Derived and Base. Thus Derived.class is recorded in MDCL's ClassTable + // but the Base.class is not because the Base's initiating loader is PCL. This is the + // case when loading the MostDerived class and remains the case after resolving the + // "invoke-super Derived.foo(.)" called from from MostDerived.foo(.). When that + // invoke-super is executed from AOT-compiled code, it goes through the .bss ArtMethod* + // entry and on first execution goes through the resolution method. After resolving to + // the Base.foo(.), the artQuickResolutionTrampoline() used to erroneously fill the + // Base.foo(.) entry in the MostDerived's DexCache which is wrong as the referenced + // class Base is not in the associated, i.e. MDCL's, ClassTable. + new MostDerived().foo(main); + try { + // This discrepancy then used to crash when resolving the Base.foo(.) method + // for JIT compilation of another method. + main.getDeclaredMethod("ensureJitCompiled", Class.class, String.class).invoke( + null, MostDerived.class, "bar"); + } catch (Throwable t) { + t.printStackTrace(System.out); + } + System.out.println("MostDerived.test(.) done."); + } + + public void foo(Class main) { + super.foo(main); + } + + public void bar(Class main) { + Base b = this; + b.foo(main); + } +} diff --git a/test/164-resolution-trampoline-dex-cache/src/Base.java b/test/164-resolution-trampoline-dex-cache/src/Base.java new file mode 100644 index 0000000000..d4ef78bf49 --- /dev/null +++ b/test/164-resolution-trampoline-dex-cache/src/Base.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2017 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. + */ + +public class Base { + public void foo(Class main) { + System.out.println("Base.foo() on " + getClass().getName()); + } +} diff --git a/test/164-resolution-trampoline-dex-cache/src/Derived.java b/test/164-resolution-trampoline-dex-cache/src/Derived.java new file mode 100644 index 0000000000..acca9ce5af --- /dev/null +++ b/test/164-resolution-trampoline-dex-cache/src/Derived.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 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. + */ + +public class Derived extends Base { +} diff --git a/test/164-resolution-trampoline-dex-cache/src/Main.java b/test/164-resolution-trampoline-dex-cache/src/Main.java new file mode 100644 index 0000000000..b4731ae0b6 --- /dev/null +++ b/test/164-resolution-trampoline-dex-cache/src/Main.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 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.Constructor; +import java.lang.reflect.Method; + +public class Main { + public static String TEST_NAME = "164-resolution-trampoline-dex-cache"; + + public static void main(String[] args) { + // Load the test JNI for ensureJitCompiled(). Note that classes Main loaded + // by other class loaders do not have the binding, so we need to pass the + // current Main.class around and call ensureJitCompiled() via reflection. + System.loadLibrary(args[0]); + try { + String dex_location = System.getenv("DEX_LOCATION"); + ClassLoader systemLoader = ClassLoader.getSystemClassLoader().getParent(); + ClassLoader baseLoader = getClassLoaderFor(dex_location, systemLoader, /* ex */ false); + ClassLoader mainLoader = getClassLoaderFor(dex_location, baseLoader, /* ex */ true); + + Class<?> tc = Class.forName("MostDerived", true, mainLoader); + Method m = tc.getDeclaredMethod("test", Class.class); + m.invoke(null, Main.class); + } catch (Throwable t) { + t.printStackTrace(System.out); + } + } + + public static ClassLoader getClassLoaderFor(String location, ClassLoader parent, boolean ex) + throws Exception { + try { + Class<?> class_loader_class = Class.forName("dalvik.system.PathClassLoader"); + Constructor<?> ctor = + class_loader_class.getConstructor(String.class, ClassLoader.class); + String path = location + "/" + TEST_NAME + (ex ? "-ex.jar" : ".jar"); + return (ClassLoader)ctor.newInstance(path, parent); + } catch (ClassNotFoundException e) { + // Running on RI. Use URLClassLoader. + String url = "file://" + location + (ex ? "/classes-ex/" : "/classes/"); + return new java.net.URLClassLoader( + new java.net.URL[] { new java.net.URL(url) }, parent); + } + } + + public static native void ensureJitCompiled(Class<?> klass, String method_name); +} diff --git a/test/knownfailures.json b/test/knownfailures.json index 69421de325..a2502e69e0 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -105,6 +105,14 @@ "description": ["This test sometimes runs out of memory initializing the boot classpath."] }, { + "tests": "164-resolution-trampoline-dex-cache", + "variant": "interp-ac | interpreter", + "description": ["This test requires AOT mixed with JIT and enables the JIT by the ", + "runtime option -Xusejit:true. This conflicts with -Xint passed for ", + "interpreter configurations (interp-ac | interpreter). The 'jit' ", + "configuration succeeds even though it does not test anything useful."] + }, + { "tests": ["908-gc-start-finish", "913-heaps"], "variant": "gcstress", |