blob: a04a836a6e089a68c762e0d241556ad9b2eb9ce8 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 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 */
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070016
17#include "compiler.h"
18
Brian Carlstrom27ec9612011-09-19 20:20:38 -070019#include <sys/mman.h>
20
Brian Carlstrom2cc022b2011-08-25 10:05:39 -070021#include "assembler.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070022#include "class_linker.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070023#include "class_loader.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070024#include "dex_cache.h"
Brian Carlstrome7d856b2012-01-11 18:10:55 -080025#include "dex_verifier.h"
Brian Carlstrom2cc022b2011-08-25 10:05:39 -070026#include "jni_compiler.h"
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070027#include "jni_internal.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070028#include "oat_file.h"
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080029#include "object_utils.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070030#include "runtime.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070031#include "stl_util.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070032
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070033namespace art {
34
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080035CompiledMethod* oatCompileMethod(const Compiler& compiler, const DexFile::CodeItem* code_item,
36 uint32_t access_flags, uint32_t method_idx,
37 const ClassLoader* class_loader,
38 const DexFile& dex_file, InstructionSet);
39
Shih-wei Liaoc486c112011-09-13 16:43:52 -070040namespace arm {
Ian Rogersbdb03912011-09-14 00:55:44 -070041 ByteArray* CreateAbstractMethodErrorStub();
Ian Rogers0571d352011-11-03 19:51:38 -070042 CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty);
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070043 ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type);
Elliott Hughes8add92d2012-01-18 18:18:43 -080044 ByteArray* CreateJniDlsymLookupStub();
Shih-wei Liaoc486c112011-09-13 16:43:52 -070045}
Shih-wei Liaoc486c112011-09-13 16:43:52 -070046namespace x86 {
Ian Rogersbdb03912011-09-14 00:55:44 -070047 ByteArray* CreateAbstractMethodErrorStub();
Ian Rogers0571d352011-11-03 19:51:38 -070048 CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty);
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070049 ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type);
Elliott Hughes8add92d2012-01-18 18:18:43 -080050 ByteArray* CreateJniDlsymLookupStub();
Brian Carlstrome24fa612011-09-29 00:53:55 -070051}
52
Brian Carlstromae826982011-11-09 01:33:42 -080053Compiler::Compiler(InstructionSet instruction_set,
54 bool image,
55 const std::set<std::string>* image_classes)
Brian Carlstromaded5f72011-10-07 17:15:04 -070056 : instruction_set_(instruction_set),
57 jni_compiler_(instruction_set),
58 image_(image),
Elliott Hughesbb551fa2012-01-25 16:35:29 -080059 dex_file_count_(0),
60 class_count_(0),
61 abstract_method_count_(0),
62 native_method_count_(0),
63 regular_method_count_(0),
64 instruction_count_(0),
65 start_ns_(NanoTime()),
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -080066 image_classes_(image_classes) {
Brian Carlstrom25c33252011-09-18 15:58:35 -070067 CHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -080068 if (!image_) {
69 CHECK(image_classes_ == NULL);
70 }
Shih-wei Liaoc486c112011-09-13 16:43:52 -070071}
72
Brian Carlstrom3320cf42011-10-04 14:58:28 -070073Compiler::~Compiler() {
Brian Carlstrom0755ec52012-01-11 15:19:46 -080074 STLDeleteValues(&compiled_classes_);
Brian Carlstrom3320cf42011-10-04 14:58:28 -070075 STLDeleteValues(&compiled_methods_);
76 STLDeleteValues(&compiled_invoke_stubs_);
Elliott Hughesbb551fa2012-01-25 16:35:29 -080077 if (dex_file_count_ > 0) {
78 uint64_t duration_ns = NanoTime() - start_ns_;
Elliott Hughesaa56b722012-01-26 13:25:35 -080079 std::string stats(StringPrintf("Compiled files:%zd"
80 " classes:%zd"
81 " methods:(abstract:%zd"
82 " native:%zd"
83 " regular:%zd)"
Ian Rogers3bb17a62012-01-27 23:56:44 -080084 " instructions:%zd",
Brian Carlstromfc0842b2012-01-26 11:41:11 -080085 dex_file_count_,
86 class_count_,
87 abstract_method_count_,
88 native_method_count_,
89 regular_method_count_,
Ian Rogers3bb17a62012-01-27 23:56:44 -080090 instruction_count_));
91 stats += " (took ",
92 stats += PrettyDuration(duration_ns);
Brian Carlstromfc0842b2012-01-26 11:41:11 -080093 if (instruction_count_ != 0) {
Ian Rogers3bb17a62012-01-27 23:56:44 -080094 stats += ", ";
95 stats += PrettyDuration(duration_ns / instruction_count_);
96 stats += "/instruction";
Brian Carlstromfc0842b2012-01-26 11:41:11 -080097 }
98 stats += ")";
99 LOG(INFO) << stats;
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800100 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700101}
102
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700103ByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set,
104 Runtime::TrampolineType type) {
Ian Rogersad25ac52011-10-04 19:13:33 -0700105 if (instruction_set == kX86) {
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700106 return x86::X86CreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -0700107 } else {
108 CHECK(instruction_set == kArm || instruction_set == kThumb2);
109 // Generates resolution stub using ARM instruction set
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700110 return arm::ArmCreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -0700111 }
112}
113
Elliott Hughes8add92d2012-01-18 18:18:43 -0800114ByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) {
Ian Rogers169c9a72011-11-13 20:13:17 -0800115 switch (instruction_set) {
116 case kArm:
117 case kThumb2:
Elliott Hughes8add92d2012-01-18 18:18:43 -0800118 return arm::CreateJniDlsymLookupStub();
Ian Rogers169c9a72011-11-13 20:13:17 -0800119 case kX86:
Elliott Hughes8add92d2012-01-18 18:18:43 -0800120 return x86::CreateJniDlsymLookupStub();
Ian Rogers169c9a72011-11-13 20:13:17 -0800121 default:
Elliott Hughesba8eee12012-01-24 20:25:24 -0800122 LOG(FATAL) << "Unknown InstructionSet: " << static_cast<int>(instruction_set);
Ian Rogers169c9a72011-11-13 20:13:17 -0800123 return NULL;
124 }
125}
126
Ian Rogersad25ac52011-10-04 19:13:33 -0700127ByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) {
128 if (instruction_set == kX86) {
129 return x86::CreateAbstractMethodErrorStub();
130 } else {
131 CHECK(instruction_set == kArm || instruction_set == kThumb2);
132 // Generates resolution stub using ARM instruction set
133 return arm::CreateAbstractMethodErrorStub();
134 }
135}
136
Jesse Wilson254db0f2011-11-16 16:44:11 -0500137void Compiler::CompileAll(const ClassLoader* class_loader,
Brian Carlstromae826982011-11-09 01:33:42 -0800138 const std::vector<const DexFile*>& dex_files) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700139 DCHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800140
141 PreCompile(class_loader, dex_files);
142 Compile(class_loader, dex_files);
143 PostCompile(class_loader, dex_files);
Brian Carlstrom8a487412011-08-29 20:08:52 -0700144}
145
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700146void Compiler::CompileOne(const Method* method) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700147 DCHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800148
Brian Carlstrom8a487412011-08-29 20:08:52 -0700149 const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
Brian Carlstromae826982011-11-09 01:33:42 -0800150
Ian Rogers0571d352011-11-03 19:51:38 -0700151 // Find the dex_file
152 const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
153 const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
Brian Carlstromae826982011-11-09 01:33:42 -0800154 std::vector<const DexFile*> dex_files;
155 dex_files.push_back(&dex_file);
156
157 PreCompile(class_loader, dex_files);
158
Ian Rogers0571d352011-11-03 19:51:38 -0700159 uint32_t method_idx = method->GetDexMethodIndex();
Ian Rogersa3760aa2011-11-14 14:32:37 -0800160 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
161 CompileMethod(code_item, method->GetAccessFlags(), method_idx, class_loader, dex_file);
Brian Carlstromae826982011-11-09 01:33:42 -0800162
163 PostCompile(class_loader, dex_files);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700164}
165
Brian Carlstromae826982011-11-09 01:33:42 -0800166void Compiler::Resolve(const ClassLoader* class_loader,
167 const std::vector<const DexFile*>& dex_files) {
168 for (size_t i = 0; i != dex_files.size(); ++i) {
169 const DexFile* dex_file = dex_files[i];
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700170 CHECK(dex_file != NULL);
171 ResolveDexFile(class_loader, *dex_file);
172 }
173}
174
Brian Carlstromae826982011-11-09 01:33:42 -0800175void Compiler::PreCompile(const ClassLoader* class_loader,
176 const std::vector<const DexFile*>& dex_files) {
177 Resolve(class_loader, dex_files);
178 Verify(class_loader, dex_files);
179 InitializeClassesWithoutClinit(class_loader, dex_files);
180}
181
182void Compiler::PostCompile(const ClassLoader* class_loader,
183 const std::vector<const DexFile*>& dex_files) {
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800184 SetGcMaps(class_loader, dex_files);
Brian Carlstromae826982011-11-09 01:33:42 -0800185 SetCodeAndDirectMethods(dex_files);
186}
187
188bool Compiler::IsImageClass(const std::string& descriptor) const {
189 if (image_classes_ == NULL) {
190 return true;
191 }
192 return image_classes_->find(descriptor) != image_classes_->end();
193}
194
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800195bool Compiler::CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache,
196 uint32_t type_idx) const {
197 if (!IsImage()) {
198 return false;
199 }
200 Class* resolved_class = dex_cache->GetResolvedTypes()->Get(type_idx);
201 if (resolved_class == NULL) {
202 return false;
203 }
204 return IsImageClass(ClassHelper(resolved_class).GetDescriptor());
205}
206
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800207// Return true if the class should be skipped during compilation. We
208// never skip classes in the boot class loader. However, if we have a
209// non-boot class loader and we can resolve the class in the boot
210// class loader, we do skip the class. This happens if an app bundles
211// classes found in the boot classpath. Since at runtime we will
212// select the class from the boot classpath, do not attempt to resolve
213// or compile it now.
214static bool SkipClass(const ClassLoader* class_loader,
215 const DexFile& dex_file,
216 const DexFile::ClassDef& class_def) {
217 if (class_loader == NULL) {
218 return false;
219 }
220 const char* descriptor = dex_file.GetClassDescriptor(class_def);
221 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
222 Class* klass = class_linker->FindClass(descriptor, NULL);
223 if (klass == NULL) {
224 Thread* self = Thread::Current();
225 CHECK(self->IsExceptionPending());
226 self->ClearException();
227 return false;
228 }
229 return true;
230}
231
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700232void Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800233 Thread* self = Thread::Current();
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700234 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromaded5f72011-10-07 17:15:04 -0700235 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700236
Brian Carlstromae826982011-11-09 01:33:42 -0800237 // Strings are easy in that they always are simply resolved to literals in the same file
238 if (image_ && image_classes_ == NULL) {
239 // TODO: Add support for loading strings referenced by image_classes_
240 // See also Compiler::CanAssumeTypeIsPresentInDexCache.
Brian Carlstromaded5f72011-10-07 17:15:04 -0700241 for (size_t string_idx = 0; string_idx < dex_cache->NumStrings(); string_idx++) {
242 class_linker->ResolveString(dex_file, string_idx, dex_cache);
243 }
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700244 }
245
Brian Carlstrom845490b2011-09-19 15:56:53 -0700246 // Class derived values are more complicated, they require the linker and loader.
Brian Carlstromffca45d2011-09-16 12:10:49 -0700247 for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
248 Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700249 if (klass == NULL) {
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800250 CHECK(self->IsExceptionPending());
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700251 Thread::Current()->ClearException();
252 }
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700253 }
Brian Carlstrom845490b2011-09-19 15:56:53 -0700254
255 // Method and Field are the worst. We can't resolve without either
256 // context from the code use (to disambiguate virtual vs direct
257 // method and instance vs static field) or from class
258 // definitions. While the compiler will resolve what it can as it
259 // needs it, here we try to resolve fields and methods used in class
260 // definitions, since many of them many never be referenced by
261 // generated code.
262 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
263 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800264 if (SkipClass(class_loader, dex_file, class_def)) {
265 continue;
266 }
Brian Carlstrom845490b2011-09-19 15:56:53 -0700267
268 // Note the class_data pointer advances through the headers,
269 // static fields, instance fields, direct methods, and virtual
270 // methods.
271 const byte* class_data = dex_file.GetClassData(class_def);
Ian Rogers0571d352011-11-03 19:51:38 -0700272 if (class_data == NULL) {
273 // empty class such as a marker interface
274 continue;
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700275 }
Ian Rogers0571d352011-11-03 19:51:38 -0700276 ClassDataItemIterator it(dex_file, class_data);
277 while (it.HasNextStaticField()) {
278 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
279 class_loader, true);
280 if (field == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700281 CHECK(self->IsExceptionPending());
282 self->ClearException();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700283 }
Ian Rogers0571d352011-11-03 19:51:38 -0700284 it.Next();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700285 }
Ian Rogers0571d352011-11-03 19:51:38 -0700286 while (it.HasNextInstanceField()) {
287 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
288 class_loader, false);
289 if (field == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700290 CHECK(self->IsExceptionPending());
291 self->ClearException();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700292 }
Ian Rogers0571d352011-11-03 19:51:38 -0700293 it.Next();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700294 }
Ian Rogers0571d352011-11-03 19:51:38 -0700295 while (it.HasNextDirectMethod()) {
296 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
297 class_loader, true);
298 if (method == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700299 CHECK(self->IsExceptionPending());
300 self->ClearException();
Brian Carlstrom845490b2011-09-19 15:56:53 -0700301 }
Ian Rogers0571d352011-11-03 19:51:38 -0700302 it.Next();
Brian Carlstrom20cfffa2011-08-26 02:31:27 -0700303 }
Ian Rogers0571d352011-11-03 19:51:38 -0700304 while (it.HasNextVirtualMethod()) {
305 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
306 class_loader, false);
307 if (method == NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700308 CHECK(self->IsExceptionPending());
309 self->ClearException();
310 }
311 it.Next();
312 }
313 DCHECK(!it.HasNext());
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700314 }
315}
316
Brian Carlstromae826982011-11-09 01:33:42 -0800317void Compiler::Verify(const ClassLoader* class_loader,
318 const std::vector<const DexFile*>& dex_files) {
319 for (size_t i = 0; i != dex_files.size(); ++i) {
320 const DexFile* dex_file = dex_files[i];
jeffhao98eacac2011-09-14 16:11:53 -0700321 CHECK(dex_file != NULL);
322 VerifyDexFile(class_loader, *dex_file);
323 }
324}
325
326void Compiler::VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
jeffhaob4df5142011-09-19 20:25:32 -0700327 dex_file.ChangePermissions(PROT_READ | PROT_WRITE);
jeffhao98eacac2011-09-14 16:11:53 -0700328 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700329 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
330 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
jeffhao98eacac2011-09-14 16:11:53 -0700331 const char* descriptor = dex_file.GetClassDescriptor(class_def);
332 Class* klass = class_linker->FindClass(descriptor, class_loader);
Brian Carlstrom65ca0772011-09-24 16:03:08 -0700333 if (klass == NULL) {
334 Thread* self = Thread::Current();
335 CHECK(self->IsExceptionPending());
336 self->ClearException();
337 continue;
338 }
339 CHECK(klass->IsResolved()) << PrettyClass(klass);
jeffhao98eacac2011-09-14 16:11:53 -0700340 class_linker->VerifyClass(klass);
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700341
342 if (klass->IsErroneous()) {
343 // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
344 CHECK(Thread::Current()->IsExceptionPending());
345 Thread::Current()->ClearException();
346 // We want to try verification again at run-time, so move back into the resolved state.
347 klass->SetStatus(Class::kStatusResolved);
348 }
349
jeffhao5cfd6fb2011-09-27 13:54:29 -0700350 CHECK(klass->IsVerified() || klass->IsResolved()) << PrettyClass(klass);
351 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700352 }
jeffhaob4df5142011-09-19 20:25:32 -0700353 dex_file.ChangePermissions(PROT_READ);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700354}
355
Brian Carlstromae826982011-11-09 01:33:42 -0800356void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader,
357 const std::vector<const DexFile*>& dex_files) {
358 for (size_t i = 0; i != dex_files.size(); ++i) {
359 const DexFile* dex_file = dex_files[i];
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700360 CHECK(dex_file != NULL);
361 InitializeClassesWithoutClinit(class_loader, *dex_file);
362 }
363}
364
365void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, const DexFile& dex_file) {
366 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700367 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
368 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700369 const char* descriptor = dex_file.GetClassDescriptor(class_def);
370 Class* klass = class_linker->FindClass(descriptor, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700371 if (klass != NULL) {
372 class_linker->EnsureInitialized(klass, false);
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800373 // record the final class status if necessary
374 Class::Status status = klass->GetStatus();
375 ClassReference ref(&dex_file, class_def_index);
376 CompiledClass* compiled_class = GetCompiledClass(ref);
377 if (compiled_class == NULL) {
378 compiled_class = new CompiledClass(status);
379 compiled_classes_[ref] = compiled_class;
380 } else {
381 DCHECK_EQ(status, compiled_class->GetStatus());
382 }
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700383 }
384 // clear any class not found or verification exceptions
385 Thread::Current()->ClearException();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700386 }
387
388 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
389 for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
390 Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700391 if (klass == NULL) {
392 Thread::Current()->ClearException();
393 } else if (klass->IsInitialized()) {
Brian Carlstromffca45d2011-09-16 12:10:49 -0700394 dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
395 }
jeffhao98eacac2011-09-14 16:11:53 -0700396 }
397}
398
Brian Carlstromae826982011-11-09 01:33:42 -0800399void Compiler::Compile(const ClassLoader* class_loader,
400 const std::vector<const DexFile*>& dex_files) {
401 for (size_t i = 0; i != dex_files.size(); ++i) {
402 const DexFile* dex_file = dex_files[i];
Brian Carlstrom83db7722011-08-26 17:32:56 -0700403 CHECK(dex_file != NULL);
404 CompileDexFile(class_loader, *dex_file);
405 }
406}
407
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700408void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800409 ++dex_file_count_;
Brian Carlstromffca45d2011-09-16 12:10:49 -0700410 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
411 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Ian Rogers0571d352011-11-03 19:51:38 -0700412 CompileClass(class_def, class_loader, dex_file);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700413 }
414}
415
Ian Rogers0571d352011-11-03 19:51:38 -0700416void Compiler::CompileClass(const DexFile::ClassDef& class_def, const ClassLoader* class_loader,
417 const DexFile& dex_file) {
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800418 if (SkipClass(class_loader, dex_file, class_def)) {
419 return;
420 }
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800421 ++class_count_;
Ian Rogers0571d352011-11-03 19:51:38 -0700422 const byte* class_data = dex_file.GetClassData(class_def);
423 if (class_data == NULL) {
424 // empty class, probably a marker interface
425 return;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700426 }
Ian Rogers0571d352011-11-03 19:51:38 -0700427 ClassDataItemIterator it(dex_file, class_data);
428 // Skip fields
429 while (it.HasNextStaticField()) {
430 it.Next();
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700431 }
Ian Rogers0571d352011-11-03 19:51:38 -0700432 while (it.HasNextInstanceField()) {
433 it.Next();
434 }
435 // Compile direct methods
436 while (it.HasNextDirectMethod()) {
Ian Rogersa3760aa2011-11-14 14:32:37 -0800437 CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(), it.GetMemberIndex(),
438 class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700439 it.Next();
440 }
441 // Compile virtual methods
442 while (it.HasNextVirtualMethod()) {
Ian Rogersa3760aa2011-11-14 14:32:37 -0800443 CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(), it.GetMemberIndex(),
444 class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700445 it.Next();
446 }
447 DCHECK(!it.HasNext());
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700448}
449
Ian Rogersa3760aa2011-11-14 14:32:37 -0800450void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
451 uint32_t method_idx, const ClassLoader* class_loader,
452 const DexFile& dex_file) {
Elliott Hughesf09afe82011-10-16 14:24:21 -0700453 CompiledMethod* compiled_method = NULL;
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800454 uint64_t start_ns = NanoTime();
Ian Rogers169c9a72011-11-13 20:13:17 -0800455 if ((access_flags & kAccNative) != 0) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800456 ++native_method_count_;
Ian Rogers169c9a72011-11-13 20:13:17 -0800457 compiled_method = jni_compiler_.Compile(access_flags, method_idx, class_loader, dex_file);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700458 CHECK(compiled_method != NULL);
Ian Rogers169c9a72011-11-13 20:13:17 -0800459 } else if ((access_flags & kAccAbstract) != 0) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800460 ++abstract_method_count_;
Brian Carlstrom2cc022b2011-08-25 10:05:39 -0700461 } else {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800462 ++regular_method_count_;
463 instruction_count_ += code_item->insns_size_in_code_units_;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800464 compiled_method = oatCompileMethod(*this, code_item, access_flags, method_idx, class_loader,
465 dex_file, kThumb2);
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800466 CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
467 }
Ian Rogers3bb17a62012-01-27 23:56:44 -0800468 uint64_t duration_ns = NanoTime() - start_ns;
469 if (duration_ns > MsToNs(10)) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800470 LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
Ian Rogers3bb17a62012-01-27 23:56:44 -0800471 << " took " << PrettyDuration(duration_ns);
Elliott Hughesf09afe82011-10-16 14:24:21 -0700472 }
473
474 if (compiled_method != NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -0700475 MethodReference ref(&dex_file, method_idx);
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800476 CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700477 compiled_methods_[ref] = compiled_method;
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800478 DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file);
Brian Carlstrom2cc022b2011-08-25 10:05:39 -0700479 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700480
Ian Rogers0571d352011-11-03 19:51:38 -0700481 const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
Ian Rogers169c9a72011-11-13 20:13:17 -0800482 bool is_static = (access_flags & kAccStatic) != 0;
Ian Rogers0571d352011-11-03 19:51:38 -0700483 const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
484 if (compiled_invoke_stub == NULL) {
485 if (instruction_set_ == kX86) {
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800486 compiled_invoke_stub = ::art::x86::X86CreateInvokeStub(is_static, shorty);
Ian Rogers0571d352011-11-03 19:51:38 -0700487 } else {
488 CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
489 // Generates invocation stub using ARM instruction set
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800490 compiled_invoke_stub = ::art::arm::ArmCreateInvokeStub(is_static, shorty);
Ian Rogers0571d352011-11-03 19:51:38 -0700491 }
492 CHECK(compiled_invoke_stub != NULL);
493 InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
Ian Rogers2c8f6532011-09-02 17:16:34 -0700494 }
Ian Rogers0571d352011-11-03 19:51:38 -0700495 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700496}
497
Ian Rogers0571d352011-11-03 19:51:38 -0700498static std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
499 std::string key(shorty);
500 if (is_static) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800501 key += "$"; // Must not be a shorty type character.
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700502 }
Ian Rogers0571d352011-11-03 19:51:38 -0700503 return key;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700504}
505
Ian Rogers0571d352011-11-03 19:51:38 -0700506const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
Elliott Hughes95572412011-12-13 18:14:20 -0800507 const std::string key(MakeInvokeStubKey(is_static, shorty));
Ian Rogers0571d352011-11-03 19:51:38 -0700508 InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700509 if (it == compiled_invoke_stubs_.end()) {
510 return NULL;
Ian Rogers0571d352011-11-03 19:51:38 -0700511 } else {
512 DCHECK(it->second != NULL);
513 return it->second;
514 }
515}
516
517void Compiler::InsertInvokeStub(bool is_static, const char* shorty,
518 const CompiledInvokeStub* compiled_invoke_stub) {
Elliott Hughes95572412011-12-13 18:14:20 -0800519 std::string key(MakeInvokeStubKey(is_static, shorty));
Ian Rogers0571d352011-11-03 19:51:38 -0700520 compiled_invoke_stubs_[key] = compiled_invoke_stub;
521}
522
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800523CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const {
524 ClassTable::const_iterator it = compiled_classes_.find(ref);
525 if (it == compiled_classes_.end()) {
526 return NULL;
527 }
528 CHECK(it->second != NULL);
529 return it->second;
530}
531
Ian Rogers0571d352011-11-03 19:51:38 -0700532CompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
533 MethodTable::const_iterator it = compiled_methods_.find(ref);
534 if (it == compiled_methods_.end()) {
535 return NULL;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700536 }
537 CHECK(it->second != NULL);
538 return it->second;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700539}
540
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800541void Compiler::SetGcMaps(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files) {
542 for (size_t i = 0; i != dex_files.size(); ++i) {
543 const DexFile* dex_file = dex_files[i];
544 CHECK(dex_file != NULL);
545 SetGcMapsDexFile(class_loader, *dex_file);
546 }
547}
548
549void Compiler::SetGcMapsDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
550 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
551 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
552 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
553 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
554 const char* descriptor = dex_file.GetClassDescriptor(class_def);
555 Class* klass = class_linker->FindClass(descriptor, class_loader);
556 if (klass == NULL || !klass->IsVerified()) {
557 Thread::Current()->ClearException();
558 continue;
559 }
560 const byte* class_data = dex_file.GetClassData(class_def);
561 if (class_data == NULL) {
562 // empty class such as a marker interface
563 continue;
564 }
565 ClassDataItemIterator it(dex_file, class_data);
566 while (it.HasNextStaticField()) {
567 it.Next();
568 }
569 while (it.HasNextInstanceField()) {
570 it.Next();
571 }
572 while (it.HasNextDirectMethod()) {
573 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
574 class_loader, true);
575 SetGcMapsMethod(dex_file, method);
576 it.Next();
577 }
578 while (it.HasNextVirtualMethod()) {
579 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
580 class_loader, false);
581 SetGcMapsMethod(dex_file, method);
582 it.Next();
583 }
584 }
585}
586
587void Compiler::SetGcMapsMethod(const DexFile& dex_file, Method* method) {
588 if (method == NULL) {
589 Thread::Current()->ClearException();
590 return;
591 }
592 uint16_t method_idx = method->GetDexMethodIndex();
593 MethodReference ref(&dex_file, method_idx);
594 CompiledMethod* compiled_method = GetCompiledMethod(ref);
595 if (compiled_method == NULL) {
596 return;
597 }
598 const std::vector<uint8_t>* gc_map = verifier::DexVerifier::GetGcMap(ref);
599 if (gc_map == NULL) {
600 return;
601 }
602 compiled_method->SetGcMap(*gc_map);
603}
604
Brian Carlstromae826982011-11-09 01:33:42 -0800605void Compiler::SetCodeAndDirectMethods(const std::vector<const DexFile*>& dex_files) {
606 for (size_t i = 0; i != dex_files.size(); ++i) {
607 const DexFile* dex_file = dex_files[i];
Brian Carlstrom83db7722011-08-26 17:32:56 -0700608 CHECK(dex_file != NULL);
Brian Carlstrom8a487412011-08-29 20:08:52 -0700609 SetCodeAndDirectMethodsDexFile(*dex_file);
Brian Carlstrom83db7722011-08-26 17:32:56 -0700610 }
611}
612
Brian Carlstrom8a487412011-08-29 20:08:52 -0700613void Compiler::SetCodeAndDirectMethodsDexFile(const DexFile& dex_file) {
Ian Rogersad25ac52011-10-04 19:13:33 -0700614 Runtime* runtime = Runtime::Current();
615 ClassLinker* class_linker = runtime->GetClassLinker();
Brian Carlstrom83db7722011-08-26 17:32:56 -0700616 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700617 CodeAndDirectMethods* code_and_direct_methods = dex_cache->GetCodeAndDirectMethods();
Brian Carlstrom1caa2c22011-08-28 13:02:33 -0700618 for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
Brian Carlstrom83db7722011-08-26 17:32:56 -0700619 Method* method = dex_cache->GetResolvedMethod(i);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700620 if (method == NULL || method->IsDirect()) {
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700621 Runtime::TrampolineType type = Runtime::GetTrampolineType(method);
622 ByteArray* res_trampoline = runtime->GetResolutionStubArray(type);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700623 code_and_direct_methods->SetResolvedDirectMethodTrampoline(i, res_trampoline);
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700624 } else {
625 // TODO: we currently leave the entry blank for resolved
626 // non-direct methods. we could put in an error stub.
Brian Carlstrom83db7722011-08-26 17:32:56 -0700627 }
628 }
629}
630
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700631} // namespace art