blob: c95bac24fda9c9475c17296076f2f4ca1af3011a [file] [log] [blame]
Mathieu Chartiere5f13e52015-02-24 09:37:21 -08001/*
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
Mathieu Chartiere401d142015-04-22 13:56:20 -070019#include "art_method-inl.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080020#include "arch/instruction_set.h"
21#include "arch/instruction_set_features.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010022#include "base/time_utils.h"
Mathieu Chartiera4885cb2015-03-09 15:38:54 -070023#include "base/timing_logger.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080024#include "compiler_callbacks.h"
25#include "dex/pass_manager.h"
26#include "dex/quick_compiler_callbacks.h"
27#include "driver/compiler_driver.h"
28#include "driver/compiler_options.h"
29#include "jit/jit.h"
30#include "jit/jit_code_cache.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080031#include "oat_file-inl.h"
32#include "object_lock.h"
33#include "thread_list.h"
34#include "verifier/method_verifier-inl.h"
35
36namespace art {
37namespace jit {
38
39JitCompiler* JitCompiler::Create() {
40 return new JitCompiler();
41}
42
43extern "C" void* jit_load(CompilerCallbacks** callbacks) {
44 VLOG(jit) << "loading jit compiler";
45 auto* const jit_compiler = JitCompiler::Create();
46 CHECK(jit_compiler != nullptr);
47 *callbacks = jit_compiler->GetCompilerCallbacks();
48 VLOG(jit) << "Done loading jit compiler";
49 return jit_compiler;
50}
51
52extern "C" void jit_unload(void* handle) {
53 DCHECK(handle != nullptr);
54 delete reinterpret_cast<JitCompiler*>(handle);
55}
56
Mathieu Chartiere401d142015-04-22 13:56:20 -070057extern "C" bool jit_compile_method(void* handle, ArtMethod* method, Thread* self)
Mathieu Chartier90443472015-07-16 20:32:27 -070058 SHARED_REQUIRES(Locks::mutator_lock_) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080059 auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
60 DCHECK(jit_compiler != nullptr);
61 return jit_compiler->CompileMethod(self, method);
62}
63
64JitCompiler::JitCompiler() : total_time_(0) {
65 auto* pass_manager_options = new PassManagerOptions;
Mathieu Chartierf36cb5f2015-04-24 16:55:16 -070066 pass_manager_options->SetDisablePassList("GVN,DCE,GVNCleanup");
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080067 compiler_options_.reset(new CompilerOptions(
68 CompilerOptions::kDefaultCompilerFilter,
69 CompilerOptions::kDefaultHugeMethodThreshold,
70 CompilerOptions::kDefaultLargeMethodThreshold,
71 CompilerOptions::kDefaultSmallMethodThreshold,
72 CompilerOptions::kDefaultTinyMethodThreshold,
73 CompilerOptions::kDefaultNumDexMethodsThreshold,
Calin Juravleec748352015-07-29 13:52:12 +010074 CompilerOptions::kDefaultInlineDepthLimit,
75 CompilerOptions::kDefaultInlineMaxCodeUnits,
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +010076 /* include_patch_information */ false,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080077 CompilerOptions::kDefaultTopKProfileThreshold,
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +010078 Runtime::Current()->IsDebuggable(),
David Srbecky8363c772015-05-28 16:12:43 +010079 CompilerOptions::kDefaultGenerateDebugInfo,
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +010080 /* implicit_null_checks */ true,
81 /* implicit_so_checks */ true,
82 /* implicit_suspend_checks */ false,
83 /* pic */ true, // TODO: Support non-PIC in optimizing.
84 /* verbose_methods */ nullptr,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080085 pass_manager_options,
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +010086 /* init_failure_output */ nullptr,
87 /* abort_on_hard_verifier_failure */ false));
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080088 const InstructionSet instruction_set = kRuntimeISA;
89 instruction_set_features_.reset(InstructionSetFeatures::FromCppDefines());
90 cumulative_logger_.reset(new CumulativeLogger("jit times"));
91 verification_results_.reset(new VerificationResults(compiler_options_.get()));
92 method_inliner_map_.reset(new DexFileToMethodInlinerMap);
93 callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
Andreas Gampe81c6f8d2015-03-25 17:19:53 -070094 method_inliner_map_.get(),
Andreas Gampe4585f872015-03-27 23:45:15 -070095 CompilerCallbacks::CallbackMode::kCompileApp));
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080096 compiler_driver_.reset(new CompilerDriver(
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +010097 compiler_options_.get(),
98 verification_results_.get(),
99 method_inliner_map_.get(),
100 Compiler::kOptimizing,
101 instruction_set,
102 instruction_set_features_.get(),
103 /* image */ false,
104 /* image_classes */ nullptr,
105 /* compiled_classes */ nullptr,
106 /* compiled_methods */ nullptr,
107 /* thread_count */ 1,
108 /* dump_stats */ false,
109 /* dump_passes */ false,
110 /* dump_cfg_file_name */ "",
111 cumulative_logger_.get(),
112 /* swap_fd */ -1,
113 /* profile_file */ ""));
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800114 // Disable dedupe so we can remove compiled methods.
115 compiler_driver_->SetDedupeEnabled(false);
116 compiler_driver_->SetSupportBootImageFixup(false);
117}
118
119JitCompiler::~JitCompiler() {
120}
121
Mathieu Chartiere401d142015-04-22 13:56:20 -0700122bool JitCompiler::CompileMethod(Thread* self, ArtMethod* method) {
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700123 TimingLogger logger("JIT compiler timing logger", true, VLOG_IS_ON(jit));
Mathieu Chartier9b34b242015-03-09 11:30:17 -0700124 const uint64_t start_time = NanoTime();
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800125 StackHandleScope<2> hs(self);
126 self->AssertNoPendingException();
127 Runtime* runtime = Runtime::Current();
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800128 if (runtime->GetJit()->GetCodeCache()->ContainsMethod(method)) {
129 VLOG(jit) << "Already compiled " << PrettyMethod(method);
130 return true; // Already compiled
131 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700132 Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700133 {
134 TimingLogger::ScopedTiming t2("Initializing", &logger);
135 if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700136 VLOG(jit) << "JIT failed to initialize " << PrettyMethod(method);
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700137 return false;
138 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800139 }
140 const DexFile* dex_file = h_class->GetDexCache()->GetDexFile();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700141 MethodReference method_ref(dex_file, method->GetDexMethodIndex());
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800142 // Only verify if we don't already have verification results.
143 if (verification_results_->GetVerifiedMethod(method_ref) == nullptr) {
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700144 TimingLogger::ScopedTiming t2("Verifying", &logger);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800145 std::string error;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700146 if (verifier::MethodVerifier::VerifyMethod(method, true, &error) ==
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800147 verifier::MethodVerifier::kHardFailure) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700148 VLOG(jit) << "Not compile method " << PrettyMethod(method)
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800149 << " due to verification failure " << error;
150 return false;
151 }
152 }
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700153 CompiledMethod* compiled_method = nullptr;
154 {
155 TimingLogger::ScopedTiming t2("Compiling", &logger);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700156 compiled_method = compiler_driver_->CompileMethod(self, method);
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700157 }
158 {
159 TimingLogger::ScopedTiming t2("TrimMaps", &logger);
160 // Trim maps to reduce memory usage, TODO: measure how much this increases compile time.
161 runtime->GetArenaPool()->TrimMaps();
162 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800163 if (compiled_method == nullptr) {
164 return false;
165 }
166 total_time_ += NanoTime() - start_time;
Mathieu Chartierc0d5f892015-02-25 13:22:57 -0800167 // Don't add the method if we are supposed to be deoptimized.
168 bool result = false;
169 if (!runtime->GetInstrumentation()->AreAllMethodsDeoptimized()) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700170 const void* code = runtime->GetClassLinker()->GetOatMethodQuickCodeFor(method);
Mathieu Chartierc0d5f892015-02-25 13:22:57 -0800171 if (code != nullptr) {
172 // Already have some compiled code, just use this instead of linking.
173 // TODO: Fix recompilation.
Mathieu Chartiere401d142015-04-22 13:56:20 -0700174 method->SetEntryPointFromQuickCompiledCode(code);
Mathieu Chartierc0d5f892015-02-25 13:22:57 -0800175 result = true;
176 } else {
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700177 TimingLogger::ScopedTiming t2("MakeExecutable", &logger);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700178 result = MakeExecutable(compiled_method, method);
Mathieu Chartierc0d5f892015-02-25 13:22:57 -0800179 }
180 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800181 // Remove the compiled method to save memory.
182 compiler_driver_->RemoveCompiledMethod(method_ref);
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700183 runtime->GetJit()->AddTimingLogger(logger);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800184 return result;
185}
186
187CompilerCallbacks* JitCompiler::GetCompilerCallbacks() const {
188 return callbacks_.get();
189}
190
191uint8_t* JitCompiler::WriteMethodHeaderAndCode(const CompiledMethod* compiled_method,
192 uint8_t* reserve_begin, uint8_t* reserve_end,
193 const uint8_t* mapping_table,
194 const uint8_t* vmap_table,
195 const uint8_t* gc_map) {
196 reserve_begin += sizeof(OatQuickMethodHeader);
197 reserve_begin = reinterpret_cast<uint8_t*>(
198 compiled_method->AlignCode(reinterpret_cast<uintptr_t>(reserve_begin)));
199 const auto* quick_code = compiled_method->GetQuickCode();
200 CHECK_LE(reserve_begin, reserve_end);
201 CHECK_LE(quick_code->size(), static_cast<size_t>(reserve_end - reserve_begin));
202 auto* code_ptr = reserve_begin;
203 OatQuickMethodHeader* method_header = reinterpret_cast<OatQuickMethodHeader*>(code_ptr) - 1;
204 // Construct the header last.
205 const auto frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
206 const auto core_spill_mask = compiled_method->GetCoreSpillMask();
207 const auto fp_spill_mask = compiled_method->GetFpSpillMask();
208 const auto code_size = quick_code->size();
209 CHECK_NE(code_size, 0U);
210 std::copy(quick_code->data(), quick_code->data() + code_size, code_ptr);
211 // After we are done writing we need to update the method header.
212 // Write out the method header last.
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +0100213 method_header = new(method_header) OatQuickMethodHeader(
214 (mapping_table == nullptr) ? 0 : code_ptr - mapping_table,
215 (vmap_table == nullptr) ? 0 : code_ptr - vmap_table,
216 (gc_map == nullptr) ? 0 : code_ptr - gc_map,
217 frame_size_in_bytes,
218 core_spill_mask,
219 fp_spill_mask,
220 code_size);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800221 // Return the code ptr.
222 return code_ptr;
223}
224
Mathieu Chartiere401d142015-04-22 13:56:20 -0700225bool JitCompiler::AddToCodeCache(ArtMethod* method, const CompiledMethod* compiled_method,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800226 OatFile::OatMethod* out_method) {
227 Runtime* runtime = Runtime::Current();
228 JitCodeCache* const code_cache = runtime->GetJit()->GetCodeCache();
229 const auto* quick_code = compiled_method->GetQuickCode();
230 if (quick_code == nullptr) {
231 return false;
232 }
233 const auto code_size = quick_code->size();
234 Thread* const self = Thread::Current();
235 const uint8_t* base = code_cache->CodeCachePtr();
236 auto* const mapping_table = compiled_method->GetMappingTable();
237 auto* const vmap_table = compiled_method->GetVmapTable();
238 auto* const gc_map = compiled_method->GetGcMap();
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +0100239 uint8_t* mapping_table_ptr = nullptr;
240 uint8_t* vmap_table_ptr = nullptr;
241 uint8_t* gc_map_ptr = nullptr;
242
243 if (mapping_table != nullptr) {
244 // Write out pre-header stuff.
245 mapping_table_ptr = code_cache->AddDataArray(
246 self, mapping_table->data(), mapping_table->data() + mapping_table->size());
247 if (mapping_table_ptr == nullptr) {
248 return false; // Out of data cache.
249 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800250 }
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +0100251
252 if (vmap_table != nullptr) {
253 vmap_table_ptr = code_cache->AddDataArray(
254 self, vmap_table->data(), vmap_table->data() + vmap_table->size());
255 if (vmap_table_ptr == nullptr) {
256 return false; // Out of data cache.
257 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800258 }
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +0100259
260 if (gc_map != nullptr) {
261 gc_map_ptr = code_cache->AddDataArray(
262 self, gc_map->data(), gc_map->data() + gc_map->size());
263 if (gc_map_ptr == nullptr) {
264 return false; // Out of data cache.
265 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800266 }
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +0100267
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800268 // Don't touch this until you protect / unprotect the code.
269 const size_t reserve_size = sizeof(OatQuickMethodHeader) + quick_code->size() + 32;
270 uint8_t* const code_reserve = code_cache->ReserveCode(self, reserve_size);
271 if (code_reserve == nullptr) {
272 return false;
273 }
274 auto* code_ptr = WriteMethodHeaderAndCode(
275 compiled_method, code_reserve, code_reserve + reserve_size, mapping_table_ptr,
276 vmap_table_ptr, gc_map_ptr);
277
Mathieu Chartier5783a742015-06-01 19:12:36 -0700278 __builtin___clear_cache(reinterpret_cast<char*>(code_ptr),
279 reinterpret_cast<char*>(code_ptr + quick_code->size()));
280
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800281 const size_t thumb_offset = compiled_method->CodeDelta();
282 const uint32_t code_offset = code_ptr - base + thumb_offset;
283 *out_method = OatFile::OatMethod(base, code_offset);
284 DCHECK_EQ(out_method->GetGcMap(), gc_map_ptr);
285 DCHECK_EQ(out_method->GetMappingTable(), mapping_table_ptr);
286 DCHECK_EQ(out_method->GetVmapTable(), vmap_table_ptr);
287 DCHECK_EQ(out_method->GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
288 DCHECK_EQ(out_method->GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
289 DCHECK_EQ(out_method->GetFpSpillMask(), compiled_method->GetFpSpillMask());
290 VLOG(jit) << "JIT added " << PrettyMethod(method) << "@" << method << " ccache_size="
291 << PrettySize(code_cache->CodeCacheSize()) << ": " << reinterpret_cast<void*>(code_ptr)
292 << "," << reinterpret_cast<void*>(code_ptr + code_size);
293 return true;
294}
295
Mathieu Chartiere401d142015-04-22 13:56:20 -0700296bool JitCompiler::MakeExecutable(CompiledMethod* compiled_method, ArtMethod* method) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800297 CHECK(method != nullptr);
298 CHECK(compiled_method != nullptr);
299 OatFile::OatMethod oat_method(nullptr, 0);
300 if (!AddToCodeCache(method, compiled_method, &oat_method)) {
301 return false;
302 }
303 // TODO: Flush instruction cache.
304 oat_method.LinkMethod(method);
305 CHECK(Runtime::Current()->GetJit()->GetCodeCache()->ContainsMethod(method))
306 << PrettyMethod(method);
307 return true;
308}
309
310} // namespace jit
311} // namespace art