blob: b254c57fa6544d8678acfa19a751c778d329e74f [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
Andreas Gampe46ee31b2016-12-14 10:11:49 -080019#include "android-base/stringprintf.h"
20
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080021#include "arch/instruction_set.h"
22#include "arch/instruction_set_features.h"
David Srbecky4fda4eb2016-02-05 13:34:46 +000023#include "art_method-inl.h"
Andreas Gampe170331f2017-12-07 18:41:03 -080024#include "base/logging.h" // For VLOG
Vladimir Marko8581e2a2019-02-06 15:54:55 +000025#include "base/string_view_cpp20.h"
Andreas Gampec6548162017-12-08 12:15:22 -080026#include "base/systrace.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010027#include "base/time_utils.h"
Mathieu Chartiera4885cb2015-03-09 15:38:54 -070028#include "base/timing_logger.h"
Vladimir Marko038924b2019-02-19 15:09:35 +000029#include "compiler.h"
David Srbeckyc5bfa972016-02-05 15:49:10 +000030#include "debug/elf_debug_writer.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080031#include "driver/compiler_options.h"
Tamas Berghammer160e6df2016-01-05 14:29:02 +000032#include "jit/debugger_interface.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080033#include "jit/jit.h"
34#include "jit/jit_code_cache.h"
Vladimir Markoa0431112018-06-25 09:32:54 +010035#include "jit/jit_logger.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080036
37namespace art {
38namespace jit {
39
40JitCompiler* JitCompiler::Create() {
41 return new JitCompiler();
42}
43
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +000044void JitCompiler::ParseCompilerOptions() {
Nicolas Geoffray62a2f272017-11-10 16:46:43 +000045 // Special case max code units for inlining, whose default is "unset" (implictly
Roland Levillainef071322018-04-17 14:16:49 +010046 // meaning no limit). Do this before parsing the actual passed options.
Nicolas Geoffray62a2f272017-11-10 16:46:43 +000047 compiler_options_->SetInlineMaxCodeUnits(CompilerOptions::kDefaultInlineMaxCodeUnits);
Vladimir Marko6be1dbd2018-11-13 13:09:51 +000048 Runtime* runtime = Runtime::Current();
Andreas Gampe097f34c2017-08-23 08:57:51 -070049 {
50 std::string error_msg;
Vladimir Marko6be1dbd2018-11-13 13:09:51 +000051 if (!compiler_options_->ParseCompilerOptions(runtime->GetCompilerOptions(),
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +000052 /*ignore_unrecognized=*/ true,
53 &error_msg)) {
Andreas Gampe097f34c2017-08-23 08:57:51 -070054 LOG(FATAL) << error_msg;
55 UNREACHABLE();
56 }
Nicolas Geoffrayabbb0f72015-10-29 18:55:58 +000057 }
Vladimir Marko695348f2020-05-19 14:42:02 +010058 // Set to appropriate JIT compiler type.
59 compiler_options_->compiler_type_ = runtime->IsZygote()
60 ? CompilerOptions::CompilerType::kSharedCodeJitCompiler
61 : CompilerOptions::CompilerType::kJitCompiler;
Vladimir Marko2fad5272017-05-17 12:57:18 +010062 // JIT is never PIC, no matter what the runtime compiler options specify.
63 compiler_options_->SetNonPic();
64
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +000065 // If the options don't provide whether we generate debuggable code, set
66 // debuggability based on the runtime value.
67 if (!compiler_options_->GetDebuggable()) {
68 compiler_options_->SetDebuggable(runtime->IsJavaDebuggable());
69 }
Nicolas Geoffray57c47042017-06-29 11:31:39 +010070
Vladimir Markoa0431112018-06-25 09:32:54 +010071 const InstructionSet instruction_set = compiler_options_->GetInstructionSet();
72 if (kRuntimeISA == InstructionSet::kArm) {
73 DCHECK_EQ(instruction_set, InstructionSet::kThumb2);
74 } else {
75 DCHECK_EQ(instruction_set, kRuntimeISA);
76 }
77 std::unique_ptr<const InstructionSetFeatures> instruction_set_features;
Vladimir Marko8581e2a2019-02-06 15:54:55 +000078 for (const std::string& option : runtime->GetCompilerOptions()) {
Mathieu Chartier085fc872015-10-15 18:19:01 -070079 VLOG(compiler) << "JIT compiler option " << option;
80 std::string error_msg;
Vladimir Marko8581e2a2019-02-06 15:54:55 +000081 if (StartsWith(option, "--instruction-set-variant=")) {
82 const char* str = option.c_str() + strlen("--instruction-set-variant=");
Mathieu Chartier085fc872015-10-15 18:19:01 -070083 VLOG(compiler) << "JIT instruction set variant " << str;
Vladimir Markoa0431112018-06-25 09:32:54 +010084 instruction_set_features = InstructionSetFeatures::FromVariant(
Vladimir Marko8581e2a2019-02-06 15:54:55 +000085 instruction_set, str, &error_msg);
Vladimir Markoa0431112018-06-25 09:32:54 +010086 if (instruction_set_features == nullptr) {
Mathieu Chartier085fc872015-10-15 18:19:01 -070087 LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
88 }
Vladimir Marko8581e2a2019-02-06 15:54:55 +000089 } else if (StartsWith(option, "--instruction-set-features=")) {
90 const char* str = option.c_str() + strlen("--instruction-set-features=");
Mathieu Chartier085fc872015-10-15 18:19:01 -070091 VLOG(compiler) << "JIT instruction set features " << str;
Vladimir Markoa0431112018-06-25 09:32:54 +010092 if (instruction_set_features == nullptr) {
93 instruction_set_features = InstructionSetFeatures::FromVariant(
Andreas Gampe0415b4e2015-01-06 15:17:07 -080094 instruction_set, "default", &error_msg);
Vladimir Markoa0431112018-06-25 09:32:54 +010095 if (instruction_set_features == nullptr) {
Mathieu Chartier085fc872015-10-15 18:19:01 -070096 LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
97 }
98 }
Vladimir Markoa0431112018-06-25 09:32:54 +010099 instruction_set_features =
Vladimir Marko8581e2a2019-02-06 15:54:55 +0000100 instruction_set_features->AddFeaturesFromString(str, &error_msg);
Vladimir Markoa0431112018-06-25 09:32:54 +0100101 if (instruction_set_features == nullptr) {
Mathieu Chartier085fc872015-10-15 18:19:01 -0700102 LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
103 }
104 }
105 }
xueliang.zhong7f88c1a2018-11-06 11:42:41 +0000106
Vladimir Markoa0431112018-06-25 09:32:54 +0100107 if (instruction_set_features == nullptr) {
xueliang.zhong7f88c1a2018-11-06 11:42:41 +0000108 // '--instruction-set-features/--instruction-set-variant' were not used.
109 // Use build-time defined features.
Vladimir Markoa0431112018-06-25 09:32:54 +0100110 instruction_set_features = InstructionSetFeatures::FromCppDefines();
Mathieu Chartier085fc872015-10-15 18:19:01 -0700111 }
Vladimir Markoa0431112018-06-25 09:32:54 +0100112 compiler_options_->instruction_set_features_ = std::move(instruction_set_features);
113
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000114 if (compiler_options_->GetGenerateDebugInfo()) {
115 jit_logger_.reset(new JitLogger());
116 jit_logger_->OpenLog();
117 }
118}
119
David Srbecky46b53532019-08-06 13:39:05 +0100120extern "C" JitCompilerInterface* jit_load() {
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000121 VLOG(jit) << "Create jit compiler";
122 auto* const jit_compiler = JitCompiler::Create();
123 CHECK(jit_compiler != nullptr);
124 VLOG(jit) << "Done creating jit compiler";
125 return jit_compiler;
126}
127
David Srbecky9ac8e432019-08-13 13:16:13 +0100128void JitCompiler::TypesLoaded(mirror::Class** types, size_t count) {
David Srbecky46b53532019-08-06 13:39:05 +0100129 const CompilerOptions& compiler_options = GetCompilerOptions();
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000130 if (compiler_options.GetGenerateDebugInfo()) {
David Srbecky8fc2f952019-07-31 18:40:09 +0100131 InstructionSet isa = compiler_options.GetInstructionSet();
132 const InstructionSetFeatures* features = compiler_options.GetInstructionSetFeatures();
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000133 const ArrayRef<mirror::Class*> types_array(types, count);
David Srbecky8fc2f952019-07-31 18:40:09 +0100134 std::vector<uint8_t> elf_file =
135 debug::WriteDebugElfFileForClasses(isa, features, types_array);
136
137 // NB: Don't allow packing since it would remove non-backtrace data.
David Srbecky9ac8e432019-08-13 13:16:13 +0100138 MutexLock mu(Thread::Current(), *Locks::jit_lock_);
David Srbecky8fc2f952019-07-31 18:40:09 +0100139 AddNativeDebugInfoForJit(/*code_ptr=*/ nullptr, elf_file, /*allow_packing=*/ false);
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000140 }
141}
142
David Srbecky46b53532019-08-06 13:39:05 +0100143bool JitCompiler::GenerateDebugInfo() {
144 return GetCompilerOptions().GetGenerateDebugInfo();
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000145}
146
David Srbeckye09b87e2019-08-19 21:31:31 +0100147std::vector<uint8_t> JitCompiler::PackElfFileForJIT(ArrayRef<const JITCodeEntry*> elf_files,
David Srbecky8fc2f952019-07-31 18:40:09 +0100148 ArrayRef<const void*> removed_symbols,
149 bool compress,
150 /*out*/ size_t* num_symbols) {
151 return debug::PackElfFileForJIT(elf_files, removed_symbols, compress, num_symbols);
152}
153
Nicolas Geoffrayc9de61c2018-11-27 17:34:31 +0000154JitCompiler::JitCompiler() {
155 compiler_options_.reset(new CompilerOptions());
156 ParseCompilerOptions();
Vladimir Marko038924b2019-02-19 15:09:35 +0000157 compiler_.reset(
158 Compiler::Create(*compiler_options_, /*storage=*/ nullptr, Compiler::kOptimizing));
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800159}
160
161JitCompiler::~JitCompiler() {
xueliang.zhong383b57d2016-10-04 11:19:17 +0100162 if (compiler_options_->GetGenerateDebugInfo()) {
163 jit_logger_->CloseLog();
Nicolas Geoffraya25dce92016-01-12 16:41:10 +0000164 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800165}
166
Nicolas Geoffray7f7539b2019-06-06 16:20:54 +0100167bool JitCompiler::CompileMethod(
Nicolas Geoffray0d60a2b2020-06-17 14:31:56 +0100168 Thread* self, JitMemoryRegion* region, ArtMethod* method, CompilationKind compilation_kind) {
Nicolas Geoffray76e52e82020-03-09 14:16:42 +0000169 SCOPED_TRACE << "JIT compiling "
170 << method->PrettyMethod()
Nicolas Geoffray0d60a2b2020-06-17 14:31:56 +0100171 << " (kind=" << compilation_kind << ")";
Andreas Gampec6548162017-12-08 12:15:22 -0800172
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000173 DCHECK(!method->IsProxyMethod());
Nicolas Geoffray23ddfe82017-06-07 14:09:43 +0100174 DCHECK(method->GetDeclaringClass()->IsResolved());
175
Nicolas Geoffray3d699222017-09-20 15:15:20 +0100176 TimingLogger logger(
177 "JIT compiler timing logger", true, VLOG_IS_ON(jit), TimingLogger::TimingKind::kThreadCpu);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800178 self->AssertNoPendingException();
179 Runtime* runtime = Runtime::Current();
Nicolas Geoffray0c3c2662015-10-15 13:53:04 +0100180
Nicolas Geoffray0c3c2662015-10-15 13:53:04 +0100181 // Do the compilation.
Nicolas Geoffrayd28b9692015-11-04 14:36:55 +0000182 bool success = false;
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700183 {
Nicolas Geoffrayc473dc72020-07-03 15:04:21 +0100184 TimingLogger::ScopedTiming t2(compilation_kind == CompilationKind::kOsr
185 ? "Compiling OSR"
186 : compilation_kind == CompilationKind::kOptimized
187 ? "Compiling optimized"
188 : "Compiling baseline",
189 &logger);
Nicolas Geoffray73be1e82015-09-17 15:22:56 +0100190 JitCodeCache* const code_cache = runtime->GetJit()->GetCodeCache();
Nicolas Geoffrayf59bc112019-04-03 10:29:29 +0100191 uint64_t start_ns = NanoTime();
Nicolas Geoffray7f7539b2019-06-06 16:20:54 +0100192 success = compiler_->JitCompile(
Nicolas Geoffray0d60a2b2020-06-17 14:31:56 +0100193 self, code_cache, region, method, compilation_kind, jit_logger_.get());
Nicolas Geoffrayf59bc112019-04-03 10:29:29 +0100194 uint64_t duration_ns = NanoTime() - start_ns;
195 VLOG(jit) << "Compilation of "
196 << method->PrettyMethod()
197 << " took "
198 << PrettyDuration(duration_ns);
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700199 }
Nicolas Geoffray0c3c2662015-10-15 13:53:04 +0100200
201 // Trim maps to reduce memory usage.
Nicolas Geoffray25e04562016-03-01 13:17:58 +0000202 // TODO: move this to an idle phase.
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700203 {
204 TimingLogger::ScopedTiming t2("TrimMaps", &logger);
Nicolas Geoffray25e04562016-03-01 13:17:58 +0000205 runtime->GetJitArenaPool()->TrimMaps();
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700206 }
Nicolas Geoffray0c3c2662015-10-15 13:53:04 +0100207
Mathieu Chartiera4885cb2015-03-09 15:38:54 -0700208 runtime->GetJit()->AddTimingLogger(logger);
Nicolas Geoffrayd28b9692015-11-04 14:36:55 +0000209 return success;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800210}
211
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800212} // namespace jit
213} // namespace art