blob: 469f7d5d5749df478e22e0b1f2a65c2d2e6f433d [file] [log] [blame]
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -07001/*
2 * Copyright (C) 2012 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 "greenland.h"
18
Shih-wei Liao21d28f52012-06-12 05:55:00 -070019#include "gbc_context.h"
20#include "gbc_function.h"
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070021#include "target_codegen_machine.h"
22#include "target_registry.h"
23
24#include "class_linker.h"
25#include "compiler.h"
26#include "oat_compilation_unit.h"
27#include "stl_util.h"
28#include "utils.h"
29
30#include <vector>
31
32#include <llvm/InitializePasses.h>
33#include <llvm/Module.h>
34#include <llvm/PassRegistry.h>
35#include <llvm/Support/Threading.h>
36
37namespace art {
38namespace greenland {
39
40// Forward declarations
41#define LLVM_TARGET(TargetName) void Initialize##TargetName##CodeGenMachine();
42#include <llvm/Config/Targets.def>
43
44#define LLVM_TARGET(TargetName) \
45 void Initialize##TargetName##InvokeStubCompiler();
46#include <llvm/Config/Targets.def>
47
48} // namespace greeland
49} // namespace art
50
51namespace {
52
53pthread_once_t greenland_initialized = PTHREAD_ONCE_INIT;
54
55void InitializeAllCodeGenMachines() {
56#define LLVM_TARGET(TargetName) \
57 art::greenland::Initialize##TargetName##CodeGenMachine();
58#include <llvm/Config/Targets.def>
59}
60
61void InitializeAllInvokeStubCompilers() {
62#define LLVM_TARGET(TargetName) \
63 art::greenland::Initialize##TargetName##InvokeStubCompiler();
64#include <llvm/Config/Targets.def>
65}
66
67void InitializeGreenland() {
Shih-wei Liao21d28f52012-06-12 05:55:00 -070068 // Initialize LLVM internal data structure for multithreading
69 llvm::llvm_start_multithreaded();
70
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070071 // Initialize passes
72 llvm::PassRegistry &registry = *llvm::PassRegistry::getPassRegistry();
73
74 llvm::initializeCore(registry);
75 llvm::initializeScalarOpts(registry);
76
77 // Run vectorization passes when our backend supports vector type
78 //llvm::initializeVectorization(registry);
79
80 // DexLang operates on an llvm::Function and never runs IPO and IPA
81 //llvm::initializeIPO(registry);
82 //llvm::initializeIPA(registry);
83
84 llvm::initializeAnalysis(registry);
85 llvm::initializeTransformUtils(registry);
86 llvm::initializeInstCombine(registry);
87
88 InitializeAllCodeGenMachines();
89 InitializeAllInvokeStubCompilers();
90
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070091 return;
92}
93
94} // anonymous namespace
95
96namespace art {
97namespace greenland {
98
99Greenland::Greenland(art::Compiler& compiler)
100 : compiler_(compiler), codegen_machine_(NULL),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700101 lock_("greenland_compiler_lock"), cur_gbc_ctx_(NULL) {
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700102 // Initialize Greenland
103 pthread_once(&greenland_initialized, InitializeGreenland);
104
105 codegen_machine_ =
106 TargetCodeGenMachine::Create(compiler_.GetInstructionSet());
107 DCHECK(codegen_machine_ != NULL);
108 return;
109}
110
111Greenland::~Greenland() {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700112 cur_gbc_ctx_->DecRef();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700113 delete codegen_machine_;
114}
115
116CompiledMethod* Greenland::Compile(OatCompilationUnit& cunit) {
117 MutexLock GUARD(lock_);
118
119 // Dex to LLVM IR
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700120 GBCContext& gbc_ctx = GetGBCContext();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700121
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700122 UniquePtr<DexLang> dex_lang(new DexLang(gbc_ctx.GetDexLangContext(),
123 compiler_, cunit));
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700124
125 llvm::Function* func = dex_lang->Build();
126
127 if (func == NULL) {
128 LOG(FATAL) << "Failed to run dexlang on "
129 << PrettyMethod(cunit.GetDexMethodIndex(), *cunit.GetDexFile());
130 return NULL;
131 }
132
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700133 func->dump();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700134
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700135 // NOTE: From statistic, the bitcode size is 4.5 times bigger than the
136 // Dex file. Besides, we have to convert the code unit into bytes.
137 // Thus, we got our magic number 9.
138 gbc_ctx.AddMemUsageApproximation(
139 cunit.GetCodeItem()->insns_size_in_code_units_ * 900);
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700140
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700141 GBCFunction gbc_func(gbc_ctx, *func, cunit);
142
143 UniquePtr<CompiledMethod> result(codegen_machine_->Run(compiler_, gbc_func));
144
145 // gbc_ctx was no longer needed
146 gbc_ctx.DecRef();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700147
148 return result.release();
149}
150
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700151GBCContext& Greenland::GetGBCContext() {
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700152 //MutexLock GUARD(lock_);
153
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700154 ResetGBCContextIfThresholdReached();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700155
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700156 if (cur_gbc_ctx_ == NULL) {
157 cur_gbc_ctx_ = new GBCContext();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700158 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700159 CHECK(cur_gbc_ctx_ != NULL);
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700160
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700161 return cur_gbc_ctx_->IncRef();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700162}
163
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700164void Greenland::ResetGBCContextIfThresholdReached() {
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700165 lock_.AssertHeld();
166
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700167 if (cur_gbc_ctx_ == NULL) {
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700168 return;
169 }
170
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700171 if (cur_gbc_ctx_->IsMemUsageThresholdReached()) {
172 cur_gbc_ctx_->DecRef();
173 cur_gbc_ctx_ = NULL;
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700174 }
175 return;
176}
177
178} // namespace greenland
179} // namespace art
180
181inline static art::greenland::Greenland* ContextOf(art::Compiler& compiler) {
182 void *compiler_context = compiler.GetCompilerContext();
183 CHECK(compiler_context != NULL);
184 return reinterpret_cast<art::greenland::Greenland*>(compiler_context);
185}
186
187extern "C" void ArtInitCompilerContext(art::Compiler& compiler) {
188 CHECK(compiler.GetCompilerContext() == NULL);
189 compiler.SetCompilerContext(new art::greenland::Greenland(compiler));
190 return;
191}
192
193extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler,
194 const art::DexFile::CodeItem* code_item,
195 uint32_t access_flags, uint32_t method_idx,
196 const art::ClassLoader* class_loader,
197 const art::DexFile& dex_file)
198{
199 art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
200 art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
201
202 art::OatCompilationUnit cunit(
203 class_loader, class_linker, dex_file, *dex_cache, code_item,
204 method_idx, access_flags);
205
206 return ContextOf(compiler)->Compile(cunit);
207}
208
209extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler,
210 bool is_static,
211 const char* shorty,
212 uint32_t shorty_len) {
213 art::greenland::TargetRegistry::CreateInvokeStubFn compiler_fn =
214 art::greenland::TargetRegistry::GetInvokeStubCompiler(compiler.GetInstructionSet());
215 CHECK(compiler_fn != NULL);
216 return (*compiler_fn)(compiler, is_static, shorty, shorty_len);
217}