blob: 2f9b3ed9b99f3948de3541029ee3428fe0a71480 [file] [log] [blame]
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "compiler.h"
4
Brian Carlstrom27ec9612011-09-19 20:20:38 -07005#include <sys/mman.h>
6
Brian Carlstrom2cc022b2011-08-25 10:05:39 -07007#include "assembler.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -07008#include "class_linker.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -07009#include "class_loader.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070010#include "dex_cache.h"
Brian Carlstrome7d856b2012-01-11 18:10:55 -080011#include "dex_verifier.h"
Brian Carlstrom2cc022b2011-08-25 10:05:39 -070012#include "jni_compiler.h"
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070013#include "jni_internal.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070014#include "oat_file.h"
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080015#include "object_utils.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070016#include "runtime.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070017#include "stl_util.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070018
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070019namespace art {
20
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080021CompiledMethod* oatCompileMethod(const Compiler& compiler, const DexFile::CodeItem* code_item,
22 uint32_t access_flags, uint32_t method_idx,
23 const ClassLoader* class_loader,
24 const DexFile& dex_file, InstructionSet);
25
Shih-wei Liaoc486c112011-09-13 16:43:52 -070026namespace arm {
Ian Rogersbdb03912011-09-14 00:55:44 -070027 ByteArray* CreateAbstractMethodErrorStub();
Ian Rogers0571d352011-11-03 19:51:38 -070028 CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty);
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070029 ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type);
Elliott Hughes8add92d2012-01-18 18:18:43 -080030 ByteArray* CreateJniDlsymLookupStub();
Shih-wei Liaoc486c112011-09-13 16:43:52 -070031}
Shih-wei Liaoc486c112011-09-13 16:43:52 -070032namespace x86 {
Ian Rogersbdb03912011-09-14 00:55:44 -070033 ByteArray* CreateAbstractMethodErrorStub();
Ian Rogers0571d352011-11-03 19:51:38 -070034 CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty);
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070035 ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type);
Elliott Hughes8add92d2012-01-18 18:18:43 -080036 ByteArray* CreateJniDlsymLookupStub();
Brian Carlstrome24fa612011-09-29 00:53:55 -070037}
38
Brian Carlstromae826982011-11-09 01:33:42 -080039Compiler::Compiler(InstructionSet instruction_set,
40 bool image,
41 const std::set<std::string>* image_classes)
Brian Carlstromaded5f72011-10-07 17:15:04 -070042 : instruction_set_(instruction_set),
43 jni_compiler_(instruction_set),
44 image_(image),
Elliott Hughesbb551fa2012-01-25 16:35:29 -080045 dex_file_count_(0),
46 class_count_(0),
47 abstract_method_count_(0),
48 native_method_count_(0),
49 regular_method_count_(0),
50 instruction_count_(0),
51 start_ns_(NanoTime()),
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -080052 image_classes_(image_classes) {
Brian Carlstrom25c33252011-09-18 15:58:35 -070053 CHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -080054 if (!image_) {
55 CHECK(image_classes_ == NULL);
56 }
Shih-wei Liaoc486c112011-09-13 16:43:52 -070057}
58
Brian Carlstrom3320cf42011-10-04 14:58:28 -070059Compiler::~Compiler() {
Brian Carlstrom0755ec52012-01-11 15:19:46 -080060 STLDeleteValues(&compiled_classes_);
Brian Carlstrom3320cf42011-10-04 14:58:28 -070061 STLDeleteValues(&compiled_methods_);
62 STLDeleteValues(&compiled_invoke_stubs_);
Elliott Hughesbb551fa2012-01-25 16:35:29 -080063 if (dex_file_count_ > 0) {
64 uint64_t duration_ns = NanoTime() - start_ns_;
65 uint64_t duration_ms = NsToMs(duration_ns);
66 LOG(INFO) << "Compiled files:" << dex_file_count_
67 << " classes:" << class_count_
68 << " methods:(abstract:" << abstract_method_count_
69 << " native:" << native_method_count_
70 << " regular:" << regular_method_count_ << ")"
71 << " instructions:" << instruction_count_
72 << " (took " << duration_ms << "ms, "
73 << (duration_ns/instruction_count_) << " ns/instruction)";
74 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -070075}
76
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070077ByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set,
78 Runtime::TrampolineType type) {
Ian Rogersad25ac52011-10-04 19:13:33 -070079 if (instruction_set == kX86) {
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070080 return x86::X86CreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -070081 } else {
82 CHECK(instruction_set == kArm || instruction_set == kThumb2);
83 // Generates resolution stub using ARM instruction set
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070084 return arm::ArmCreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -070085 }
86}
87
Elliott Hughes8add92d2012-01-18 18:18:43 -080088ByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) {
Ian Rogers169c9a72011-11-13 20:13:17 -080089 switch (instruction_set) {
90 case kArm:
91 case kThumb2:
Elliott Hughes8add92d2012-01-18 18:18:43 -080092 return arm::CreateJniDlsymLookupStub();
Ian Rogers169c9a72011-11-13 20:13:17 -080093 case kX86:
Elliott Hughes8add92d2012-01-18 18:18:43 -080094 return x86::CreateJniDlsymLookupStub();
Ian Rogers169c9a72011-11-13 20:13:17 -080095 default:
Elliott Hughesba8eee12012-01-24 20:25:24 -080096 LOG(FATAL) << "Unknown InstructionSet: " << static_cast<int>(instruction_set);
Ian Rogers169c9a72011-11-13 20:13:17 -080097 return NULL;
98 }
99}
100
Ian Rogersad25ac52011-10-04 19:13:33 -0700101ByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) {
102 if (instruction_set == kX86) {
103 return x86::CreateAbstractMethodErrorStub();
104 } else {
105 CHECK(instruction_set == kArm || instruction_set == kThumb2);
106 // Generates resolution stub using ARM instruction set
107 return arm::CreateAbstractMethodErrorStub();
108 }
109}
110
Jesse Wilson254db0f2011-11-16 16:44:11 -0500111void Compiler::CompileAll(const ClassLoader* class_loader,
Brian Carlstromae826982011-11-09 01:33:42 -0800112 const std::vector<const DexFile*>& dex_files) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700113 DCHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800114
115 PreCompile(class_loader, dex_files);
116 Compile(class_loader, dex_files);
117 PostCompile(class_loader, dex_files);
Brian Carlstrom8a487412011-08-29 20:08:52 -0700118}
119
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700120void Compiler::CompileOne(const Method* method) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700121 DCHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800122
Brian Carlstrom8a487412011-08-29 20:08:52 -0700123 const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
Brian Carlstromae826982011-11-09 01:33:42 -0800124
Ian Rogers0571d352011-11-03 19:51:38 -0700125 // Find the dex_file
126 const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
127 const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
Brian Carlstromae826982011-11-09 01:33:42 -0800128 std::vector<const DexFile*> dex_files;
129 dex_files.push_back(&dex_file);
130
131 PreCompile(class_loader, dex_files);
132
Ian Rogers0571d352011-11-03 19:51:38 -0700133 uint32_t method_idx = method->GetDexMethodIndex();
Ian Rogersa3760aa2011-11-14 14:32:37 -0800134 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
135 CompileMethod(code_item, method->GetAccessFlags(), method_idx, class_loader, dex_file);
Brian Carlstromae826982011-11-09 01:33:42 -0800136
137 PostCompile(class_loader, dex_files);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700138}
139
Brian Carlstromae826982011-11-09 01:33:42 -0800140void Compiler::Resolve(const ClassLoader* class_loader,
141 const std::vector<const DexFile*>& dex_files) {
142 for (size_t i = 0; i != dex_files.size(); ++i) {
143 const DexFile* dex_file = dex_files[i];
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700144 CHECK(dex_file != NULL);
145 ResolveDexFile(class_loader, *dex_file);
146 }
147}
148
Brian Carlstromae826982011-11-09 01:33:42 -0800149void Compiler::PreCompile(const ClassLoader* class_loader,
150 const std::vector<const DexFile*>& dex_files) {
151 Resolve(class_loader, dex_files);
152 Verify(class_loader, dex_files);
153 InitializeClassesWithoutClinit(class_loader, dex_files);
154}
155
156void Compiler::PostCompile(const ClassLoader* class_loader,
157 const std::vector<const DexFile*>& dex_files) {
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800158 SetGcMaps(class_loader, dex_files);
Brian Carlstromae826982011-11-09 01:33:42 -0800159 SetCodeAndDirectMethods(dex_files);
160}
161
162bool Compiler::IsImageClass(const std::string& descriptor) const {
163 if (image_classes_ == NULL) {
164 return true;
165 }
166 return image_classes_->find(descriptor) != image_classes_->end();
167}
168
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800169bool Compiler::CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache,
170 uint32_t type_idx) const {
171 if (!IsImage()) {
172 return false;
173 }
174 Class* resolved_class = dex_cache->GetResolvedTypes()->Get(type_idx);
175 if (resolved_class == NULL) {
176 return false;
177 }
178 return IsImageClass(ClassHelper(resolved_class).GetDescriptor());
179}
180
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800181// Return true if the class should be skipped during compilation. We
182// never skip classes in the boot class loader. However, if we have a
183// non-boot class loader and we can resolve the class in the boot
184// class loader, we do skip the class. This happens if an app bundles
185// classes found in the boot classpath. Since at runtime we will
186// select the class from the boot classpath, do not attempt to resolve
187// or compile it now.
188static bool SkipClass(const ClassLoader* class_loader,
189 const DexFile& dex_file,
190 const DexFile::ClassDef& class_def) {
191 if (class_loader == NULL) {
192 return false;
193 }
194 const char* descriptor = dex_file.GetClassDescriptor(class_def);
195 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
196 Class* klass = class_linker->FindClass(descriptor, NULL);
197 if (klass == NULL) {
198 Thread* self = Thread::Current();
199 CHECK(self->IsExceptionPending());
200 self->ClearException();
201 return false;
202 }
203 return true;
204}
205
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700206void Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800207 Thread* self = Thread::Current();
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700208 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromaded5f72011-10-07 17:15:04 -0700209 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700210
Brian Carlstromae826982011-11-09 01:33:42 -0800211 // Strings are easy in that they always are simply resolved to literals in the same file
212 if (image_ && image_classes_ == NULL) {
213 // TODO: Add support for loading strings referenced by image_classes_
214 // See also Compiler::CanAssumeTypeIsPresentInDexCache.
Brian Carlstromaded5f72011-10-07 17:15:04 -0700215 for (size_t string_idx = 0; string_idx < dex_cache->NumStrings(); string_idx++) {
216 class_linker->ResolveString(dex_file, string_idx, dex_cache);
217 }
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700218 }
219
Brian Carlstrom845490b2011-09-19 15:56:53 -0700220 // Class derived values are more complicated, they require the linker and loader.
Brian Carlstromffca45d2011-09-16 12:10:49 -0700221 for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
222 Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700223 if (klass == NULL) {
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800224 CHECK(self->IsExceptionPending());
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700225 Thread::Current()->ClearException();
226 }
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700227 }
Brian Carlstrom845490b2011-09-19 15:56:53 -0700228
229 // Method and Field are the worst. We can't resolve without either
230 // context from the code use (to disambiguate virtual vs direct
231 // method and instance vs static field) or from class
232 // definitions. While the compiler will resolve what it can as it
233 // needs it, here we try to resolve fields and methods used in class
234 // definitions, since many of them many never be referenced by
235 // generated code.
236 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
237 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800238 if (SkipClass(class_loader, dex_file, class_def)) {
239 continue;
240 }
Brian Carlstrom845490b2011-09-19 15:56:53 -0700241
242 // Note the class_data pointer advances through the headers,
243 // static fields, instance fields, direct methods, and virtual
244 // methods.
245 const byte* class_data = dex_file.GetClassData(class_def);
Ian Rogers0571d352011-11-03 19:51:38 -0700246 if (class_data == NULL) {
247 // empty class such as a marker interface
248 continue;
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700249 }
Ian Rogers0571d352011-11-03 19:51:38 -0700250 ClassDataItemIterator it(dex_file, class_data);
251 while (it.HasNextStaticField()) {
252 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
253 class_loader, true);
254 if (field == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700255 CHECK(self->IsExceptionPending());
256 self->ClearException();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700257 }
Ian Rogers0571d352011-11-03 19:51:38 -0700258 it.Next();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700259 }
Ian Rogers0571d352011-11-03 19:51:38 -0700260 while (it.HasNextInstanceField()) {
261 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
262 class_loader, false);
263 if (field == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700264 CHECK(self->IsExceptionPending());
265 self->ClearException();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700266 }
Ian Rogers0571d352011-11-03 19:51:38 -0700267 it.Next();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700268 }
Ian Rogers0571d352011-11-03 19:51:38 -0700269 while (it.HasNextDirectMethod()) {
270 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
271 class_loader, true);
272 if (method == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700273 CHECK(self->IsExceptionPending());
274 self->ClearException();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700275 }
Ian Rogers0571d352011-11-03 19:51:38 -0700276 it.Next();
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700277 }
Ian Rogers0571d352011-11-03 19:51:38 -0700278 while (it.HasNextVirtualMethod()) {
279 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
280 class_loader, false);
281 if (method == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700282 CHECK(self->IsExceptionPending());
283 self->ClearException();
284 }
285 it.Next();
286 }
287 DCHECK(!it.HasNext());
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700288 }
289}
290
Brian Carlstromae826982011-11-09 01:33:42 -0800291void Compiler::Verify(const ClassLoader* class_loader,
292 const std::vector<const DexFile*>& dex_files) {
293 for (size_t i = 0; i != dex_files.size(); ++i) {
294 const DexFile* dex_file = dex_files[i];
jeffhao98eacac2011-09-14 16:11:53 -0700295 CHECK(dex_file != NULL);
296 VerifyDexFile(class_loader, *dex_file);
297 }
298}
299
300void Compiler::VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
jeffhaob4df5142011-09-19 20:25:32 -0700301 dex_file.ChangePermissions(PROT_READ | PROT_WRITE);
jeffhao98eacac2011-09-14 16:11:53 -0700302 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700303 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
304 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
jeffhao98eacac2011-09-14 16:11:53 -0700305 const char* descriptor = dex_file.GetClassDescriptor(class_def);
306 Class* klass = class_linker->FindClass(descriptor, class_loader);
Brian Carlstrom65ca0772011-09-24 16:03:08 -0700307 if (klass == NULL) {
308 Thread* self = Thread::Current();
309 CHECK(self->IsExceptionPending());
310 self->ClearException();
311 continue;
312 }
313 CHECK(klass->IsResolved()) << PrettyClass(klass);
jeffhao98eacac2011-09-14 16:11:53 -0700314 class_linker->VerifyClass(klass);
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700315
316 if (klass->IsErroneous()) {
317 // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
318 CHECK(Thread::Current()->IsExceptionPending());
319 Thread::Current()->ClearException();
320 // We want to try verification again at run-time, so move back into the resolved state.
321 klass->SetStatus(Class::kStatusResolved);
322 }
323
jeffhao5cfd6fb2011-09-27 13:54:29 -0700324 CHECK(klass->IsVerified() || klass->IsResolved()) << PrettyClass(klass);
325 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700326 }
jeffhaob4df5142011-09-19 20:25:32 -0700327 dex_file.ChangePermissions(PROT_READ);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700328}
329
Brian Carlstromae826982011-11-09 01:33:42 -0800330void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader,
331 const std::vector<const DexFile*>& dex_files) {
332 for (size_t i = 0; i != dex_files.size(); ++i) {
333 const DexFile* dex_file = dex_files[i];
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700334 CHECK(dex_file != NULL);
335 InitializeClassesWithoutClinit(class_loader, *dex_file);
336 }
337}
338
339void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, const DexFile& dex_file) {
340 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700341 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
342 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700343 const char* descriptor = dex_file.GetClassDescriptor(class_def);
344 Class* klass = class_linker->FindClass(descriptor, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700345 if (klass != NULL) {
346 class_linker->EnsureInitialized(klass, false);
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800347 // record the final class status if necessary
348 Class::Status status = klass->GetStatus();
349 ClassReference ref(&dex_file, class_def_index);
350 CompiledClass* compiled_class = GetCompiledClass(ref);
351 if (compiled_class == NULL) {
352 compiled_class = new CompiledClass(status);
353 compiled_classes_[ref] = compiled_class;
354 } else {
355 DCHECK_EQ(status, compiled_class->GetStatus());
356 }
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700357 }
358 // clear any class not found or verification exceptions
359 Thread::Current()->ClearException();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700360 }
361
362 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
363 for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
364 Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700365 if (klass == NULL) {
366 Thread::Current()->ClearException();
367 } else if (klass->IsInitialized()) {
Brian Carlstromffca45d2011-09-16 12:10:49 -0700368 dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
369 }
jeffhao98eacac2011-09-14 16:11:53 -0700370 }
371}
372
Brian Carlstromae826982011-11-09 01:33:42 -0800373void Compiler::Compile(const ClassLoader* class_loader,
374 const std::vector<const DexFile*>& dex_files) {
375 for (size_t i = 0; i != dex_files.size(); ++i) {
376 const DexFile* dex_file = dex_files[i];
Brian Carlstrom83db7722011-08-26 17:32:56 -0700377 CHECK(dex_file != NULL);
378 CompileDexFile(class_loader, *dex_file);
379 }
380}
381
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700382void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800383 ++dex_file_count_;
Brian Carlstromffca45d2011-09-16 12:10:49 -0700384 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
385 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Ian Rogers0571d352011-11-03 19:51:38 -0700386 CompileClass(class_def, class_loader, dex_file);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700387 }
388}
389
Ian Rogers0571d352011-11-03 19:51:38 -0700390void Compiler::CompileClass(const DexFile::ClassDef& class_def, const ClassLoader* class_loader,
391 const DexFile& dex_file) {
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800392 if (SkipClass(class_loader, dex_file, class_def)) {
393 return;
394 }
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800395 ++class_count_;
Ian Rogers0571d352011-11-03 19:51:38 -0700396 const byte* class_data = dex_file.GetClassData(class_def);
397 if (class_data == NULL) {
398 // empty class, probably a marker interface
399 return;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700400 }
Ian Rogers0571d352011-11-03 19:51:38 -0700401 ClassDataItemIterator it(dex_file, class_data);
402 // Skip fields
403 while (it.HasNextStaticField()) {
404 it.Next();
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700405 }
Ian Rogers0571d352011-11-03 19:51:38 -0700406 while (it.HasNextInstanceField()) {
407 it.Next();
408 }
409 // Compile direct methods
410 while (it.HasNextDirectMethod()) {
Ian Rogersa3760aa2011-11-14 14:32:37 -0800411 CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(), it.GetMemberIndex(),
412 class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700413 it.Next();
414 }
415 // Compile virtual methods
416 while (it.HasNextVirtualMethod()) {
Ian Rogersa3760aa2011-11-14 14:32:37 -0800417 CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(), it.GetMemberIndex(),
418 class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700419 it.Next();
420 }
421 DCHECK(!it.HasNext());
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700422}
423
Ian Rogersa3760aa2011-11-14 14:32:37 -0800424void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
425 uint32_t method_idx, const ClassLoader* class_loader,
426 const DexFile& dex_file) {
Elliott Hughesf09afe82011-10-16 14:24:21 -0700427 CompiledMethod* compiled_method = NULL;
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800428 uint64_t start_ns = NanoTime();
Ian Rogers169c9a72011-11-13 20:13:17 -0800429 if ((access_flags & kAccNative) != 0) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800430 ++native_method_count_;
Ian Rogers169c9a72011-11-13 20:13:17 -0800431 compiled_method = jni_compiler_.Compile(access_flags, method_idx, class_loader, dex_file);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700432 CHECK(compiled_method != NULL);
Ian Rogers169c9a72011-11-13 20:13:17 -0800433 } else if ((access_flags & kAccAbstract) != 0) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800434 ++abstract_method_count_;
Brian Carlstrom2cc022b2011-08-25 10:05:39 -0700435 } else {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800436 ++regular_method_count_;
437 instruction_count_ += code_item->insns_size_in_code_units_;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800438 compiled_method = oatCompileMethod(*this, code_item, access_flags, method_idx, class_loader,
439 dex_file, kThumb2);
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800440 CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
441 }
442 uint64_t duration_ms = NsToMs(NanoTime() - start_ns);
443 if (duration_ms > 10) {
444 LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
445 << " took " << duration_ms << "ms";
Elliott Hughesf09afe82011-10-16 14:24:21 -0700446 }
447
448 if (compiled_method != NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700449 MethodReference ref(&dex_file, method_idx);
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800450 CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700451 compiled_methods_[ref] = compiled_method;
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800452 DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file);
Brian Carlstrom2cc022b2011-08-25 10:05:39 -0700453 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700454
Ian Rogers0571d352011-11-03 19:51:38 -0700455 const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
Ian Rogers169c9a72011-11-13 20:13:17 -0800456 bool is_static = (access_flags & kAccStatic) != 0;
Ian Rogers0571d352011-11-03 19:51:38 -0700457 const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
458 if (compiled_invoke_stub == NULL) {
459 if (instruction_set_ == kX86) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800460 compiled_invoke_stub = ::art::x86::X86CreateInvokeStub(is_static, shorty);
Ian Rogers0571d352011-11-03 19:51:38 -0700461 } else {
462 CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
463 // Generates invocation stub using ARM instruction set
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800464 compiled_invoke_stub = ::art::arm::ArmCreateInvokeStub(is_static, shorty);
Ian Rogers0571d352011-11-03 19:51:38 -0700465 }
466 CHECK(compiled_invoke_stub != NULL);
467 InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700468 }
Ian Rogers0571d352011-11-03 19:51:38 -0700469 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700470}
471
Ian Rogers0571d352011-11-03 19:51:38 -0700472static std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
473 std::string key(shorty);
474 if (is_static) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800475 key += "$"; // Must not be a shorty type character.
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700476 }
Ian Rogers0571d352011-11-03 19:51:38 -0700477 return key;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700478}
479
Ian Rogers0571d352011-11-03 19:51:38 -0700480const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
Elliott Hughes95572412011-12-13 18:14:20 -0800481 const std::string key(MakeInvokeStubKey(is_static, shorty));
Ian Rogers0571d352011-11-03 19:51:38 -0700482 InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700483 if (it == compiled_invoke_stubs_.end()) {
484 return NULL;
Ian Rogers0571d352011-11-03 19:51:38 -0700485 } else {
486 DCHECK(it->second != NULL);
487 return it->second;
488 }
489}
490
491void Compiler::InsertInvokeStub(bool is_static, const char* shorty,
492 const CompiledInvokeStub* compiled_invoke_stub) {
Elliott Hughes95572412011-12-13 18:14:20 -0800493 std::string key(MakeInvokeStubKey(is_static, shorty));
Ian Rogers0571d352011-11-03 19:51:38 -0700494 compiled_invoke_stubs_[key] = compiled_invoke_stub;
495}
496
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800497CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const {
498 ClassTable::const_iterator it = compiled_classes_.find(ref);
499 if (it == compiled_classes_.end()) {
500 return NULL;
501 }
502 CHECK(it->second != NULL);
503 return it->second;
504}
505
Ian Rogers0571d352011-11-03 19:51:38 -0700506CompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
507 MethodTable::const_iterator it = compiled_methods_.find(ref);
508 if (it == compiled_methods_.end()) {
509 return NULL;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700510 }
511 CHECK(it->second != NULL);
512 return it->second;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700513}
514
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800515void Compiler::SetGcMaps(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files) {
516 for (size_t i = 0; i != dex_files.size(); ++i) {
517 const DexFile* dex_file = dex_files[i];
518 CHECK(dex_file != NULL);
519 SetGcMapsDexFile(class_loader, *dex_file);
520 }
521}
522
523void Compiler::SetGcMapsDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
524 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
525 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
526 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
527 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
528 const char* descriptor = dex_file.GetClassDescriptor(class_def);
529 Class* klass = class_linker->FindClass(descriptor, class_loader);
530 if (klass == NULL || !klass->IsVerified()) {
531 Thread::Current()->ClearException();
532 continue;
533 }
534 const byte* class_data = dex_file.GetClassData(class_def);
535 if (class_data == NULL) {
536 // empty class such as a marker interface
537 continue;
538 }
539 ClassDataItemIterator it(dex_file, class_data);
540 while (it.HasNextStaticField()) {
541 it.Next();
542 }
543 while (it.HasNextInstanceField()) {
544 it.Next();
545 }
546 while (it.HasNextDirectMethod()) {
547 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
548 class_loader, true);
549 SetGcMapsMethod(dex_file, method);
550 it.Next();
551 }
552 while (it.HasNextVirtualMethod()) {
553 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
554 class_loader, false);
555 SetGcMapsMethod(dex_file, method);
556 it.Next();
557 }
558 }
559}
560
561void Compiler::SetGcMapsMethod(const DexFile& dex_file, Method* method) {
562 if (method == NULL) {
563 Thread::Current()->ClearException();
564 return;
565 }
566 uint16_t method_idx = method->GetDexMethodIndex();
567 MethodReference ref(&dex_file, method_idx);
568 CompiledMethod* compiled_method = GetCompiledMethod(ref);
569 if (compiled_method == NULL) {
570 return;
571 }
572 const std::vector<uint8_t>* gc_map = verifier::DexVerifier::GetGcMap(ref);
573 if (gc_map == NULL) {
574 return;
575 }
576 compiled_method->SetGcMap(*gc_map);
577}
578
Brian Carlstromae826982011-11-09 01:33:42 -0800579void Compiler::SetCodeAndDirectMethods(const std::vector<const DexFile*>& dex_files) {
580 for (size_t i = 0; i != dex_files.size(); ++i) {
581 const DexFile* dex_file = dex_files[i];
Brian Carlstrom83db7722011-08-26 17:32:56 -0700582 CHECK(dex_file != NULL);
Brian Carlstrom8a487412011-08-29 20:08:52 -0700583 SetCodeAndDirectMethodsDexFile(*dex_file);
Brian Carlstrom83db7722011-08-26 17:32:56 -0700584 }
585}
586
Brian Carlstrom8a487412011-08-29 20:08:52 -0700587void Compiler::SetCodeAndDirectMethodsDexFile(const DexFile& dex_file) {
Ian Rogersad25ac52011-10-04 19:13:33 -0700588 Runtime* runtime = Runtime::Current();
589 ClassLinker* class_linker = runtime->GetClassLinker();
Brian Carlstrom83db7722011-08-26 17:32:56 -0700590 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700591 CodeAndDirectMethods* code_and_direct_methods = dex_cache->GetCodeAndDirectMethods();
Brian Carlstrom1caa2c22011-08-28 13:02:33 -0700592 for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
Brian Carlstrom83db7722011-08-26 17:32:56 -0700593 Method* method = dex_cache->GetResolvedMethod(i);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700594 if (method == NULL || method->IsDirect()) {
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700595 Runtime::TrampolineType type = Runtime::GetTrampolineType(method);
596 ByteArray* res_trampoline = runtime->GetResolutionStubArray(type);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700597 code_and_direct_methods->SetResolvedDirectMethodTrampoline(i, res_trampoline);
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700598 } else {
599 // TODO: we currently leave the entry blank for resolved
600 // non-direct methods. we could put in an error stub.
Brian Carlstrom83db7722011-08-26 17:32:56 -0700601 }
602 }
603}
604
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700605} // namespace art