summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2020-09-09 13:57:17 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2020-09-11 13:20:58 +0000
commit1fef877c66f066f01653ea98bfefe29304198193 (patch)
tree65561c8b15844cabe32728b61d1e5d586976acf3
parenta41ea2708d143b5982f1969864513b62706d11d4 (diff)
Handle more cases of super calls in the compiler.
Add support for calling super methods that are not referenced within the compiling dex file. Test: 808-checker-invoke-super Test: 809-checker-invoke-super-bss Change-Id: Ib103f818ac8b612a79b6b18cc8eda81131bb3149
-rw-r--r--compiler/optimizing/instruction_builder.cc32
-rw-r--r--compiler/optimizing/instruction_simplifier.cc3
-rw-r--r--compiler/optimizing/sharpening.cc7
-rw-r--r--compiler/optimizing/sharpening.h2
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc6
-rw-r--r--test/808-checker-invoke-super/expected.txt0
-rw-r--r--test/808-checker-invoke-super/info.txt2
-rw-r--r--test/808-checker-invoke-super/smali-multidex/Class.smali24
-rw-r--r--test/808-checker-invoke-super/smali/Main.smali25
-rw-r--r--test/808-checker-invoke-super/smali/SuperClass.smali21
-rw-r--r--test/809-checker-invoke-super-bss/smali-multidex/OtherClass.smali5
-rw-r--r--test/knownfailures.json1
12 files changed, 107 insertions, 21 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 3401e65163..9fb9c4e7fe 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -957,18 +957,6 @@ static ArtMethod* ResolveMethod(uint16_t method_idx,
actual_method = compiling_class->GetSuperClass()->GetVTableEntry(
vtable_index, class_linker->GetImagePointerSize());
}
- if (actual_method != resolved_method &&
- !IsSameDexFile(*actual_method->GetDexFile(), *dex_compilation_unit.GetDexFile())) {
- // The back-end code generator relies on this check in order to ensure that it will not
- // attempt to read the dex_cache with a dex_method_index that is not from the correct
- // dex_file. If we didn't do this check then the dex_method_index will not be updated in the
- // builder, which means that the code-generator (and sharpening and inliner, maybe)
- // might invoke an incorrect method.
- // TODO: The actual method could still be referenced in the current dex file, so we
- // could try locating it.
- // TODO: Remove the dex_file restriction.
- return nullptr;
- }
if (!actual_method->IsInvokable()) {
// Fail if the actual method cannot be invoked. Otherwise, the runtime resolution stub
// could resolve the callee to the wrong method.
@@ -1092,15 +1080,31 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
HInvoke* invoke = nullptr;
if (invoke_type == kDirect || invoke_type == kStatic || invoke_type == kSuper) {
+ // For sharpening, we create another MethodReference, to account for the
+ // kSuper case below where we cannot find a dex method index.
+ bool has_method_id = true;
if (invoke_type == kSuper) {
+ uint32_t dex_method_index = method_reference.index;
if (IsSameDexFile(*method_info.dex_file, *dex_compilation_unit_->GetDexFile())) {
// Update the method index to the one resolved. Note that this may be a no-op if
// we resolved to the method referenced by the instruction.
- method_reference.index = method_info.index;
+ dex_method_index = method_info.index;
+ } else {
+ // Try to find a dex method index in this caller's dex file.
+ ScopedObjectAccess soa(Thread::Current());
+ dex_method_index = resolved_method->FindDexMethodIndexInOtherDexFile(
+ *dex_compilation_unit_->GetDexFile(), method_idx);
+ }
+ if (dex_method_index == dex::kDexNoIndex) {
+ has_method_id = false;
+ } else {
+ method_reference.index = dex_method_index;
}
}
HInvokeStaticOrDirect::DispatchInfo dispatch_info =
- HSharpening::SharpenInvokeStaticOrDirect(resolved_method, code_generator_);
+ HSharpening::SharpenInvokeStaticOrDirect(resolved_method,
+ has_method_id,
+ code_generator_);
if (dispatch_info.code_ptr_location ==
HInvokeStaticOrDirect::CodePtrLocation::kCallCriticalNative) {
graph_->SetHasDirectCriticalNativeCall(true);
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index d586306a2c..d616912b9f 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -2310,7 +2310,8 @@ void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction)
// the invoke, as we would need to look it up in the current dex file, and it
// is unlikely that it exists. The most usual situation for such typed
// arraycopy methods is a direct pointer to the boot image.
- invoke->SetDispatchInfo(HSharpening::SharpenInvokeStaticOrDirect(method, codegen_));
+ invoke->SetDispatchInfo(
+ HSharpening::SharpenInvokeStaticOrDirect(method, /* has_method_id= */ true, codegen_));
}
}
}
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 04a8eab530..f658f8ad07 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -58,7 +58,7 @@ static bool BootImageAOTCanEmbedMethod(ArtMethod* method, const CompilerOptions&
}
HInvokeStaticOrDirect::DispatchInfo HSharpening::SharpenInvokeStaticOrDirect(
- ArtMethod* callee, CodeGenerator* codegen) {
+ ArtMethod* callee, bool has_method_id, CodeGenerator* codegen) {
if (kIsDebugBuild) {
ScopedObjectAccess soa(Thread::Current()); // Required for GetDeclaringClass below.
DCHECK(callee != nullptr);
@@ -96,6 +96,8 @@ HInvokeStaticOrDirect::DispatchInfo HSharpening::SharpenInvokeStaticOrDirect(
method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo;
} else if (BootImageAOTCanEmbedMethod(callee, compiler_options)) {
method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative;
+ } else if (!has_method_id) {
+ method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall;
} else {
// Use PC-relative access to the .bss methods array.
method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBssEntry;
@@ -118,6 +120,9 @@ HInvokeStaticOrDirect::DispatchInfo HSharpening::SharpenInvokeStaticOrDirect(
// Use PC-relative access to the .data.bimg.rel.ro methods array.
method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo;
code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
+ } else if (!has_method_id) {
+ method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall;
+ code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
} else {
// Use PC-relative access to the .bss methods array.
method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBssEntry;
diff --git a/compiler/optimizing/sharpening.h b/compiler/optimizing/sharpening.h
index b81867201f..b48cd4b9b3 100644
--- a/compiler/optimizing/sharpening.h
+++ b/compiler/optimizing/sharpening.h
@@ -31,7 +31,7 @@ class HSharpening {
public:
// Used by the builder and InstructionSimplifier.
static HInvokeStaticOrDirect::DispatchInfo SharpenInvokeStaticOrDirect(
- ArtMethod* callee, CodeGenerator* codegen);
+ ArtMethod* callee, bool has_method_id, CodeGenerator* codegen);
// Used by the builder and the inliner.
static HLoadClass::LoadKind ComputeLoadClassKind(HLoadClass* load_class,
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 6be095b5c5..dc990abc50 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1322,9 +1322,11 @@ extern "C" const void* artQuickResolutionTrampoline(
if (called != nullptr) {
if (invoke_type == kSuper) {
if (called->GetDexFile() == called_method.dex_file) {
- // When the target is in a different dex file, the compiler makes sure
- // the index is relative to the caller's dex file.
called_method.index = called->GetDexMethodIndex();
+ } else {
+ called_method.index = called->FindDexMethodIndexInOtherDexFile(
+ *called_method.dex_file, called_method.index);
+ DCHECK_NE(called_method.index, dex::kDexNoIndex);
}
}
MaybeUpdateBssMethodEntry(called, called_method);
diff --git a/test/808-checker-invoke-super/expected.txt b/test/808-checker-invoke-super/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/808-checker-invoke-super/expected.txt
diff --git a/test/808-checker-invoke-super/info.txt b/test/808-checker-invoke-super/info.txt
new file mode 100644
index 0000000000..015ce5c6c7
--- /dev/null
+++ b/test/808-checker-invoke-super/info.txt
@@ -0,0 +1,2 @@
+Test that even if a supercall cannot directly reference the resolved method
+within the dex file, we still generate a HInvokeStaticOrDirect.
diff --git a/test/808-checker-invoke-super/smali-multidex/Class.smali b/test/808-checker-invoke-super/smali-multidex/Class.smali
new file mode 100644
index 0000000000..e312c45f94
--- /dev/null
+++ b/test/808-checker-invoke-super/smali-multidex/Class.smali
@@ -0,0 +1,24 @@
+# Copyright 2020 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 LClass;
+.super LSuperClass;
+
+## CHECK-START: void Class.$noinline$foo() register (after)
+## CHECK-DAG: InvokeStaticOrDirect method_name:SuperClass.$noinline$foo
+.method public $noinline$foo()V
+.registers 1
+ invoke-super {p0}, LClass;->$noinline$foo()V
+ return-void
+.end method
diff --git a/test/808-checker-invoke-super/smali/Main.smali b/test/808-checker-invoke-super/smali/Main.smali
new file mode 100644
index 0000000000..b9122b341d
--- /dev/null
+++ b/test/808-checker-invoke-super/smali/Main.smali
@@ -0,0 +1,25 @@
+# Copyright 2020 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 LMain;
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+.registers 1
+ new-instance v0, LClass;
+ invoke-direct {v0}, LClass;-><init>()V
+ invoke-virtual {v0}, LClass;->$noinline$foo()V
+ invoke-virtual {v0}, LClass;->$noinline$foo()V
+ return-void
+.end method
diff --git a/test/808-checker-invoke-super/smali/SuperClass.smali b/test/808-checker-invoke-super/smali/SuperClass.smali
new file mode 100644
index 0000000000..506cf56c89
--- /dev/null
+++ b/test/808-checker-invoke-super/smali/SuperClass.smali
@@ -0,0 +1,21 @@
+# Copyright 2020 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 LSuperClass;
+.super Ljava/lang/Object;
+
+.method public $noinline$foo()V
+.registers 1
+ return-void
+.end method
diff --git a/test/809-checker-invoke-super-bss/smali-multidex/OtherClass.smali b/test/809-checker-invoke-super-bss/smali-multidex/OtherClass.smali
index 92770fef4c..2a87f4b788 100644
--- a/test/809-checker-invoke-super-bss/smali-multidex/OtherClass.smali
+++ b/test/809-checker-invoke-super-bss/smali-multidex/OtherClass.smali
@@ -16,10 +16,11 @@
.super LSuperClass;
## CHECK-START: void OtherClass.$noinline$foo() register (after)
-# TODO(ngeoffray): We should emit HInvokeStaticDirect
-## CHECK-DAG: InvokeUnresolved method_name:OtherClass.$noinline$foo
+## CHECK-DAG: InvokeStaticOrDirect dex_file_index:<<Index1:\d+>> method_name:SuperSuperClass.$noinline$foo
## CHECK-DAG: InvokeStaticOrDirect dex_file_index:<<Index2:\d+>> method_name:SuperSuperClass.$noinline$foo
## CHECK-DAG: InvokeStaticOrDirect dex_file_index:<<Index3:\d+>> method_name:SuperSuperClass.$noinline$foo
+## CHECK-EVAL: <<Index1>> == <<Index2>>
+## CHECK-EVAL: <<Index1>> == <<Index3>>
.method public $noinline$foo()V
.registers 1
invoke-super {p0}, LOtherClass;->$noinline$foo()V
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 36cfd19922..edaea0720f 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1131,6 +1131,7 @@
"692-vdex-inmem-loader",
"693-vdex-inmem-loader-evict",
"723-string-init-range",
+ "808-checker-invoke-super",
"809-checker-invoke-super-bss",
"999-redefine-hiddenapi",
"1000-non-moving-space-stress",