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 "common_compiler_test.h"
     18 
     19 #include "arch/instruction_set_features.h"
     20 #include "art_field-inl.h"
     21 #include "art_method.h"
     22 #include "class_linker.h"
     23 #include "compiled_method.h"
     24 #include "dex/quick_compiler_callbacks.h"
     25 #include "dex/quick/dex_file_to_method_inliner_map.h"
     26 #include "dex/verification_results.h"
     27 #include "driver/compiler_driver.h"
     28 #include "driver/compiler_options.h"
     29 #include "interpreter/interpreter.h"
     30 #include "mirror/class_loader.h"
     31 #include "mirror/class-inl.h"
     32 #include "mirror/dex_cache.h"
     33 #include "mirror/object-inl.h"
     34 #include "oat_quick_method_header.h"
     35 #include "scoped_thread_state_change.h"
     36 #include "thread-inl.h"
     37 #include "utils.h"
     38 
     39 namespace art {
     40 
     41 CommonCompilerTest::CommonCompilerTest() {}
     42 CommonCompilerTest::~CommonCompilerTest() {}
     43 
     44 void CommonCompilerTest::MakeExecutable(ArtMethod* method) {
     45   CHECK(method != nullptr);
     46 
     47   const CompiledMethod* compiled_method = nullptr;
     48   if (!method->IsAbstract()) {
     49     mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
     50     const DexFile& dex_file = *dex_cache->GetDexFile();
     51     compiled_method =
     52         compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
     53                                                             method->GetDexMethodIndex()));
     54   }
     55   if (compiled_method != nullptr) {
     56     ArrayRef<const uint8_t> code = compiled_method->GetQuickCode();
     57     uint32_t code_size = code.size();
     58     CHECK_NE(0u, code_size);
     59     ArrayRef<const uint8_t> vmap_table = compiled_method->GetVmapTable();
     60     uint32_t vmap_table_offset = vmap_table.empty() ? 0u
     61         : sizeof(OatQuickMethodHeader) + vmap_table.size();
     62     OatQuickMethodHeader method_header(vmap_table_offset,
     63                                        compiled_method->GetFrameSizeInBytes(),
     64                                        compiled_method->GetCoreSpillMask(),
     65                                        compiled_method->GetFpSpillMask(),
     66                                        code_size);
     67 
     68     header_code_and_maps_chunks_.push_back(std::vector<uint8_t>());
     69     std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back();
     70     const size_t max_padding = GetInstructionSetAlignment(compiled_method->GetInstructionSet());
     71     const size_t size = vmap_table.size() + sizeof(method_header) + code_size;
     72     chunk->reserve(size + max_padding);
     73     chunk->resize(sizeof(method_header));
     74     memcpy(&(*chunk)[0], &method_header, sizeof(method_header));
     75     chunk->insert(chunk->begin(), vmap_table.begin(), vmap_table.end());
     76     chunk->insert(chunk->end(), code.begin(), code.end());
     77     CHECK_EQ(chunk->size(), size);
     78     const void* unaligned_code_ptr = chunk->data() + (size - code_size);
     79     size_t offset = dchecked_integral_cast<size_t>(reinterpret_cast<uintptr_t>(unaligned_code_ptr));
     80     size_t padding = compiled_method->AlignCode(offset) - offset;
     81     // Make sure no resizing takes place.
     82     CHECK_GE(chunk->capacity(), chunk->size() + padding);
     83     chunk->insert(chunk->begin(), padding, 0);
     84     const void* code_ptr = reinterpret_cast<const uint8_t*>(unaligned_code_ptr) + padding;
     85     CHECK_EQ(code_ptr, static_cast<const void*>(chunk->data() + (chunk->size() - code_size)));
     86     MakeExecutable(code_ptr, code.size());
     87     const void* method_code = CompiledMethod::CodePointer(code_ptr,
     88                                                           compiled_method->GetInstructionSet());
     89     LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
     90     class_linker_->SetEntryPointsToCompiledCode(method, method_code);
     91   } else {
     92     // No code? You must mean to go into the interpreter.
     93     // Or the generic JNI...
     94     class_linker_->SetEntryPointsToInterpreter(method);
     95   }
     96 }
     97 
     98 void CommonCompilerTest::MakeExecutable(const void* code_start, size_t code_length) {
     99   CHECK(code_start != nullptr);
    100   CHECK_NE(code_length, 0U);
    101   uintptr_t data = reinterpret_cast<uintptr_t>(code_start);
    102   uintptr_t base = RoundDown(data, kPageSize);
    103   uintptr_t limit = RoundUp(data + code_length, kPageSize);
    104   uintptr_t len = limit - base;
    105   int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
    106   CHECK_EQ(result, 0);
    107 
    108   FlushInstructionCache(reinterpret_cast<char*>(base), reinterpret_cast<char*>(base + len));
    109 }
    110 
    111 void CommonCompilerTest::MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name) {
    112   std::string class_descriptor(DotToDescriptor(class_name));
    113   Thread* self = Thread::Current();
    114   StackHandleScope<1> hs(self);
    115   Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
    116   mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
    117   CHECK(klass != nullptr) << "Class not found " << class_name;
    118   size_t pointer_size = class_linker_->GetImagePointerSize();
    119   for (auto& m : klass->GetMethods(pointer_size)) {
    120     MakeExecutable(&m);
    121   }
    122 }
    123 
    124 // Get the set of image classes given to the compiler-driver in SetUp. Note: the compiler
    125 // driver assumes ownership of the set, so the test should properly release the set.
    126 std::unordered_set<std::string>* CommonCompilerTest::GetImageClasses() {
    127   // Empty set: by default no classes are retained in the image.
    128   return new std::unordered_set<std::string>();
    129 }
    130 
    131 // Get the set of compiled classes given to the compiler-driver in SetUp. Note: the compiler
    132 // driver assumes ownership of the set, so the test should properly release the set.
    133 std::unordered_set<std::string>* CommonCompilerTest::GetCompiledClasses() {
    134   // Null, no selection of compiled-classes.
    135   return nullptr;
    136 }
    137 
    138 // Get the set of compiled methods given to the compiler-driver in SetUp. Note: the compiler
    139 // driver assumes ownership of the set, so the test should properly release the set.
    140 std::unordered_set<std::string>* CommonCompilerTest::GetCompiledMethods() {
    141   // Null, no selection of compiled-methods.
    142   return nullptr;
    143 }
    144 
    145 // Get ProfileCompilationInfo that should be passed to the driver.
    146 ProfileCompilationInfo* CommonCompilerTest::GetProfileCompilationInfo() {
    147   // Null, profile information will not be taken into account.
    148   return nullptr;
    149 }
    150 
    151 void CommonCompilerTest::SetUp() {
    152   CommonRuntimeTest::SetUp();
    153   {
    154     ScopedObjectAccess soa(Thread::Current());
    155 
    156     const InstructionSet instruction_set = kRuntimeISA;
    157     // Take the default set of instruction features from the build.
    158     instruction_set_features_.reset(InstructionSetFeatures::FromCppDefines());
    159 
    160     runtime_->SetInstructionSet(instruction_set);
    161     for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
    162       Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
    163       if (!runtime_->HasCalleeSaveMethod(type)) {
    164         runtime_->SetCalleeSaveMethod(runtime_->CreateCalleeSaveMethod(), type);
    165       }
    166     }
    167 
    168     timer_.reset(new CumulativeLogger("Compilation times"));
    169     CreateCompilerDriver(compiler_kind_, instruction_set);
    170   }
    171 }
    172 
    173 void CommonCompilerTest::CreateCompilerDriver(Compiler::Kind kind,
    174                                               InstructionSet isa,
    175                                               size_t number_of_threads) {
    176   compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
    177                                             verification_results_.get(),
    178                                             method_inliner_map_.get(),
    179                                             kind,
    180                                             isa,
    181                                             instruction_set_features_.get(),
    182                                             /* boot_image */ true,
    183                                             /* app_image */ false,
    184                                             GetImageClasses(),
    185                                             GetCompiledClasses(),
    186                                             GetCompiledMethods(),
    187                                             number_of_threads,
    188                                             /* dump_stats */ true,
    189                                             /* dump_passes */ true,
    190                                             timer_.get(),
    191                                             /* swap_fd */ -1,
    192                                             GetProfileCompilationInfo()));
    193   // We typically don't generate an image in unit tests, disable this optimization by default.
    194   compiler_driver_->SetSupportBootImageFixup(false);
    195 }
    196 
    197 void CommonCompilerTest::SetUpRuntimeOptions(RuntimeOptions* options) {
    198   CommonRuntimeTest::SetUpRuntimeOptions(options);
    199 
    200   compiler_options_.reset(new CompilerOptions);
    201   verification_results_.reset(new VerificationResults(compiler_options_.get()));
    202   method_inliner_map_.reset(new DexFileToMethodInlinerMap);
    203   callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
    204                                               method_inliner_map_.get(),
    205                                               CompilerCallbacks::CallbackMode::kCompileApp));
    206 }
    207 
    208 Compiler::Kind CommonCompilerTest::GetCompilerKind() const {
    209   return compiler_kind_;
    210 }
    211 
    212 void CommonCompilerTest::SetCompilerKind(Compiler::Kind compiler_kind) {
    213   compiler_kind_ = compiler_kind;
    214 }
    215 
    216 InstructionSet CommonCompilerTest::GetInstructionSet() const {
    217   DCHECK(compiler_driver_.get() != nullptr);
    218   return compiler_driver_->GetInstructionSet();
    219 }
    220 
    221 void CommonCompilerTest::TearDown() {
    222   timer_.reset();
    223   compiler_driver_.reset();
    224   callbacks_.reset();
    225   method_inliner_map_.reset();
    226   verification_results_.reset();
    227   compiler_options_.reset();
    228 
    229   CommonRuntimeTest::TearDown();
    230 }
    231 
    232 void CommonCompilerTest::CompileClass(mirror::ClassLoader* class_loader, const char* class_name) {
    233   std::string class_descriptor(DotToDescriptor(class_name));
    234   Thread* self = Thread::Current();
    235   StackHandleScope<1> hs(self);
    236   Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
    237   mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
    238   CHECK(klass != nullptr) << "Class not found " << class_name;
    239   auto pointer_size = class_linker_->GetImagePointerSize();
    240   for (auto& m : klass->GetMethods(pointer_size)) {
    241     CompileMethod(&m);
    242   }
    243 }
    244 
    245 void CommonCompilerTest::CompileMethod(ArtMethod* method) {
    246   CHECK(method != nullptr);
    247   TimingLogger timings("CommonTest::CompileMethod", false, false);
    248   TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
    249   compiler_driver_->CompileOne(Thread::Current(), method, &timings);
    250   TimingLogger::ScopedTiming t2("MakeExecutable", &timings);
    251   MakeExecutable(method);
    252 }
    253 
    254 void CommonCompilerTest::CompileDirectMethod(Handle<mirror::ClassLoader> class_loader,
    255                                              const char* class_name, const char* method_name,
    256                                              const char* signature) {
    257   std::string class_descriptor(DotToDescriptor(class_name));
    258   Thread* self = Thread::Current();
    259   mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
    260   CHECK(klass != nullptr) << "Class not found " << class_name;
    261   auto pointer_size = class_linker_->GetImagePointerSize();
    262   ArtMethod* method = klass->FindDirectMethod(method_name, signature, pointer_size);
    263   CHECK(method != nullptr) << "Direct method not found: "
    264       << class_name << "." << method_name << signature;
    265   CompileMethod(method);
    266 }
    267 
    268 void CommonCompilerTest::CompileVirtualMethod(Handle<mirror::ClassLoader> class_loader,
    269                                               const char* class_name, const char* method_name,
    270                                               const char* signature) {
    271   std::string class_descriptor(DotToDescriptor(class_name));
    272   Thread* self = Thread::Current();
    273   mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
    274   CHECK(klass != nullptr) << "Class not found " << class_name;
    275   auto pointer_size = class_linker_->GetImagePointerSize();
    276   ArtMethod* method = klass->FindVirtualMethod(method_name, signature, pointer_size);
    277   CHECK(method != nullptr) << "Virtual method not found: "
    278       << class_name << "." << method_name << signature;
    279   CompileMethod(method);
    280 }
    281 
    282 void CommonCompilerTest::ReserveImageSpace() {
    283   // Reserve where the image will be loaded up front so that other parts of test set up don't
    284   // accidentally end up colliding with the fixed memory address when we need to load the image.
    285   std::string error_msg;
    286   MemMap::Init();
    287   image_reservation_.reset(MemMap::MapAnonymous("image reservation",
    288                                                 reinterpret_cast<uint8_t*>(ART_BASE_ADDRESS),
    289                                                 (size_t)120 * 1024 * 1024,  // 120MB
    290                                                 PROT_NONE,
    291                                                 false /* no need for 4gb flag with fixed mmap*/,
    292                                                 false /* not reusing existing reservation */,
    293                                                 &error_msg));
    294   CHECK(image_reservation_.get() != nullptr) << error_msg;
    295 }
    296 
    297 void CommonCompilerTest::UnreserveImageSpace() {
    298   image_reservation_.reset();
    299 }
    300 
    301 }  // namespace art
    302