blob: a3655c6932a8bd367d272fddb36d2308ebdeff3c [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 Carlstrom2cc022b2011-08-25 10:05:39 -070011#include "jni_compiler.h"
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070012#include "jni_internal.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070013#include "oat_file.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070014#include "runtime.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070015#include "stl_util.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070016
Ian Rogersa3760aa2011-11-14 14:32:37 -080017art::CompiledMethod* oatCompileMethod(const art::Compiler& compiler,
18 const art::DexFile::CodeItem* code_item,
19 uint32_t access_flags, uint32_t method_idx,
20 const art::ClassLoader* class_loader,
Ian Rogers0571d352011-11-03 19:51:38 -070021 const art::DexFile& dex_file, art::InstructionSet);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070022
23namespace art {
24
Shih-wei Liaoc486c112011-09-13 16:43:52 -070025namespace arm {
Ian Rogersbdb03912011-09-14 00:55:44 -070026 ByteArray* CreateAbstractMethodErrorStub();
Ian Rogers0571d352011-11-03 19:51:38 -070027 CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty);
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070028 ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type);
Ian Rogers169c9a72011-11-13 20:13:17 -080029 ByteArray* CreateJniDlysmLookupStub();
Shih-wei Liaoc486c112011-09-13 16:43:52 -070030}
Shih-wei Liaoc486c112011-09-13 16:43:52 -070031namespace x86 {
Ian Rogersbdb03912011-09-14 00:55:44 -070032 ByteArray* CreateAbstractMethodErrorStub();
Ian Rogers0571d352011-11-03 19:51:38 -070033 CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty);
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070034 ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type);
Ian Rogers169c9a72011-11-13 20:13:17 -080035 ByteArray* CreateJniDlysmLookupStub();
Brian Carlstrome24fa612011-09-29 00:53:55 -070036}
37
Brian Carlstromaded5f72011-10-07 17:15:04 -070038Compiler::Compiler(InstructionSet instruction_set, bool image)
39 : instruction_set_(instruction_set),
40 jni_compiler_(instruction_set),
41 image_(image),
42 verbose_(false) {
Brian Carlstrom25c33252011-09-18 15:58:35 -070043 CHECK(!Runtime::Current()->IsStarted());
Shih-wei Liaoc486c112011-09-13 16:43:52 -070044}
45
Brian Carlstrom3320cf42011-10-04 14:58:28 -070046Compiler::~Compiler() {
47 STLDeleteValues(&compiled_methods_);
48 STLDeleteValues(&compiled_invoke_stubs_);
49}
50
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070051ByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set,
52 Runtime::TrampolineType type) {
Ian Rogersad25ac52011-10-04 19:13:33 -070053 if (instruction_set == kX86) {
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070054 return x86::X86CreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -070055 } else {
56 CHECK(instruction_set == kArm || instruction_set == kThumb2);
57 // Generates resolution stub using ARM instruction set
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070058 return arm::ArmCreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -070059 }
60}
61
Ian Rogers169c9a72011-11-13 20:13:17 -080062ByteArray* Compiler::CreateJniDlysmLookupStub(InstructionSet instruction_set) {
63 switch (instruction_set) {
64 case kArm:
65 case kThumb2:
66 return arm::CreateJniDlysmLookupStub();
67 case kX86:
68 return x86::CreateJniDlysmLookupStub();
69 default:
70 LOG(FATAL) << "Unknown InstructionSet " << (int) instruction_set;
71 return NULL;
72 }
73}
74
Ian Rogersad25ac52011-10-04 19:13:33 -070075ByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) {
76 if (instruction_set == kX86) {
77 return x86::CreateAbstractMethodErrorStub();
78 } else {
79 CHECK(instruction_set == kArm || instruction_set == kThumb2);
80 // Generates resolution stub using ARM instruction set
81 return arm::CreateAbstractMethodErrorStub();
82 }
83}
84
Jesse Wilson254db0f2011-11-16 16:44:11 -050085void Compiler::CompileAll(const ClassLoader* class_loader,
86 const std::vector<const DexFile*>& dex_files) {
Brian Carlstrom25c33252011-09-18 15:58:35 -070087 DCHECK(!Runtime::Current()->IsStarted());
Jesse Wilson254db0f2011-11-16 16:44:11 -050088 for (size_t i = 0; i != dex_files.size(); ++i) {
89 ResolveDexFile(class_loader, *dex_files[i]);
90 }
91 for (size_t i = 0; i != dex_files.size(); ++i) {
92 VerifyDexFile(class_loader, *dex_files[i]);
93 }
94 for (size_t i = 0; i != dex_files.size(); ++i) {
95 InitializeClassesWithoutClinit(class_loader, *dex_files[i]);
96 }
97 for (size_t i = 0; i != dex_files.size(); ++i) {
98 CompileDexFile(class_loader, *dex_files[i]);
99 }
100 for (size_t i = 0; i != dex_files.size(); ++i) {
101 SetCodeAndDirectMethodsDexFile(*dex_files[i]);
102 }
Brian Carlstrom8a487412011-08-29 20:08:52 -0700103}
104
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700105void Compiler::CompileOne(const Method* method) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700106 DCHECK(!Runtime::Current()->IsStarted());
Brian Carlstrom8a487412011-08-29 20:08:52 -0700107 const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
108 Resolve(class_loader);
jeffhao98eacac2011-09-14 16:11:53 -0700109 Verify(class_loader);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700110 InitializeClassesWithoutClinit(class_loader);
Ian Rogers0571d352011-11-03 19:51:38 -0700111 // Find the dex_file
112 const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
113 const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
114 uint32_t method_idx = method->GetDexMethodIndex();
Ian Rogersa3760aa2011-11-14 14:32:37 -0800115 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
116 CompileMethod(code_item, method->GetAccessFlags(), method_idx, class_loader, dex_file);
Brian Carlstrom8a487412011-08-29 20:08:52 -0700117 SetCodeAndDirectMethods(class_loader);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700118}
119
120void Compiler::Resolve(const ClassLoader* class_loader) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700121 const std::vector<const DexFile*>& class_path
122 = ClassLoader::GetCompileTimeClassPath(class_loader);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700123 for (size_t i = 0; i != class_path.size(); ++i) {
124 const DexFile* dex_file = class_path[i];
125 CHECK(dex_file != NULL);
126 ResolveDexFile(class_loader, *dex_file);
127 }
128}
129
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800130// Return true if the class should be skipped during compilation. We
131// never skip classes in the boot class loader. However, if we have a
132// non-boot class loader and we can resolve the class in the boot
133// class loader, we do skip the class. This happens if an app bundles
134// classes found in the boot classpath. Since at runtime we will
135// select the class from the boot classpath, do not attempt to resolve
136// or compile it now.
137static bool SkipClass(const ClassLoader* class_loader,
138 const DexFile& dex_file,
139 const DexFile::ClassDef& class_def) {
140 if (class_loader == NULL) {
141 return false;
142 }
143 const char* descriptor = dex_file.GetClassDescriptor(class_def);
144 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
145 Class* klass = class_linker->FindClass(descriptor, NULL);
146 if (klass == NULL) {
147 Thread* self = Thread::Current();
148 CHECK(self->IsExceptionPending());
149 self->ClearException();
150 return false;
151 }
152 return true;
153}
154
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700155void Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800156 Thread* self = Thread::Current();
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700157 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromaded5f72011-10-07 17:15:04 -0700158 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700159
160 // Strings are easy, they always are simply resolved to literals in the same file
Brian Carlstromaded5f72011-10-07 17:15:04 -0700161 if (IsImage()) { // Only resolve when we'll have an image, so compiler won't choose fast path
162 for (size_t string_idx = 0; string_idx < dex_cache->NumStrings(); string_idx++) {
163 class_linker->ResolveString(dex_file, string_idx, dex_cache);
164 }
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700165 }
166
Brian Carlstrom845490b2011-09-19 15:56:53 -0700167 // Class derived values are more complicated, they require the linker and loader.
Brian Carlstromffca45d2011-09-16 12:10:49 -0700168 for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
169 Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700170 if (klass == NULL) {
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800171 CHECK(self->IsExceptionPending());
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700172 Thread::Current()->ClearException();
173 }
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700174 }
Brian Carlstrom845490b2011-09-19 15:56:53 -0700175
176 // Method and Field are the worst. We can't resolve without either
177 // context from the code use (to disambiguate virtual vs direct
178 // method and instance vs static field) or from class
179 // definitions. While the compiler will resolve what it can as it
180 // needs it, here we try to resolve fields and methods used in class
181 // definitions, since many of them many never be referenced by
182 // generated code.
183 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
184 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800185 if (SkipClass(class_loader, dex_file, class_def)) {
186 continue;
187 }
Brian Carlstrom845490b2011-09-19 15:56:53 -0700188
189 // Note the class_data pointer advances through the headers,
190 // static fields, instance fields, direct methods, and virtual
191 // methods.
192 const byte* class_data = dex_file.GetClassData(class_def);
Ian Rogers0571d352011-11-03 19:51:38 -0700193 if (class_data == NULL) {
194 // empty class such as a marker interface
195 continue;
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700196 }
Ian Rogers0571d352011-11-03 19:51:38 -0700197 ClassDataItemIterator it(dex_file, class_data);
198 while (it.HasNextStaticField()) {
199 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
200 class_loader, true);
201 if (field == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700202 CHECK(self->IsExceptionPending());
203 self->ClearException();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700204 }
Ian Rogers0571d352011-11-03 19:51:38 -0700205 it.Next();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700206 }
Ian Rogers0571d352011-11-03 19:51:38 -0700207 while (it.HasNextInstanceField()) {
208 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
209 class_loader, false);
210 if (field == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700211 CHECK(self->IsExceptionPending());
212 self->ClearException();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700213 }
Ian Rogers0571d352011-11-03 19:51:38 -0700214 it.Next();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700215 }
Ian Rogers0571d352011-11-03 19:51:38 -0700216 while (it.HasNextDirectMethod()) {
217 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
218 class_loader, true);
219 if (method == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700220 CHECK(self->IsExceptionPending());
221 self->ClearException();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700222 }
Ian Rogers0571d352011-11-03 19:51:38 -0700223 it.Next();
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700224 }
Ian Rogers0571d352011-11-03 19:51:38 -0700225 while (it.HasNextVirtualMethod()) {
226 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
227 class_loader, false);
228 if (method == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700229 CHECK(self->IsExceptionPending());
230 self->ClearException();
231 }
232 it.Next();
233 }
234 DCHECK(!it.HasNext());
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700235 }
236}
237
jeffhao98eacac2011-09-14 16:11:53 -0700238void Compiler::Verify(const ClassLoader* class_loader) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700239 const std::vector<const DexFile*>& class_path
240 = ClassLoader::GetCompileTimeClassPath(class_loader);
jeffhao98eacac2011-09-14 16:11:53 -0700241 for (size_t i = 0; i != class_path.size(); ++i) {
242 const DexFile* dex_file = class_path[i];
243 CHECK(dex_file != NULL);
244 VerifyDexFile(class_loader, *dex_file);
245 }
246}
247
248void Compiler::VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
jeffhaob4df5142011-09-19 20:25:32 -0700249 dex_file.ChangePermissions(PROT_READ | PROT_WRITE);
jeffhao98eacac2011-09-14 16:11:53 -0700250 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700251 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
252 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
jeffhao98eacac2011-09-14 16:11:53 -0700253 const char* descriptor = dex_file.GetClassDescriptor(class_def);
254 Class* klass = class_linker->FindClass(descriptor, class_loader);
Brian Carlstrom65ca0772011-09-24 16:03:08 -0700255 if (klass == NULL) {
256 Thread* self = Thread::Current();
257 CHECK(self->IsExceptionPending());
258 self->ClearException();
259 continue;
260 }
261 CHECK(klass->IsResolved()) << PrettyClass(klass);
jeffhao98eacac2011-09-14 16:11:53 -0700262 class_linker->VerifyClass(klass);
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700263
264 if (klass->IsErroneous()) {
265 // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
266 CHECK(Thread::Current()->IsExceptionPending());
267 Thread::Current()->ClearException();
268 // We want to try verification again at run-time, so move back into the resolved state.
269 klass->SetStatus(Class::kStatusResolved);
270 }
271
jeffhao5cfd6fb2011-09-27 13:54:29 -0700272 CHECK(klass->IsVerified() || klass->IsResolved()) << PrettyClass(klass);
273 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700274 }
jeffhaob4df5142011-09-19 20:25:32 -0700275 dex_file.ChangePermissions(PROT_READ);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700276}
277
278void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700279 const std::vector<const DexFile*>& class_path
280 = ClassLoader::GetCompileTimeClassPath(class_loader);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700281 for (size_t i = 0; i != class_path.size(); ++i) {
282 const DexFile* dex_file = class_path[i];
283 CHECK(dex_file != NULL);
284 InitializeClassesWithoutClinit(class_loader, *dex_file);
285 }
286}
287
288void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, const DexFile& dex_file) {
289 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700290 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
291 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700292 const char* descriptor = dex_file.GetClassDescriptor(class_def);
293 Class* klass = class_linker->FindClass(descriptor, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700294 if (klass != NULL) {
295 class_linker->EnsureInitialized(klass, false);
296 }
297 // clear any class not found or verification exceptions
298 Thread::Current()->ClearException();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700299 }
300
301 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
302 for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
303 Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700304 if (klass == NULL) {
305 Thread::Current()->ClearException();
306 } else if (klass->IsInitialized()) {
Brian Carlstromffca45d2011-09-16 12:10:49 -0700307 dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
308 }
jeffhao98eacac2011-09-14 16:11:53 -0700309 }
310}
311
Brian Carlstrom83db7722011-08-26 17:32:56 -0700312void Compiler::Compile(const ClassLoader* class_loader) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700313 const std::vector<const DexFile*>& class_path
314 = ClassLoader::GetCompileTimeClassPath(class_loader);
Brian Carlstrom83db7722011-08-26 17:32:56 -0700315 for (size_t i = 0; i != class_path.size(); ++i) {
316 const DexFile* dex_file = class_path[i];
317 CHECK(dex_file != NULL);
318 CompileDexFile(class_loader, *dex_file);
319 }
320}
321
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700322void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
Brian Carlstromffca45d2011-09-16 12:10:49 -0700323 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
324 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Ian Rogers0571d352011-11-03 19:51:38 -0700325 CompileClass(class_def, class_loader, dex_file);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700326 }
327}
328
Ian Rogers0571d352011-11-03 19:51:38 -0700329void Compiler::CompileClass(const DexFile::ClassDef& class_def, const ClassLoader* class_loader,
330 const DexFile& dex_file) {
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800331 if (SkipClass(class_loader, dex_file, class_def)) {
332 return;
333 }
Ian Rogers0571d352011-11-03 19:51:38 -0700334 const byte* class_data = dex_file.GetClassData(class_def);
335 if (class_data == NULL) {
336 // empty class, probably a marker interface
337 return;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700338 }
Ian Rogers0571d352011-11-03 19:51:38 -0700339 ClassDataItemIterator it(dex_file, class_data);
340 // Skip fields
341 while (it.HasNextStaticField()) {
342 it.Next();
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700343 }
Ian Rogers0571d352011-11-03 19:51:38 -0700344 while (it.HasNextInstanceField()) {
345 it.Next();
346 }
347 // Compile direct methods
348 while (it.HasNextDirectMethod()) {
Ian Rogersa3760aa2011-11-14 14:32:37 -0800349 CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(), it.GetMemberIndex(),
350 class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700351 it.Next();
352 }
353 // Compile virtual methods
354 while (it.HasNextVirtualMethod()) {
Ian Rogersa3760aa2011-11-14 14:32:37 -0800355 CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(), it.GetMemberIndex(),
356 class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700357 it.Next();
358 }
359 DCHECK(!it.HasNext());
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700360}
361
Ian Rogersa3760aa2011-11-14 14:32:37 -0800362void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
363 uint32_t method_idx, const ClassLoader* class_loader,
364 const DexFile& dex_file) {
Elliott Hughesf09afe82011-10-16 14:24:21 -0700365 CompiledMethod* compiled_method = NULL;
Ian Rogers169c9a72011-11-13 20:13:17 -0800366 if ((access_flags & kAccNative) != 0) {
367 compiled_method = jni_compiler_.Compile(access_flags, method_idx, class_loader, dex_file);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700368 CHECK(compiled_method != NULL);
Ian Rogers169c9a72011-11-13 20:13:17 -0800369 } else if ((access_flags & kAccAbstract) != 0) {
Brian Carlstrom2cc022b2011-08-25 10:05:39 -0700370 } else {
Ian Rogersa3760aa2011-11-14 14:32:37 -0800371 compiled_method = oatCompileMethod(*this, code_item, access_flags, method_idx, class_loader,
372 dex_file, kThumb2);
373 CHECK(compiled_method != NULL);
Elliott Hughesf09afe82011-10-16 14:24:21 -0700374 }
375
376 if (compiled_method != NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700377 MethodReference ref(&dex_file, method_idx);
378 CHECK(compiled_methods_.find(ref) == compiled_methods_.end())
379 << PrettyMethod(method_idx, dex_file);
380 compiled_methods_[ref] = compiled_method;
381 DCHECK(compiled_methods_.find(ref) != compiled_methods_.end())
382 << PrettyMethod(method_idx, dex_file);
383 DCHECK(GetCompiledMethod(ref) != NULL)
384 << PrettyMethod(method_idx, dex_file);
Brian Carlstrom2cc022b2011-08-25 10:05:39 -0700385 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700386
Ian Rogers0571d352011-11-03 19:51:38 -0700387 const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
Ian Rogers169c9a72011-11-13 20:13:17 -0800388 bool is_static = (access_flags & kAccStatic) != 0;
Ian Rogers0571d352011-11-03 19:51:38 -0700389 const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
390 if (compiled_invoke_stub == NULL) {
391 if (instruction_set_ == kX86) {
392 compiled_invoke_stub = art::x86::X86CreateInvokeStub(is_static, shorty);
393 } else {
394 CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
395 // Generates invocation stub using ARM instruction set
396 compiled_invoke_stub = art::arm::ArmCreateInvokeStub(is_static, shorty);
397 }
398 CHECK(compiled_invoke_stub != NULL);
399 InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700400 }
Ian Rogers0571d352011-11-03 19:51:38 -0700401 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700402}
403
Ian Rogers0571d352011-11-03 19:51:38 -0700404static std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
405 std::string key(shorty);
406 if (is_static) {
407 key += "$"; // musn't be a shorty type character
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700408 }
Ian Rogers0571d352011-11-03 19:51:38 -0700409 return key;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700410}
411
Ian Rogers0571d352011-11-03 19:51:38 -0700412const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
413 std::string key = MakeInvokeStubKey(is_static, shorty);
414 InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700415 if (it == compiled_invoke_stubs_.end()) {
416 return NULL;
Ian Rogers0571d352011-11-03 19:51:38 -0700417 } else {
418 DCHECK(it->second != NULL);
419 return it->second;
420 }
421}
422
423void Compiler::InsertInvokeStub(bool is_static, const char* shorty,
424 const CompiledInvokeStub* compiled_invoke_stub) {
425 std::string key = MakeInvokeStubKey(is_static, shorty);
426 compiled_invoke_stubs_[key] = compiled_invoke_stub;
427}
428
429CompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
430 MethodTable::const_iterator it = compiled_methods_.find(ref);
431 if (it == compiled_methods_.end()) {
432 return NULL;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700433 }
434 CHECK(it->second != NULL);
435 return it->second;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700436}
437
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700438void Compiler::SetCodeAndDirectMethods(const ClassLoader* class_loader) {
Brian Carlstromaded5f72011-10-07 17:15:04 -0700439 const std::vector<const DexFile*>& class_path
440 = ClassLoader::GetCompileTimeClassPath(class_loader);
Brian Carlstrom83db7722011-08-26 17:32:56 -0700441 for (size_t i = 0; i != class_path.size(); ++i) {
442 const DexFile* dex_file = class_path[i];
443 CHECK(dex_file != NULL);
Brian Carlstrom8a487412011-08-29 20:08:52 -0700444 SetCodeAndDirectMethodsDexFile(*dex_file);
Brian Carlstrom83db7722011-08-26 17:32:56 -0700445 }
446}
447
Brian Carlstrom8a487412011-08-29 20:08:52 -0700448void Compiler::SetCodeAndDirectMethodsDexFile(const DexFile& dex_file) {
Ian Rogersad25ac52011-10-04 19:13:33 -0700449 Runtime* runtime = Runtime::Current();
450 ClassLinker* class_linker = runtime->GetClassLinker();
Brian Carlstrom83db7722011-08-26 17:32:56 -0700451 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700452 CodeAndDirectMethods* code_and_direct_methods = dex_cache->GetCodeAndDirectMethods();
Brian Carlstrom1caa2c22011-08-28 13:02:33 -0700453 for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
Brian Carlstrom83db7722011-08-26 17:32:56 -0700454 Method* method = dex_cache->GetResolvedMethod(i);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700455 if (method == NULL || method->IsDirect()) {
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700456 Runtime::TrampolineType type = Runtime::GetTrampolineType(method);
457 ByteArray* res_trampoline = runtime->GetResolutionStubArray(type);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700458 code_and_direct_methods->SetResolvedDirectMethodTrampoline(i, res_trampoline);
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700459 } else {
460 // TODO: we currently leave the entry blank for resolved
461 // non-direct methods. we could put in an error stub.
Brian Carlstrom83db7722011-08-26 17:32:56 -0700462 }
463 }
464}
465
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700466} // namespace art