summaryrefslogtreecommitdiff
path: root/compiler/driver/compiler_driver_test.cc
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2019-03-04 12:53:20 +0000
committerVladimir Marko <vmarko@google.com>2019-03-11 06:59:41 +0000
commit327497e303903f300b01f77f2259fd5b61238ee3 (patch)
tree3f714d2d2ee7d9b6c0ecf71a10c157d4952e5758 /compiler/driver/compiler_driver_test.cc
parentef764ad3e6d7f07ea9e32642dc3e163bb4eb44fb (diff)
Move CompilerDriver to dex2oat/.
Also DexToDexCompiler, QuickCompilerCallbacks and tests. aosp_taimen-userdebug: - before: lib64/libart-compiler.so: 3112344 lib/libart-compiler.so: 2312908 bin/dex2oat: 563176 - after: lib64/libart-compiler.so: 2986720 (-123KiB) lib/libart-compiler.so: 2219852 (-91KiB) bin/dex2oat: 635832 (+71KiB) Test: m test-art-host-gtest Test: testrunner.py --host --optimizing --jit Change-Id: I36e63b83dff1d5c731d05de27d3663cfc81de6ad
Diffstat (limited to 'compiler/driver/compiler_driver_test.cc')
-rw-r--r--compiler/driver/compiler_driver_test.cc370
1 files changed, 0 insertions, 370 deletions
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
deleted file mode 100644
index dd2b3abe14..0000000000
--- a/compiler/driver/compiler_driver_test.cc
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#include "driver/compiler_driver.h"
-
-#include <limits>
-#include <stdint.h>
-#include <stdio.h>
-#include <memory>
-
-#include "art_method-inl.h"
-#include "base/casts.h"
-#include "class_linker-inl.h"
-#include "common_compiler_driver_test.h"
-#include "compiler_callbacks.h"
-#include "dex/dex_file.h"
-#include "dex/dex_file_types.h"
-#include "gc/heap.h"
-#include "handle_scope-inl.h"
-#include "mirror/class-inl.h"
-#include "mirror/class_loader.h"
-#include "mirror/dex_cache-inl.h"
-#include "mirror/object-inl.h"
-#include "mirror/object_array-inl.h"
-#include "profile/profile_compilation_info.h"
-#include "scoped_thread_state_change-inl.h"
-
-namespace art {
-
-class CompilerDriverTest : public CommonCompilerDriverTest {
- protected:
- void CompileAllAndMakeExecutable(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
- TimingLogger timings("CompilerDriverTest::CompileAllAndMakeExecutable", false, false);
- dex_files_ = GetDexFiles(class_loader);
- CompileAll(class_loader, dex_files_, &timings);
- TimingLogger::ScopedTiming t("MakeAllExecutable", &timings);
- MakeAllExecutable(class_loader);
- }
-
- void EnsureCompiled(jobject class_loader, const char* class_name, const char* method,
- const char* signature, bool is_virtual)
- REQUIRES(!Locks::mutator_lock_) {
- CompileAllAndMakeExecutable(class_loader);
- Thread::Current()->TransitionFromSuspendedToRunnable();
- bool started = runtime_->Start();
- CHECK(started);
- env_ = Thread::Current()->GetJniEnv();
- class_ = env_->FindClass(class_name);
- CHECK(class_ != nullptr) << "Class not found: " << class_name;
- if (is_virtual) {
- mid_ = env_->GetMethodID(class_, method, signature);
- } else {
- mid_ = env_->GetStaticMethodID(class_, method, signature);
- }
- CHECK(mid_ != nullptr) << "Method not found: " << class_name << "." << method << signature;
- }
-
- void MakeAllExecutable(jobject class_loader) {
- const std::vector<const DexFile*> class_path = GetDexFiles(class_loader);
- for (size_t i = 0; i != class_path.size(); ++i) {
- const DexFile* dex_file = class_path[i];
- CHECK(dex_file != nullptr);
- MakeDexFileExecutable(class_loader, *dex_file);
- }
- }
-
- void MakeExecutable(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
- CHECK(method != nullptr);
-
- const CompiledMethod* compiled_method = nullptr;
- if (!method->IsAbstract()) {
- mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
- const DexFile& dex_file = *dex_cache->GetDexFile();
- compiled_method =
- compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
- method->GetDexMethodIndex()));
- }
- CommonCompilerTest::MakeExecutable(method, compiled_method);
- }
-
- void MakeDexFileExecutable(jobject class_loader, const DexFile& dex_file) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
- const dex::ClassDef& class_def = dex_file.GetClassDef(i);
- const char* descriptor = dex_file.GetClassDescriptor(class_def);
- ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ClassLoader> loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
- ObjPtr<mirror::Class> c = class_linker->FindClass(soa.Self(), descriptor, loader);
- CHECK(c != nullptr);
- const auto pointer_size = class_linker->GetImagePointerSize();
- for (auto& m : c->GetMethods(pointer_size)) {
- MakeExecutable(&m);
- }
- }
- }
-
- JNIEnv* env_;
- jclass class_;
- jmethodID mid_;
- std::vector<const DexFile*> dex_files_;
-};
-
-// Disabled due to 10 second runtime on host
-// TODO: Update the test for hash-based dex cache arrays. Bug: 30627598
-TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
- CompileAllAndMakeExecutable(nullptr);
-
- // All libcore references should resolve
- ScopedObjectAccess soa(Thread::Current());
- ASSERT_TRUE(java_lang_dex_file_ != nullptr);
- const DexFile& dex = *java_lang_dex_file_;
- ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(soa.Self(), dex);
- EXPECT_EQ(dex.NumStringIds(), dex_cache->NumStrings());
- for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
- const ObjPtr<mirror::String> string = dex_cache->GetResolvedString(dex::StringIndex(i));
- EXPECT_TRUE(string != nullptr) << "string_idx=" << i;
- }
- EXPECT_EQ(dex.NumTypeIds(), dex_cache->NumResolvedTypes());
- for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
- const ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(dex::TypeIndex(i));
- EXPECT_TRUE(type != nullptr)
- << "type_idx=" << i << " " << dex.GetTypeDescriptor(dex.GetTypeId(dex::TypeIndex(i)));
- }
- EXPECT_TRUE(dex_cache->StaticMethodSize() == dex_cache->NumResolvedMethods()
- || dex.NumMethodIds() == dex_cache->NumResolvedMethods());
- auto* cl = Runtime::Current()->GetClassLinker();
- auto pointer_size = cl->GetImagePointerSize();
- for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
- // FIXME: This is outdated for hash-based method array.
- ArtMethod* method = dex_cache->GetResolvedMethod(i, pointer_size);
- EXPECT_TRUE(method != nullptr) << "method_idx=" << i
- << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i))
- << " " << dex.GetMethodName(dex.GetMethodId(i));
- EXPECT_TRUE(method->GetEntryPointFromQuickCompiledCode() != nullptr) << "method_idx=" << i
- << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i)) << " "
- << dex.GetMethodName(dex.GetMethodId(i));
- }
- EXPECT_TRUE(dex_cache->StaticArtFieldSize() == dex_cache->NumResolvedFields()
- || dex.NumFieldIds() == dex_cache->NumResolvedFields());
- for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
- // FIXME: This is outdated for hash-based field array.
- ArtField* field = dex_cache->GetResolvedField(i, cl->GetImagePointerSize());
- EXPECT_TRUE(field != nullptr) << "field_idx=" << i
- << " " << dex.GetFieldDeclaringClassDescriptor(dex.GetFieldId(i))
- << " " << dex.GetFieldName(dex.GetFieldId(i));
- }
-
- // TODO check Class::IsVerified for all classes
-
- // TODO: check that all Method::GetCode() values are non-null
-}
-
-TEST_F(CompilerDriverTest, AbstractMethodErrorStub) {
- jobject class_loader;
- {
- ScopedObjectAccess soa(Thread::Current());
- class_loader = LoadDex("AbstractMethod");
- }
- ASSERT_TRUE(class_loader != nullptr);
- EnsureCompiled(class_loader, "AbstractClass", "foo", "()V", true);
-
- // Create a jobj_ of ConcreteClass, NOT AbstractClass.
- jclass c_class = env_->FindClass("ConcreteClass");
-
- jmethodID constructor = env_->GetMethodID(c_class, "<init>", "()V");
-
- jobject jobj_ = env_->NewObject(c_class, constructor);
- ASSERT_TRUE(jobj_ != nullptr);
-
- // Force non-virtual call to AbstractClass foo, will throw AbstractMethodError exception.
- env_->CallNonvirtualVoidMethod(jobj_, class_, mid_);
-
- EXPECT_EQ(env_->ExceptionCheck(), JNI_TRUE);
- jthrowable exception = env_->ExceptionOccurred();
- env_->ExceptionClear();
- jclass jlame = env_->FindClass("java/lang/AbstractMethodError");
- EXPECT_TRUE(env_->IsInstanceOf(exception, jlame));
- {
- ScopedObjectAccess soa(Thread::Current());
- Thread::Current()->ClearException();
- }
-}
-
-class CompilerDriverProfileTest : public CompilerDriverTest {
- protected:
- ProfileCompilationInfo* GetProfileCompilationInfo() override {
- ScopedObjectAccess soa(Thread::Current());
- std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");
-
- ProfileCompilationInfo info;
- for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
- profile_info_.AddMethodIndex(ProfileCompilationInfo::MethodHotness::kFlagHot,
- MethodReference(dex_file.get(), 1));
- profile_info_.AddMethodIndex(ProfileCompilationInfo::MethodHotness::kFlagHot,
- MethodReference(dex_file.get(), 2));
- }
- return &profile_info_;
- }
-
- CompilerFilter::Filter GetCompilerFilter() const override {
- // Use a profile based filter.
- return CompilerFilter::kSpeedProfile;
- }
-
- std::unordered_set<std::string> GetExpectedMethodsForClass(const std::string& clazz) {
- if (clazz == "Main") {
- return std::unordered_set<std::string>({
- "java.lang.String Main.getA()",
- "java.lang.String Main.getB()"});
- } else if (clazz == "Second") {
- return std::unordered_set<std::string>({
- "java.lang.String Second.getX()",
- "java.lang.String Second.getY()"});
- } else {
- return std::unordered_set<std::string>();
- }
- }
-
- void CheckCompiledMethods(jobject class_loader,
- const std::string& clazz,
- const std::unordered_set<std::string>& expected_methods) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Thread* self = Thread::Current();
- ScopedObjectAccess soa(self);
- StackHandleScope<1> hs(self);
- Handle<mirror::ClassLoader> h_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
- ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
- ASSERT_NE(klass, nullptr);
-
- const auto pointer_size = class_linker->GetImagePointerSize();
- size_t number_of_compiled_methods = 0;
- for (auto& m : klass->GetVirtualMethods(pointer_size)) {
- std::string name = m.PrettyMethod(true);
- const void* code = m.GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
- ASSERT_NE(code, nullptr);
- if (expected_methods.find(name) != expected_methods.end()) {
- number_of_compiled_methods++;
- EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code));
- } else {
- EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code));
- }
- }
- EXPECT_EQ(expected_methods.size(), number_of_compiled_methods);
- }
-
- private:
- ProfileCompilationInfo profile_info_;
-};
-
-TEST_F(CompilerDriverProfileTest, ProfileGuidedCompilation) {
- Thread* self = Thread::Current();
- jobject class_loader;
- {
- ScopedObjectAccess soa(self);
- class_loader = LoadDex("ProfileTestMultiDex");
- }
- ASSERT_NE(class_loader, nullptr);
-
- // Need to enable dex-file writability. Methods rejected to be compiled will run through the
- // dex-to-dex compiler.
- for (const DexFile* dex_file : GetDexFiles(class_loader)) {
- ASSERT_TRUE(dex_file->EnableWrite());
- }
-
- CompileAllAndMakeExecutable(class_loader);
-
- std::unordered_set<std::string> m = GetExpectedMethodsForClass("Main");
- std::unordered_set<std::string> s = GetExpectedMethodsForClass("Second");
- CheckCompiledMethods(class_loader, "LMain;", m);
- CheckCompiledMethods(class_loader, "LSecond;", s);
-}
-
-// Test that a verify only compiler filter updates the CompiledClass map,
-// which will be used for OatClass.
-class CompilerDriverVerifyTest : public CompilerDriverTest {
- protected:
- CompilerFilter::Filter GetCompilerFilter() const override {
- return CompilerFilter::kVerify;
- }
-
- void CheckVerifiedClass(jobject class_loader, const std::string& clazz) const {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Thread* self = Thread::Current();
- ScopedObjectAccess soa(self);
- StackHandleScope<1> hs(self);
- Handle<mirror::ClassLoader> h_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
- ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
- ASSERT_NE(klass, nullptr);
- EXPECT_TRUE(klass->IsVerified());
-
- ClassStatus status;
- bool found = compiler_driver_->GetCompiledClass(
- ClassReference(&klass->GetDexFile(), klass->GetDexTypeIndex().index_), &status);
- ASSERT_TRUE(found);
- EXPECT_EQ(status, ClassStatus::kVerified);
- }
-};
-
-TEST_F(CompilerDriverVerifyTest, VerifyCompilation) {
- Thread* self = Thread::Current();
- jobject class_loader;
- {
- ScopedObjectAccess soa(self);
- class_loader = LoadDex("ProfileTestMultiDex");
- }
- ASSERT_NE(class_loader, nullptr);
-
- CompileAllAndMakeExecutable(class_loader);
-
- CheckVerifiedClass(class_loader, "LMain;");
- CheckVerifiedClass(class_loader, "LSecond;");
-}
-
-// Test that a class of status ClassStatus::kRetryVerificationAtRuntime is indeed
-// recorded that way in the driver.
-TEST_F(CompilerDriverVerifyTest, RetryVerifcationStatusCheckVerified) {
- Thread* const self = Thread::Current();
- jobject class_loader;
- std::vector<const DexFile*> dex_files;
- const DexFile* dex_file = nullptr;
- {
- ScopedObjectAccess soa(self);
- class_loader = LoadDex("ProfileTestMultiDex");
- ASSERT_NE(class_loader, nullptr);
- dex_files = GetDexFiles(class_loader);
- ASSERT_GT(dex_files.size(), 0u);
- dex_file = dex_files.front();
- }
- SetDexFilesForOatFile(dex_files);
- callbacks_->SetDoesClassUnloading(true, compiler_driver_.get());
- ClassReference ref(dex_file, 0u);
- // Test that the status is read from the compiler driver as expected.
- static_assert(enum_cast<size_t>(ClassStatus::kLast) < std::numeric_limits<size_t>::max(),
- "Make sure incrementing the class status does not overflow.");
- for (size_t i = enum_cast<size_t>(ClassStatus::kRetryVerificationAtRuntime);
- i <= enum_cast<size_t>(ClassStatus::kLast);
- ++i) {
- const ClassStatus expected_status = enum_cast<ClassStatus>(i);
- // Skip unsupported status that are not supposed to be ever recorded.
- if (expected_status == ClassStatus::kVerifyingAtRuntime ||
- expected_status == ClassStatus::kInitializing) {
- continue;
- }
- compiler_driver_->RecordClassStatus(ref, expected_status);
- ClassStatus status = {};
- ASSERT_TRUE(compiler_driver_->GetCompiledClass(ref, &status));
- EXPECT_EQ(status, expected_status);
- }
-}
-
-// TODO: need check-cast test (when stub complete & we can throw/catch
-
-} // namespace art