1 /* 2 * Copyright 2014 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 "jit_compiler.h" 18 19 #include "arch/instruction_set.h" 20 #include "arch/instruction_set_features.h" 21 #include "art_method-inl.h" 22 #include "base/stringpiece.h" 23 #include "base/time_utils.h" 24 #include "base/timing_logger.h" 25 #include "base/unix_file/fd_file.h" 26 #include "debug/elf_debug_writer.h" 27 #include "driver/compiler_driver.h" 28 #include "driver/compiler_options.h" 29 #include "jit/debugger_interface.h" 30 #include "jit/jit.h" 31 #include "jit/jit_code_cache.h" 32 #include "oat_file-inl.h" 33 #include "oat_quick_method_header.h" 34 #include "object_lock.h" 35 #include "thread_list.h" 36 37 namespace art { 38 namespace jit { 39 40 JitCompiler* JitCompiler::Create() { 41 return new JitCompiler(); 42 } 43 44 extern "C" void* jit_load(bool* generate_debug_info) { 45 VLOG(jit) << "loading jit compiler"; 46 auto* const jit_compiler = JitCompiler::Create(); 47 CHECK(jit_compiler != nullptr); 48 *generate_debug_info = jit_compiler->GetCompilerOptions()->GetGenerateDebugInfo(); 49 VLOG(jit) << "Done loading jit compiler"; 50 return jit_compiler; 51 } 52 53 extern "C" void jit_unload(void* handle) { 54 DCHECK(handle != nullptr); 55 delete reinterpret_cast<JitCompiler*>(handle); 56 } 57 58 extern "C" bool jit_compile_method( 59 void* handle, ArtMethod* method, Thread* self, bool osr) 60 SHARED_REQUIRES(Locks::mutator_lock_) { 61 auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle); 62 DCHECK(jit_compiler != nullptr); 63 return jit_compiler->CompileMethod(self, method, osr); 64 } 65 66 extern "C" void jit_types_loaded(void* handle, mirror::Class** types, size_t count) 67 SHARED_REQUIRES(Locks::mutator_lock_) { 68 auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle); 69 DCHECK(jit_compiler != nullptr); 70 if (jit_compiler->GetCompilerOptions()->GetGenerateDebugInfo()) { 71 const ArrayRef<mirror::Class*> types_array(types, count); 72 std::vector<uint8_t> elf_file = debug::WriteDebugElfFileForClasses( 73 kRuntimeISA, jit_compiler->GetCompilerDriver()->GetInstructionSetFeatures(), types_array); 74 CreateJITCodeEntry(std::move(elf_file)); 75 } 76 } 77 78 // Callers of this method assume it has NO_RETURN. 79 NO_RETURN static void Usage(const char* fmt, ...) { 80 va_list ap; 81 va_start(ap, fmt); 82 std::string error; 83 StringAppendV(&error, fmt, ap); 84 LOG(FATAL) << error; 85 va_end(ap); 86 exit(EXIT_FAILURE); 87 } 88 89 JitCompiler::JitCompiler() { 90 compiler_options_.reset(new CompilerOptions( 91 CompilerOptions::kDefaultCompilerFilter, 92 CompilerOptions::kDefaultHugeMethodThreshold, 93 CompilerOptions::kDefaultLargeMethodThreshold, 94 CompilerOptions::kDefaultSmallMethodThreshold, 95 CompilerOptions::kDefaultTinyMethodThreshold, 96 CompilerOptions::kDefaultNumDexMethodsThreshold, 97 CompilerOptions::kDefaultInlineDepthLimit, 98 CompilerOptions::kDefaultInlineMaxCodeUnits, 99 /* no_inline_from */ nullptr, 100 /* include_patch_information */ false, 101 CompilerOptions::kDefaultTopKProfileThreshold, 102 Runtime::Current()->IsDebuggable(), 103 CompilerOptions::kDefaultGenerateDebugInfo, 104 /* implicit_null_checks */ true, 105 /* implicit_so_checks */ true, 106 /* implicit_suspend_checks */ false, 107 /* pic */ true, // TODO: Support non-PIC in optimizing. 108 /* verbose_methods */ nullptr, 109 /* init_failure_output */ nullptr, 110 /* abort_on_hard_verifier_failure */ false, 111 /* dump_cfg_file_name */ "", 112 /* dump_cfg_append */ false, 113 /* force_determinism */ false)); 114 for (const std::string& argument : Runtime::Current()->GetCompilerOptions()) { 115 compiler_options_->ParseCompilerOption(argument, Usage); 116 } 117 const InstructionSet instruction_set = kRuntimeISA; 118 for (const StringPiece option : Runtime::Current()->GetCompilerOptions()) { 119 VLOG(compiler) << "JIT compiler option " << option; 120 std::string error_msg; 121 if (option.starts_with("--instruction-set-variant=")) { 122 StringPiece str = option.substr(strlen("--instruction-set-variant=")).data(); 123 VLOG(compiler) << "JIT instruction set variant " << str; 124 instruction_set_features_.reset(InstructionSetFeatures::FromVariant( 125 instruction_set, str.as_string(), &error_msg)); 126 if (instruction_set_features_ == nullptr) { 127 LOG(WARNING) << "Error parsing " << option << " message=" << error_msg; 128 } 129 } else if (option.starts_with("--instruction-set-features=")) { 130 StringPiece str = option.substr(strlen("--instruction-set-features=")).data(); 131 VLOG(compiler) << "JIT instruction set features " << str; 132 if (instruction_set_features_.get() == nullptr) { 133 instruction_set_features_.reset(InstructionSetFeatures::FromVariant( 134 instruction_set, "default", &error_msg)); 135 if (instruction_set_features_ == nullptr) { 136 LOG(WARNING) << "Error parsing " << option << " message=" << error_msg; 137 } 138 } 139 instruction_set_features_.reset( 140 instruction_set_features_->AddFeaturesFromString(str.as_string(), &error_msg)); 141 if (instruction_set_features_ == nullptr) { 142 LOG(WARNING) << "Error parsing " << option << " message=" << error_msg; 143 } 144 } 145 } 146 if (instruction_set_features_ == nullptr) { 147 instruction_set_features_.reset(InstructionSetFeatures::FromCppDefines()); 148 } 149 cumulative_logger_.reset(new CumulativeLogger("jit times")); 150 method_inliner_map_.reset(new DexFileToMethodInlinerMap); 151 compiler_driver_.reset(new CompilerDriver( 152 compiler_options_.get(), 153 /* verification_results */ nullptr, 154 method_inliner_map_.get(), 155 Compiler::kOptimizing, 156 instruction_set, 157 instruction_set_features_.get(), 158 /* boot_image */ false, 159 /* app_image */ false, 160 /* image_classes */ nullptr, 161 /* compiled_classes */ nullptr, 162 /* compiled_methods */ nullptr, 163 /* thread_count */ 1, 164 /* dump_stats */ false, 165 /* dump_passes */ false, 166 cumulative_logger_.get(), 167 /* swap_fd */ -1, 168 /* profile_compilation_info */ nullptr)); 169 // Disable dedupe so we can remove compiled methods. 170 compiler_driver_->SetDedupeEnabled(false); 171 compiler_driver_->SetSupportBootImageFixup(false); 172 173 size_t thread_count = compiler_driver_->GetThreadCount(); 174 if (compiler_options_->GetGenerateDebugInfo()) { 175 #ifdef __ANDROID__ 176 const char* prefix = "/data/misc/trace"; 177 #else 178 const char* prefix = "/tmp"; 179 #endif 180 DCHECK_EQ(thread_count, 1u) 181 << "Generating debug info only works with one compiler thread"; 182 std::string perf_filename = std::string(prefix) + "/perf-" + std::to_string(getpid()) + ".map"; 183 perf_file_.reset(OS::CreateEmptyFileWriteOnly(perf_filename.c_str())); 184 if (perf_file_ == nullptr) { 185 LOG(ERROR) << "Could not create perf file at " << perf_filename << 186 " Are you on a user build? Perf only works on userdebug/eng builds"; 187 } 188 } 189 190 size_t inline_depth_limit = compiler_driver_->GetCompilerOptions().GetInlineDepthLimit(); 191 DCHECK_LT(thread_count * inline_depth_limit, std::numeric_limits<uint16_t>::max()) 192 << "ProfilingInfo's inline counter can potentially overflow"; 193 } 194 195 JitCompiler::~JitCompiler() { 196 if (perf_file_ != nullptr) { 197 UNUSED(perf_file_->Flush()); 198 UNUSED(perf_file_->Close()); 199 } 200 } 201 202 bool JitCompiler::CompileMethod(Thread* self, ArtMethod* method, bool osr) { 203 DCHECK(!method->IsProxyMethod()); 204 TimingLogger logger("JIT compiler timing logger", true, VLOG_IS_ON(jit)); 205 StackHandleScope<2> hs(self); 206 self->AssertNoPendingException(); 207 Runtime* runtime = Runtime::Current(); 208 209 // Ensure the class is initialized. 210 Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass())); 211 if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) { 212 VLOG(jit) << "JIT failed to initialize " << PrettyMethod(method); 213 return false; 214 } 215 216 // Do the compilation. 217 bool success = false; 218 { 219 TimingLogger::ScopedTiming t2("Compiling", &logger); 220 JitCodeCache* const code_cache = runtime->GetJit()->GetCodeCache(); 221 success = compiler_driver_->GetCompiler()->JitCompile(self, code_cache, method, osr); 222 if (success && (perf_file_ != nullptr)) { 223 const void* ptr = method->GetEntryPointFromQuickCompiledCode(); 224 std::ostringstream stream; 225 stream << std::hex 226 << reinterpret_cast<uintptr_t>(ptr) 227 << " " 228 << code_cache->GetMemorySizeOfCodePointer(ptr) 229 << " " 230 << PrettyMethod(method) 231 << std::endl; 232 std::string str = stream.str(); 233 bool res = perf_file_->WriteFully(str.c_str(), str.size()); 234 CHECK(res); 235 } 236 } 237 238 // Trim maps to reduce memory usage. 239 // TODO: move this to an idle phase. 240 { 241 TimingLogger::ScopedTiming t2("TrimMaps", &logger); 242 runtime->GetJitArenaPool()->TrimMaps(); 243 } 244 245 runtime->GetJit()->AddTimingLogger(logger); 246 return success; 247 } 248 249 } // namespace jit 250 } // namespace art 251