summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-09-19 07:26:56 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-09-19 07:26:56 +0000
commit112f3ae232f90ecf5b9b1ac9393029aebebc21cd (patch)
tree340851feead9293899fafc975ed6eb4d251ddb99
parent171693533c0d80eb7d5d88edb75db691582a54ad (diff)
parent476b11204e9ea611a0b7099d64320749453c64f4 (diff)
downloadart-112f3ae232f90ecf5b9b1ac9393029aebebc21cd.tar.gz
release-request-336ddfb0-c762-4bda-8684-20198669642d-for-git_oc-mr1-release-4346879 snap-temp-L51800000104038734
Change-Id: I888ce08f03dac01d0a5b22df9ca927830c081d62
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc38
-rw-r--r--test/164-resolution-trampoline-dex-cache/expected.txt3
-rw-r--r--test/164-resolution-trampoline-dex-cache/info.txt3
-rw-r--r--test/164-resolution-trampoline-dex-cache/profile1
-rw-r--r--test/164-resolution-trampoline-dex-cache/run22
-rw-r--r--test/164-resolution-trampoline-dex-cache/src-ex/MostDerived.java50
-rw-r--r--test/164-resolution-trampoline-dex-cache/src/Base.java21
-rw-r--r--test/164-resolution-trampoline-dex-cache/src/Derived.java18
-rw-r--r--test/164-resolution-trampoline-dex-cache/src/Main.java59
-rw-r--r--test/knownfailures.json8
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",