Home | History | Annotate | Download | only in driver
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "driver/compiler_driver.h"
     18 
     19 #include <limits>
     20 #include <stdint.h>
     21 #include <stdio.h>
     22 #include <memory>
     23 
     24 #include "art_method-inl.h"
     25 #include "base/casts.h"
     26 #include "class_linker-inl.h"
     27 #include "common_compiler_test.h"
     28 #include "compiler_callbacks.h"
     29 #include "dex/dex_file.h"
     30 #include "dex/dex_file_types.h"
     31 #include "gc/heap.h"
     32 #include "handle_scope-inl.h"
     33 #include "jit/profile_compilation_info.h"
     34 #include "mirror/class-inl.h"
     35 #include "mirror/class_loader.h"
     36 #include "mirror/dex_cache-inl.h"
     37 #include "mirror/object-inl.h"
     38 #include "mirror/object_array-inl.h"
     39 #include "scoped_thread_state_change-inl.h"
     40 
     41 namespace art {
     42 
     43 class CompilerDriverTest : public CommonCompilerTest {
     44  protected:
     45   void CompileAll(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
     46     TimingLogger timings("CompilerDriverTest::CompileAll", false, false);
     47     TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
     48     dex_files_ = GetDexFiles(class_loader);
     49     compiler_driver_->SetDexFilesForOatFile(dex_files_);;
     50     compiler_driver_->CompileAll(class_loader, dex_files_, &timings);
     51     t.NewTiming("MakeAllExecutable");
     52     MakeAllExecutable(class_loader);
     53   }
     54 
     55   void EnsureCompiled(jobject class_loader, const char* class_name, const char* method,
     56                       const char* signature, bool is_virtual)
     57       REQUIRES(!Locks::mutator_lock_) {
     58     CompileAll(class_loader);
     59     Thread::Current()->TransitionFromSuspendedToRunnable();
     60     bool started = runtime_->Start();
     61     CHECK(started);
     62     env_ = Thread::Current()->GetJniEnv();
     63     class_ = env_->FindClass(class_name);
     64     CHECK(class_ != nullptr) << "Class not found: " << class_name;
     65     if (is_virtual) {
     66       mid_ = env_->GetMethodID(class_, method, signature);
     67     } else {
     68       mid_ = env_->GetStaticMethodID(class_, method, signature);
     69     }
     70     CHECK(mid_ != nullptr) << "Method not found: " << class_name << "." << method << signature;
     71   }
     72 
     73   void MakeAllExecutable(jobject class_loader) {
     74     const std::vector<const DexFile*> class_path = GetDexFiles(class_loader);
     75     for (size_t i = 0; i != class_path.size(); ++i) {
     76       const DexFile* dex_file = class_path[i];
     77       CHECK(dex_file != nullptr);
     78       MakeDexFileExecutable(class_loader, *dex_file);
     79     }
     80   }
     81 
     82   void MakeDexFileExecutable(jobject class_loader, const DexFile& dex_file) {
     83     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     84     for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
     85       const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
     86       const char* descriptor = dex_file.GetClassDescriptor(class_def);
     87       ScopedObjectAccess soa(Thread::Current());
     88       StackHandleScope<1> hs(soa.Self());
     89       Handle<mirror::ClassLoader> loader(
     90           hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
     91       mirror::Class* c = class_linker->FindClass(soa.Self(), descriptor, loader);
     92       CHECK(c != nullptr);
     93       const auto pointer_size = class_linker->GetImagePointerSize();
     94       for (auto& m : c->GetMethods(pointer_size)) {
     95         MakeExecutable(&m);
     96       }
     97     }
     98   }
     99 
    100   JNIEnv* env_;
    101   jclass class_;
    102   jmethodID mid_;
    103   std::vector<const DexFile*> dex_files_;
    104 };
    105 
    106 // Disabled due to 10 second runtime on host
    107 // TODO: Update the test for hash-based dex cache arrays. Bug: 30627598
    108 TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
    109   CompileAll(nullptr);
    110 
    111   // All libcore references should resolve
    112   ScopedObjectAccess soa(Thread::Current());
    113   ASSERT_TRUE(java_lang_dex_file_ != nullptr);
    114   const DexFile& dex = *java_lang_dex_file_;
    115   ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(soa.Self(), dex);
    116   EXPECT_EQ(dex.NumStringIds(), dex_cache->NumStrings());
    117   for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
    118     const mirror::String* string = dex_cache->GetResolvedString(dex::StringIndex(i));
    119     EXPECT_TRUE(string != nullptr) << "string_idx=" << i;
    120   }
    121   EXPECT_EQ(dex.NumTypeIds(), dex_cache->NumResolvedTypes());
    122   for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
    123     mirror::Class* type = dex_cache->GetResolvedType(dex::TypeIndex(i));
    124     EXPECT_TRUE(type != nullptr) << "type_idx=" << i
    125                               << " " << dex.GetTypeDescriptor(dex.GetTypeId(dex::TypeIndex(i)));
    126   }
    127   EXPECT_TRUE(dex_cache->StaticMethodSize() == dex_cache->NumResolvedMethods()
    128       || dex.NumMethodIds() ==  dex_cache->NumResolvedMethods());
    129   auto* cl = Runtime::Current()->GetClassLinker();
    130   auto pointer_size = cl->GetImagePointerSize();
    131   for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
    132     // FIXME: This is outdated for hash-based method array.
    133     ArtMethod* method = dex_cache->GetResolvedMethod(i, pointer_size);
    134     EXPECT_TRUE(method != nullptr) << "method_idx=" << i
    135                                 << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i))
    136                                 << " " << dex.GetMethodName(dex.GetMethodId(i));
    137     EXPECT_TRUE(method->GetEntryPointFromQuickCompiledCode() != nullptr) << "method_idx=" << i
    138         << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i)) << " "
    139         << dex.GetMethodName(dex.GetMethodId(i));
    140   }
    141   EXPECT_TRUE(dex_cache->StaticArtFieldSize() == dex_cache->NumResolvedFields()
    142       || dex.NumFieldIds() ==  dex_cache->NumResolvedFields());
    143   for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
    144     // FIXME: This is outdated for hash-based field array.
    145     ArtField* field = dex_cache->GetResolvedField(i, cl->GetImagePointerSize());
    146     EXPECT_TRUE(field != nullptr) << "field_idx=" << i
    147                                << " " << dex.GetFieldDeclaringClassDescriptor(dex.GetFieldId(i))
    148                                << " " << dex.GetFieldName(dex.GetFieldId(i));
    149   }
    150 
    151   // TODO check Class::IsVerified for all classes
    152 
    153   // TODO: check that all Method::GetCode() values are non-null
    154 }
    155 
    156 TEST_F(CompilerDriverTest, AbstractMethodErrorStub) {
    157   jobject class_loader;
    158   {
    159     ScopedObjectAccess soa(Thread::Current());
    160     class_loader = LoadDex("AbstractMethod");
    161   }
    162   ASSERT_TRUE(class_loader != nullptr);
    163   EnsureCompiled(class_loader, "AbstractClass", "foo", "()V", true);
    164 
    165   // Create a jobj_ of ConcreteClass, NOT AbstractClass.
    166   jclass c_class = env_->FindClass("ConcreteClass");
    167 
    168   jmethodID constructor = env_->GetMethodID(c_class, "<init>", "()V");
    169 
    170   jobject jobj_ = env_->NewObject(c_class, constructor);
    171   ASSERT_TRUE(jobj_ != nullptr);
    172 
    173   // Force non-virtual call to AbstractClass foo, will throw AbstractMethodError exception.
    174   env_->CallNonvirtualVoidMethod(jobj_, class_, mid_);
    175 
    176   EXPECT_EQ(env_->ExceptionCheck(), JNI_TRUE);
    177   jthrowable exception = env_->ExceptionOccurred();
    178   env_->ExceptionClear();
    179   jclass jlame = env_->FindClass("java/lang/AbstractMethodError");
    180   EXPECT_TRUE(env_->IsInstanceOf(exception, jlame));
    181   {
    182     ScopedObjectAccess soa(Thread::Current());
    183     Thread::Current()->ClearException();
    184   }
    185 }
    186 
    187 class CompilerDriverMethodsTest : public CompilerDriverTest {
    188  protected:
    189   std::unordered_set<std::string>* GetCompiledMethods() OVERRIDE {
    190     return new std::unordered_set<std::string>({
    191       "byte StaticLeafMethods.identity(byte)",
    192       "int StaticLeafMethods.sum(int, int, int)",
    193       "double StaticLeafMethods.sum(double, double, double, double)"
    194     });
    195   }
    196 };
    197 
    198 TEST_F(CompilerDriverMethodsTest, Selection) {
    199   Thread* self = Thread::Current();
    200   jobject class_loader;
    201   {
    202     ScopedObjectAccess soa(self);
    203     class_loader = LoadDex("StaticLeafMethods");
    204   }
    205   ASSERT_NE(class_loader, nullptr);
    206 
    207   // Need to enable dex-file writability. Methods rejected to be compiled will run through the
    208   // dex-to-dex compiler.
    209   for (const DexFile* dex_file : GetDexFiles(class_loader)) {
    210     ASSERT_TRUE(dex_file->EnableWrite());
    211   }
    212 
    213   CompileAll(class_loader);
    214 
    215   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    216   ScopedObjectAccess soa(self);
    217   StackHandleScope<1> hs(self);
    218   Handle<mirror::ClassLoader> h_loader(
    219       hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
    220   mirror::Class* klass = class_linker->FindClass(self, "LStaticLeafMethods;", h_loader);
    221   ASSERT_NE(klass, nullptr);
    222 
    223   std::unique_ptr<std::unordered_set<std::string>> expected(GetCompiledMethods());
    224 
    225   const auto pointer_size = class_linker->GetImagePointerSize();
    226   for (auto& m : klass->GetDirectMethods(pointer_size)) {
    227     std::string name = m.PrettyMethod(true);
    228     const void* code = m.GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
    229     ASSERT_NE(code, nullptr);
    230     if (expected->find(name) != expected->end()) {
    231       expected->erase(name);
    232       EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code));
    233     } else {
    234       EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code));
    235     }
    236   }
    237   EXPECT_TRUE(expected->empty());
    238 }
    239 
    240 class CompilerDriverProfileTest : public CompilerDriverTest {
    241  protected:
    242   ProfileCompilationInfo* GetProfileCompilationInfo() OVERRIDE {
    243     ScopedObjectAccess soa(Thread::Current());
    244     std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ProfileTestMultiDex");
    245 
    246     ProfileCompilationInfo info;
    247     for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
    248       profile_info_.AddMethodIndex(ProfileCompilationInfo::MethodHotness::kFlagHot,
    249                                    MethodReference(dex_file.get(), 1));
    250       profile_info_.AddMethodIndex(ProfileCompilationInfo::MethodHotness::kFlagHot,
    251                                    MethodReference(dex_file.get(), 2));
    252     }
    253     return &profile_info_;
    254   }
    255 
    256   CompilerFilter::Filter GetCompilerFilter() const OVERRIDE {
    257     // Use a profile based filter.
    258     return CompilerFilter::kSpeedProfile;
    259   }
    260 
    261   std::unordered_set<std::string> GetExpectedMethodsForClass(const std::string& clazz) {
    262     if (clazz == "Main") {
    263       return std::unordered_set<std::string>({
    264           "java.lang.String Main.getA()",
    265           "java.lang.String Main.getB()"});
    266     } else if (clazz == "Second") {
    267       return std::unordered_set<std::string>({
    268           "java.lang.String Second.getX()",
    269           "java.lang.String Second.getY()"});
    270     } else {
    271       return std::unordered_set<std::string>();
    272     }
    273   }
    274 
    275   void CheckCompiledMethods(jobject class_loader,
    276                             const std::string& clazz,
    277                             const std::unordered_set<std::string>& expected_methods) {
    278     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    279     Thread* self = Thread::Current();
    280     ScopedObjectAccess soa(self);
    281     StackHandleScope<1> hs(self);
    282     Handle<mirror::ClassLoader> h_loader(
    283         hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
    284     mirror::Class* klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
    285     ASSERT_NE(klass, nullptr);
    286 
    287     const auto pointer_size = class_linker->GetImagePointerSize();
    288     size_t number_of_compiled_methods = 0;
    289     for (auto& m : klass->GetVirtualMethods(pointer_size)) {
    290       std::string name = m.PrettyMethod(true);
    291       const void* code = m.GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
    292       ASSERT_NE(code, nullptr);
    293       if (expected_methods.find(name) != expected_methods.end()) {
    294         number_of_compiled_methods++;
    295         EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code));
    296       } else {
    297         EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code));
    298       }
    299     }
    300     EXPECT_EQ(expected_methods.size(), number_of_compiled_methods);
    301   }
    302 
    303  private:
    304   ProfileCompilationInfo profile_info_;
    305 };
    306 
    307 TEST_F(CompilerDriverProfileTest, ProfileGuidedCompilation) {
    308   Thread* self = Thread::Current();
    309   jobject class_loader;
    310   {
    311     ScopedObjectAccess soa(self);
    312     class_loader = LoadDex("ProfileTestMultiDex");
    313   }
    314   ASSERT_NE(class_loader, nullptr);
    315 
    316   // Need to enable dex-file writability. Methods rejected to be compiled will run through the
    317   // dex-to-dex compiler.
    318   for (const DexFile* dex_file : GetDexFiles(class_loader)) {
    319     ASSERT_TRUE(dex_file->EnableWrite());
    320   }
    321 
    322   CompileAll(class_loader);
    323 
    324   std::unordered_set<std::string> m = GetExpectedMethodsForClass("Main");
    325   std::unordered_set<std::string> s = GetExpectedMethodsForClass("Second");
    326   CheckCompiledMethods(class_loader, "LMain;", m);
    327   CheckCompiledMethods(class_loader, "LSecond;", s);
    328 }
    329 
    330 // Test that a verify only compiler filter updates the CompiledClass map,
    331 // which will be used for OatClass.
    332 class CompilerDriverVerifyTest : public CompilerDriverTest {
    333  protected:
    334   CompilerFilter::Filter GetCompilerFilter() const OVERRIDE {
    335     return CompilerFilter::kVerify;
    336   }
    337 
    338   void CheckVerifiedClass(jobject class_loader, const std::string& clazz) const {
    339     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    340     Thread* self = Thread::Current();
    341     ScopedObjectAccess soa(self);
    342     StackHandleScope<1> hs(self);
    343     Handle<mirror::ClassLoader> h_loader(
    344         hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
    345     mirror::Class* klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
    346     ASSERT_NE(klass, nullptr);
    347     EXPECT_TRUE(klass->IsVerified());
    348 
    349     ClassStatus status;
    350     bool found = compiler_driver_->GetCompiledClass(
    351         ClassReference(&klass->GetDexFile(), klass->GetDexTypeIndex().index_), &status);
    352     ASSERT_TRUE(found);
    353     EXPECT_EQ(status, ClassStatus::kVerified);
    354   }
    355 };
    356 
    357 TEST_F(CompilerDriverVerifyTest, VerifyCompilation) {
    358   Thread* self = Thread::Current();
    359   jobject class_loader;
    360   {
    361     ScopedObjectAccess soa(self);
    362     class_loader = LoadDex("ProfileTestMultiDex");
    363   }
    364   ASSERT_NE(class_loader, nullptr);
    365 
    366   CompileAll(class_loader);
    367 
    368   CheckVerifiedClass(class_loader, "LMain;");
    369   CheckVerifiedClass(class_loader, "LSecond;");
    370 }
    371 
    372 // Test that a class of status ClassStatus::kRetryVerificationAtRuntime is indeed
    373 // recorded that way in the driver.
    374 TEST_F(CompilerDriverVerifyTest, RetryVerifcationStatusCheckVerified) {
    375   Thread* const self = Thread::Current();
    376   jobject class_loader;
    377   std::vector<const DexFile*> dex_files;
    378   const DexFile* dex_file = nullptr;
    379   {
    380     ScopedObjectAccess soa(self);
    381     class_loader = LoadDex("ProfileTestMultiDex");
    382     ASSERT_NE(class_loader, nullptr);
    383     dex_files = GetDexFiles(class_loader);
    384     ASSERT_GT(dex_files.size(), 0u);
    385     dex_file = dex_files.front();
    386   }
    387   compiler_driver_->SetDexFilesForOatFile(dex_files);
    388   callbacks_->SetDoesClassUnloading(true, compiler_driver_.get());
    389   ClassReference ref(dex_file, 0u);
    390   // Test that the status is read from the compiler driver as expected.
    391   static_assert(enum_cast<size_t>(ClassStatus::kLast) < std::numeric_limits<size_t>::max(),
    392                 "Make sure incrementing the class status does not overflow.");
    393   for (size_t i = enum_cast<size_t>(ClassStatus::kRetryVerificationAtRuntime);
    394        i <= enum_cast<size_t>(ClassStatus::kLast);
    395        ++i) {
    396     const ClassStatus expected_status = enum_cast<ClassStatus>(i);
    397     // Skip unsupported status that are not supposed to be ever recorded.
    398     if (expected_status == ClassStatus::kVerifyingAtRuntime ||
    399         expected_status == ClassStatus::kInitializing) {
    400       continue;
    401     }
    402     compiler_driver_->RecordClassStatus(ref, expected_status);
    403     ClassStatus status = {};
    404     ASSERT_TRUE(compiler_driver_->GetCompiledClass(ref, &status));
    405     EXPECT_EQ(status, expected_status);
    406   }
    407 }
    408 
    409 // TODO: need check-cast test (when stub complete & we can throw/catch
    410 
    411 }  // namespace art
    412