Create empty VerifiedMethod after vdex verification.
The compiler and quicken require the existence of a
VerifiedMethod for compiling a method.
This fixes the regression of not doing any compilation when
passed --input-vdex.
Test: 629-vdex-speed
Change-Id: Ie65578eadd09099df1c1a403d96c15e5da78a901
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc
index 669d8cd..9d39bf2 100644
--- a/compiler/dex/verification_results.cc
+++ b/compiler/dex/verification_results.cc
@@ -103,6 +103,17 @@
return (it != verified_methods_.end()) ? it->second : nullptr;
}
+void VerificationResults::CreateVerifiedMethodFor(MethodReference ref) {
+ // This method should only be called for classes verified at compile time,
+ // which have no verifier error, nor has methods that we know will throw
+ // at runtime.
+ AtomicMap::InsertResult result = atomic_verified_methods_.Insert(
+ ref,
+ /*expected*/ nullptr,
+ new VerifiedMethod(/* encountered_error_types */ 0, /* has_runtime_throw */ false));
+ DCHECK_EQ(result, AtomicMap::kInsertResultSuccess);
+}
+
void VerificationResults::AddRejectedClass(ClassReference ref) {
{
WriterMutexLock mu(Thread::Current(), rejected_classes_lock_);
diff --git a/compiler/dex/verification_results.h b/compiler/dex/verification_results.h
index ea38f4d..ab735c1 100644
--- a/compiler/dex/verification_results.h
+++ b/compiler/dex/verification_results.h
@@ -47,6 +47,9 @@
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!verified_methods_lock_);
+ void CreateVerifiedMethodFor(MethodReference ref)
+ REQUIRES(!verified_methods_lock_);
+
const VerifiedMethod* GetVerifiedMethod(MethodReference ref)
REQUIRES(!verified_methods_lock_);
diff --git a/compiler/dex/verified_method.h b/compiler/dex/verified_method.h
index 04331e5..ce53417 100644
--- a/compiler/dex/verified_method.h
+++ b/compiler/dex/verified_method.h
@@ -32,6 +32,8 @@
class VerifiedMethod {
public:
+ VerifiedMethod(uint32_t encountered_error_types, bool has_runtime_throw);
+
// Cast elision set type.
// Since we're adding the dex PCs to the set in increasing order, a sorted vector
// is better for performance (not just memory usage), especially for large sets.
@@ -80,8 +82,6 @@
}
private:
- VerifiedMethod(uint32_t encountered_error_types, bool has_runtime_throw);
-
/*
* Generate the GC map for a method that has just been verified (i.e. we're doing this as part of
* verification). For type-precise determination we have all the data we need, so we just need to
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 6b62110..a2bab80 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -2005,6 +2005,35 @@
}
}
+static void PopulateVerifiedMethods(const DexFile& dex_file,
+ uint32_t class_def_index,
+ VerificationResults* verification_results) {
+ const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
+ const uint8_t* class_data = dex_file.GetClassData(class_def);
+ if (class_data == nullptr) {
+ return;
+ }
+ ClassDataItemIterator it(dex_file, class_data);
+ // Skip fields
+ while (it.HasNextStaticField()) {
+ it.Next();
+ }
+ while (it.HasNextInstanceField()) {
+ it.Next();
+ }
+
+ while (it.HasNextDirectMethod()) {
+ verification_results->CreateVerifiedMethodFor(MethodReference(&dex_file, it.GetMemberIndex()));
+ it.Next();
+ }
+
+ while (it.HasNextVirtualMethod()) {
+ verification_results->CreateVerifiedMethodFor(MethodReference(&dex_file, it.GetMemberIndex()));
+ it.Next();
+ }
+ DCHECK(!it.HasNext());
+}
+
void CompilerDriver::Verify(jobject jclass_loader,
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings) {
@@ -2041,6 +2070,13 @@
} else if (set.find(class_def.class_idx_) == set.end()) {
ObjectLock<mirror::Class> lock(soa.Self(), cls);
mirror::Class::SetStatus(cls, mirror::Class::kStatusVerified, soa.Self());
+ // Create `VerifiedMethod`s for each methods, the compiler expects one for
+ // quickening or compiling.
+ // Note that this means:
+ // - We're only going to compile methods that did verify.
+ // - Quickening will not do checkcast ellision.
+ // TODO(ngeoffray): Reconsider this once we refactor compiler filters.
+ PopulateVerifiedMethods(*dex_file, i, verification_results_);
}
}
}
diff --git a/test/629-vdex-speed/expected.txt b/test/629-vdex-speed/expected.txt
new file mode 100644
index 0000000..6a5618e
--- /dev/null
+++ b/test/629-vdex-speed/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/629-vdex-speed/info.txt b/test/629-vdex-speed/info.txt
new file mode 100644
index 0000000..6d84cb5
--- /dev/null
+++ b/test/629-vdex-speed/info.txt
@@ -0,0 +1,2 @@
+Regression test for vdex that used to not AOT compile
+methods when the VerifierDeps were verified.
diff --git a/test/629-vdex-speed/run b/test/629-vdex-speed/run
new file mode 100644
index 0000000..f1b0a95
--- /dev/null
+++ b/test/629-vdex-speed/run
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright (C) 2016 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.
+
+exec ${RUN} --vdex "${@}"
diff --git a/test/629-vdex-speed/src/Main.java b/test/629-vdex-speed/src/Main.java
new file mode 100644
index 0000000..470565a
--- /dev/null
+++ b/test/629-vdex-speed/src/Main.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 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 Main {
+ public static void main(String[] args) {
+ System.loadLibrary(args[0]);
+ if (!isAotCompiled(Main.class, "main")) {
+ throw new Error("Expected Main.main to be AOT compiled");
+ }
+ }
+
+ private native static boolean isAotCompiled(Class<?> cls, String methodName);
+}
+
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index d15d016..d7dfe5a 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -360,8 +360,10 @@
TEST_ART_BROKEN_NO_RELOCATE_TESTS :=
# Temporarily disable some broken tests when forcing access checks in interpreter b/22414682
+# 629 requires compilation.
TEST_ART_BROKEN_INTERPRETER_ACCESS_CHECK_TESTS := \
- 137-cfi
+ 137-cfi \
+ 629-vdex-speed
ifneq (,$(filter interp-ac,$(COMPILER_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
@@ -470,12 +472,14 @@
# This test dynamically enables tracing to force a deoptimization. This makes the test meaningless
# when already tracing, and writes an error message that we do not want to check for.
# 130 occasional timeout b/32383962.
+# 629 requires compilation.
TEST_ART_BROKEN_TRACING_RUN_TESTS := \
087-gc-after-link \
130-hprof \
137-cfi \
141-class-unload \
570-checker-osr \
+ 629-vdex-speed \
802-deoptimization
ifneq (,$(filter trace stream,$(TRACE_TYPES)))
@@ -486,9 +490,11 @@
# Known broken tests for the interpreter.
# CFI unwinding expects managed frames.
+# 629 requires compilation.
TEST_ART_BROKEN_INTERPRETER_RUN_TESTS := \
137-cfi \
- 554-jit-profile-file
+ 554-jit-profile-file \
+ 629-vdex-speed
ifneq (,$(filter interpreter,$(COMPILER_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
@@ -504,8 +510,10 @@
# Test 906 iterates the heap filtering with different options. No instances should be created
# between those runs to be able to have precise checks.
# Test 902 hits races with the JIT compiler. b/32821077
+# Test 629 requires compilation.
TEST_ART_BROKEN_JIT_RUN_TESTS := \
137-cfi \
+ 629-vdex-speed \
902-hello-transformation \
904-object-allocation \
906-iterate-heap \
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index 9cfa324..285f3aa 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -119,6 +119,24 @@
return JNI_TRUE;
}
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAotCompiled(JNIEnv* env,
+ jclass,
+ jclass cls,
+ jstring method_name) {
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+ ScopedUtfChars chars(env, method_name);
+ CHECK(chars.c_str() != nullptr);
+ ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
+ chars.c_str(), kRuntimePointerSize);
+ const void* code = method->GetOatMethodQuickCode(kRuntimePointerSize);
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ if (jit != nullptr && jit->GetCodeCache()->ContainsPc(code)) {
+ return true;
+ }
+ return code != nullptr;
+}
+
extern "C" JNIEXPORT void JNICALL Java_Main_ensureJitCompiled(JNIEnv* env,
jclass,
jclass cls,