Home | History | Annotate | Download | only in compiler
      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 "compiler/oat_writer.h"
     18 #include "mirror/art_method-inl.h"
     19 #include "mirror/class-inl.h"
     20 #include "mirror/object_array-inl.h"
     21 #include "mirror/object-inl.h"
     22 #include "oat_file.h"
     23 #include "vector_output_stream.h"
     24 
     25 #include "common_test.h"
     26 
     27 namespace art {
     28 
     29 class OatTest : public CommonTest {
     30  protected:
     31   void CheckMethod(mirror::ArtMethod* method,
     32                    const OatFile::OatMethod& oat_method,
     33                    const DexFile* dex_file)
     34       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     35     const CompiledMethod* compiled_method =
     36         compiler_driver_->GetCompiledMethod(MethodReference(dex_file,
     37                                                             method->GetDexMethodIndex()));
     38 
     39     if (compiled_method == NULL) {
     40       EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " "
     41                                                 << oat_method.GetCode();
     42 #if !defined(ART_USE_PORTABLE_COMPILER)
     43       EXPECT_EQ(oat_method.GetFrameSizeInBytes(), static_cast<uint32_t>(kStackAlignment));
     44       EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
     45       EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
     46 #endif
     47     } else {
     48       const void* oat_code = oat_method.GetCode();
     49       EXPECT_TRUE(oat_code != NULL) << PrettyMethod(method);
     50       uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
     51       oat_code = reinterpret_cast<const void*>(oat_code_aligned);
     52 
     53       const std::vector<uint8_t>& code = compiled_method->GetCode();
     54       size_t code_size = code.size() * sizeof(code[0]);
     55       EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
     56           << PrettyMethod(method) << " " << code_size;
     57       CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
     58 #if !defined(ART_USE_PORTABLE_COMPILER)
     59       EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
     60       EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
     61       EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
     62 #endif
     63     }
     64   }
     65 };
     66 
     67 TEST_F(OatTest, WriteRead) {
     68   const bool compile = false;  // DISABLED_ due to the time to compile libcore
     69   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     70 
     71   // TODO: make selectable
     72 #if defined(ART_USE_PORTABLE_COMPILER)
     73   CompilerBackend compiler_backend = kPortable;
     74 #else
     75   CompilerBackend compiler_backend = kQuick;
     76 #endif
     77   InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
     78   compiler_driver_.reset(new CompilerDriver(compiler_backend, insn_set, false, NULL, 2, true));
     79   jobject class_loader = NULL;
     80   if (compile) {
     81     base::TimingLogger timings("OatTest::WriteRead", false, false);
     82     compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), timings);
     83   }
     84 
     85   ScopedObjectAccess soa(Thread::Current());
     86   ScratchFile tmp;
     87   OatWriter oat_writer(class_linker->GetBootClassPath(),
     88                        42U,
     89                        4096U,
     90                        "lue.art",
     91                        compiler_driver_.get());
     92   bool success = compiler_driver_->WriteElf(GetTestAndroidRoot(),
     93                                             !kIsTargetBuild,
     94                                             class_linker->GetBootClassPath(),
     95                                             oat_writer,
     96                                             tmp.GetFile());
     97   ASSERT_TRUE(success);
     98 
     99   if (compile) {  // OatWriter strips the code, regenerate to compare
    100     base::TimingLogger timings("CommonTest::WriteRead", false, false);
    101     compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), timings);
    102   }
    103   UniquePtr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), NULL, false));
    104   ASSERT_TRUE(oat_file.get() != NULL);
    105   const OatHeader& oat_header = oat_file->GetOatHeader();
    106   ASSERT_TRUE(oat_header.IsValid());
    107   ASSERT_EQ(2U, oat_header.GetDexFileCount());  // core and conscrypt
    108   ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
    109   ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatDataBegin());
    110   ASSERT_EQ("lue.art", oat_header.GetImageFileLocation());
    111 
    112   const DexFile* dex_file = java_lang_dex_file_;
    113   uint32_t dex_file_checksum = dex_file->GetLocationChecksum();
    114   const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file->GetLocation(),
    115                                                                     &dex_file_checksum);
    116   CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
    117   for (size_t i = 0; i < dex_file->NumClassDefs(); i++) {
    118     const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
    119     const byte* class_data = dex_file->GetClassData(class_def);
    120     size_t num_virtual_methods =0;
    121     if (class_data != NULL) {
    122       ClassDataItemIterator it(*dex_file, class_data);
    123       num_virtual_methods = it.NumVirtualMethods();
    124     }
    125     const char* descriptor = dex_file->GetClassDescriptor(class_def);
    126 
    127     UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i));
    128 
    129     mirror::Class* klass = class_linker->FindClass(descriptor, NULL);
    130 
    131     size_t method_index = 0;
    132     for (size_t i = 0; i < klass->NumDirectMethods(); i++, method_index++) {
    133       CheckMethod(klass->GetDirectMethod(i),
    134                   oat_class->GetOatMethod(method_index), dex_file);
    135     }
    136     for (size_t i = 0; i < num_virtual_methods; i++, method_index++) {
    137       CheckMethod(klass->GetVirtualMethod(i),
    138                   oat_class->GetOatMethod(method_index), dex_file);
    139     }
    140   }
    141 }
    142 
    143 TEST_F(OatTest, OatHeaderSizeCheck) {
    144   // If this test is failing and you have to update these constants,
    145   // it is time to update OatHeader::kOatVersion
    146   EXPECT_EQ(64U, sizeof(OatHeader));
    147   EXPECT_EQ(28U, sizeof(OatMethodOffsets));
    148 }
    149 
    150 TEST_F(OatTest, OatHeaderIsValid) {
    151     InstructionSet instruction_set = kX86;
    152     std::vector<const DexFile*> dex_files;
    153     uint32_t image_file_location_oat_checksum = 0;
    154     uint32_t image_file_location_oat_begin = 0;
    155     const std::string image_file_location;
    156     OatHeader oat_header(instruction_set,
    157                          &dex_files,
    158                          image_file_location_oat_checksum,
    159                          image_file_location_oat_begin,
    160                          image_file_location);
    161     ASSERT_TRUE(oat_header.IsValid());
    162 
    163     char* magic = const_cast<char*>(oat_header.GetMagic());
    164     strcpy(magic, "");  // bad magic
    165     ASSERT_FALSE(oat_header.IsValid());
    166     strcpy(magic, "oat\n000");  // bad version
    167     ASSERT_FALSE(oat_header.IsValid());
    168 }
    169 
    170 }  // namespace art
    171