diff options
author | Vladimir Marko <vmarko@google.com> | 2019-03-04 12:53:20 +0000 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2019-03-11 06:59:41 +0000 |
commit | 327497e303903f300b01f77f2259fd5b61238ee3 (patch) | |
tree | 3f714d2d2ee7d9b6c0ecf71a10c157d4952e5758 /compiler/driver/compiler_driver_test.cc | |
parent | ef764ad3e6d7f07ea9e32642dc3e163bb4eb44fb (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.cc | 370 |
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 |