blob: b7583d9f891ede52ec8027794d38a9f9accfbd5f [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
Elliott Hughesd9c67be2012-02-02 19:54:06 -080019#include <vector>
20
Brian Carlstrom27ec9612011-09-19 20:20:38 -070021#include <sys/mman.h>
Elliott Hughesd9c67be2012-02-02 19:54:06 -080022#include <unistd.h>
Brian Carlstrom27ec9612011-09-19 20:20:38 -070023
Brian Carlstrom2cc022b2011-08-25 10:05:39 -070024#include "assembler.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070025#include "class_linker.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070026#include "class_loader.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070027#include "dex_cache.h"
Brian Carlstrom2cc022b2011-08-25 10:05:39 -070028#include "jni_compiler.h"
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070029#include "jni_internal.h"
Logan Chien4dd96f52012-02-29 01:26:58 +080030#include "oat_compilation_unit.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070031#include "oat_file.h"
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080032#include "object_utils.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070033#include "runtime.h"
Brian Carlstrom3320cf42011-10-04 14:58:28 -070034#include "stl_util.h"
Elliott Hughes601a1232012-02-02 17:47:38 -080035#include "timing_logger.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070036
Shih-wei Liaod1fec812012-02-13 09:51:10 -080037#if defined(ART_USE_LLVM_COMPILER)
38#include "compiler_llvm/compiler_llvm.h"
39#endif
40
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070041namespace art {
42
Shih-wei Liaod1fec812012-02-13 09:51:10 -080043#if !defined(ART_USE_LLVM_COMPILER)
Ian Rogers996cc582012-02-14 22:23:29 -080044CompiledMethod* oatCompileMethod(Compiler& compiler, const DexFile::CodeItem* code_item,
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080045 uint32_t access_flags, uint32_t method_idx,
46 const ClassLoader* class_loader,
47 const DexFile& dex_file, InstructionSet);
Shih-wei Liaod1fec812012-02-13 09:51:10 -080048#endif
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080049
Shih-wei Liaoc486c112011-09-13 16:43:52 -070050namespace arm {
Ian Rogersbdb03912011-09-14 00:55:44 -070051 ByteArray* CreateAbstractMethodErrorStub();
Ian Rogers45619fc2012-02-29 11:15:25 -080052 CompiledInvokeStub* ArmCreateInvokeStub(bool is_static, const char* shorty, uint32_t shorty_len);
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070053 ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type);
Elliott Hughes8add92d2012-01-18 18:18:43 -080054 ByteArray* CreateJniDlsymLookupStub();
Shih-wei Liaoc486c112011-09-13 16:43:52 -070055}
Shih-wei Liaoc486c112011-09-13 16:43:52 -070056namespace x86 {
Ian Rogersbdb03912011-09-14 00:55:44 -070057 ByteArray* CreateAbstractMethodErrorStub();
Ian Rogers45619fc2012-02-29 11:15:25 -080058 CompiledInvokeStub* X86CreateInvokeStub(bool is_static, const char* shorty, uint32_t shorty_len);
Ian Rogers1cb0a1d2011-10-06 15:24:35 -070059 ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type);
Elliott Hughes8add92d2012-01-18 18:18:43 -080060 ByteArray* CreateJniDlsymLookupStub();
Brian Carlstrome24fa612011-09-29 00:53:55 -070061}
62
jeffhaod1224c72012-02-29 13:43:08 -080063namespace verifier {
64 class DexVerifier {
65 public:
66 static const std::vector<uint8_t>* GetGcMap(Compiler::MethodReference ref);
67 static bool IsClassRejected(Compiler::ClassReference ref);
68 };
69}
70
Ian Rogers996cc582012-02-14 22:23:29 -080071static double Percentage(size_t x, size_t y) {
72 return 100.0 * ((double)x) / ((double)(x + y));
73}
74
75static void DumpStat(size_t x, size_t y, const char* str) {
76 if (x == 0 && y == 0) {
77 return;
78 }
79 LOG(INFO) << Percentage(x, y) << "% of " << str << " for " << (x + y) << " cases";
80}
81
Ian Rogersc8b306f2012-02-17 21:34:44 -080082class AOTCompilationStats {
83 public:
84 AOTCompilationStats() : stats_lock_("AOT compilation statistics lock"),
85 types_in_dex_cache_(0), types_not_in_dex_cache_(0),
86 strings_in_dex_cache_(0), strings_not_in_dex_cache_(0),
87 resolved_types_(0), unresolved_types_(0),
88 resolved_instance_fields_(0), unresolved_instance_fields_(0),
89 resolved_local_static_fields_(0), resolved_static_fields_(0), unresolved_static_fields_(0) {
90 for (size_t i = 0; i < kMaxInvokeType; i++) {
91 resolved_methods_[i] = 0;
92 unresolved_methods_[i] = 0;
93 }
94 }
95
96 void Dump() {
97 DumpStat(types_in_dex_cache_, types_not_in_dex_cache_, "types known to be in dex cache");
98 DumpStat(strings_in_dex_cache_, strings_not_in_dex_cache_, "strings known to be in dex cache");
99 DumpStat(resolved_types_, unresolved_types_, "types resolved");
100 DumpStat(resolved_instance_fields_, unresolved_instance_fields_, "instance fields resolved");
101 DumpStat(resolved_local_static_fields_ + resolved_static_fields_, unresolved_static_fields_,
102 "static fields resolved");
103 DumpStat(resolved_local_static_fields_, resolved_static_fields_ + unresolved_static_fields_,
104 "static fields local to a class");
105
106 for (size_t i = 0; i < kMaxInvokeType; i++) {
107 std::ostringstream oss;
108 oss << "resolved " << static_cast<InvokeType>(i) << " methods";
109 DumpStat(resolved_methods_[i], unresolved_methods_[i], oss.str().c_str());
110 }
111 }
Ian Rogers996cc582012-02-14 22:23:29 -0800112
113// Allow lossy statistics in non-debug builds
114#ifndef NDEBUG
115#define STATS_LOCK() MutexLock mu(stats_lock_)
116#else
117#define STATS_LOCK()
118#endif
119
Ian Rogersc8b306f2012-02-17 21:34:44 -0800120 void TypeInDexCache() {
121 STATS_LOCK();
122 types_in_dex_cache_++;
Ian Rogers996cc582012-02-14 22:23:29 -0800123 }
Ian Rogers996cc582012-02-14 22:23:29 -0800124
Ian Rogersc8b306f2012-02-17 21:34:44 -0800125 void TypeNotInDexCache() {
126 STATS_LOCK();
127 types_not_in_dex_cache_++;
Ian Rogers996cc582012-02-14 22:23:29 -0800128 }
Ian Rogersc8b306f2012-02-17 21:34:44 -0800129
130 void StringInDexCache() {
131 STATS_LOCK();
132 strings_in_dex_cache_++;
133 }
134
135 void StringNotInDexCache() {
136 STATS_LOCK();
137 strings_not_in_dex_cache_++;
138 }
139
140 void TypeDoesntNeedAccessCheck() {
141 STATS_LOCK();
142 resolved_types_++;
143 }
144
145 void TypeNeedsAccessCheck() {
146 STATS_LOCK();
147 unresolved_types_++;
148 }
149
150 void ResolvedInstanceField() {
151 STATS_LOCK();
152 resolved_instance_fields_++;
153 }
154
155 void UnresolvedInstanceField(){
156 STATS_LOCK();
157 unresolved_instance_fields_++;
158 }
159
160 void ResolvedLocalStaticField() {
161 STATS_LOCK();
162 resolved_local_static_fields_++;
163 }
164
165 void ResolvedStaticField() {
166 STATS_LOCK();
167 resolved_static_fields_++;
168 }
169
170 void UnresolvedStaticField() {
171 STATS_LOCK();
172 unresolved_static_fields_++;
173 }
174
175 void ResolvedMethod(InvokeType type) {
176 DCHECK_LE(type, kMaxInvokeType);
177 STATS_LOCK();
178 resolved_methods_[type]++;
179 }
180
181 void UnresolvedMethod(InvokeType type) {
182 DCHECK_LE(type, kMaxInvokeType);
183 STATS_LOCK();
184 unresolved_methods_[type]++;
185 }
186
187 private:
188 Mutex stats_lock_;
189
190 size_t types_in_dex_cache_;
191 size_t types_not_in_dex_cache_;
192
193 size_t strings_in_dex_cache_;
194 size_t strings_not_in_dex_cache_;
195
196 size_t resolved_types_;
197 size_t unresolved_types_;
198
199 size_t resolved_instance_fields_;
200 size_t unresolved_instance_fields_;
201
202 size_t resolved_local_static_fields_;
203 size_t resolved_static_fields_;
204 size_t unresolved_static_fields_;
205
206 size_t resolved_methods_[kMaxInvokeType + 1];
207 size_t unresolved_methods_[kMaxInvokeType + 1];
208
209 DISALLOW_COPY_AND_ASSIGN(AOTCompilationStats);;
210};
Ian Rogers996cc582012-02-14 22:23:29 -0800211
Elliott Hughes5523ee02012-02-03 18:18:34 -0800212Compiler::Compiler(InstructionSet instruction_set, bool image, size_t thread_count,
Elliott Hughesde6e4cf2012-02-27 14:46:06 -0800213 bool support_debugging, const std::set<std::string>* image_classes)
Brian Carlstromaded5f72011-10-07 17:15:04 -0700214 : instruction_set_(instruction_set),
215 jni_compiler_(instruction_set),
Elliott Hughesc225caa2012-02-03 15:43:37 -0800216 compiled_classes_lock_("compiled classes lock"),
217 compiled_methods_lock_("compiled method lock"),
218 compiled_invoke_stubs_lock_("compiled invoke stubs lock"),
Brian Carlstromaded5f72011-10-07 17:15:04 -0700219 image_(image),
Elliott Hughes5523ee02012-02-03 18:18:34 -0800220 thread_count_(thread_count),
Elliott Hughesde6e4cf2012-02-27 14:46:06 -0800221 support_debugging_(support_debugging),
Ian Rogersc8b306f2012-02-17 21:34:44 -0800222 stats_(new AOTCompilationStats),
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800223 image_classes_(image_classes)
224#if defined(ART_USE_LLVM_COMPILER)
225 ,
226 compiler_llvm_(new compiler_llvm::CompilerLLVM(this, instruction_set))
227#endif
228 {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700229 CHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800230 if (!image_) {
231 CHECK(image_classes_ == NULL);
232 }
Shih-wei Liaoc486c112011-09-13 16:43:52 -0700233}
234
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700235Compiler::~Compiler() {
Elliott Hughesc225caa2012-02-03 15:43:37 -0800236 {
237 MutexLock mu(compiled_classes_lock_);
238 STLDeleteValues(&compiled_classes_);
239 }
240 {
241 MutexLock mu(compiled_methods_lock_);
242 STLDeleteValues(&compiled_methods_);
243 }
244 {
245 MutexLock mu(compiled_invoke_stubs_lock_);
246 STLDeleteValues(&compiled_invoke_stubs_);
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800247 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700248}
249
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700250ByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set,
251 Runtime::TrampolineType type) {
Ian Rogersad25ac52011-10-04 19:13:33 -0700252 if (instruction_set == kX86) {
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700253 return x86::X86CreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -0700254 } else {
255 CHECK(instruction_set == kArm || instruction_set == kThumb2);
256 // Generates resolution stub using ARM instruction set
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700257 return arm::ArmCreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -0700258 }
259}
260
Elliott Hughes8add92d2012-01-18 18:18:43 -0800261ByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) {
Ian Rogers169c9a72011-11-13 20:13:17 -0800262 switch (instruction_set) {
263 case kArm:
264 case kThumb2:
Elliott Hughes8add92d2012-01-18 18:18:43 -0800265 return arm::CreateJniDlsymLookupStub();
Ian Rogers169c9a72011-11-13 20:13:17 -0800266 case kX86:
Elliott Hughes8add92d2012-01-18 18:18:43 -0800267 return x86::CreateJniDlsymLookupStub();
Ian Rogers169c9a72011-11-13 20:13:17 -0800268 default:
Elliott Hughesba8eee12012-01-24 20:25:24 -0800269 LOG(FATAL) << "Unknown InstructionSet: " << static_cast<int>(instruction_set);
Ian Rogers169c9a72011-11-13 20:13:17 -0800270 return NULL;
271 }
272}
273
Ian Rogersad25ac52011-10-04 19:13:33 -0700274ByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) {
275 if (instruction_set == kX86) {
276 return x86::CreateAbstractMethodErrorStub();
277 } else {
278 CHECK(instruction_set == kArm || instruction_set == kThumb2);
279 // Generates resolution stub using ARM instruction set
280 return arm::CreateAbstractMethodErrorStub();
281 }
282}
283
Jesse Wilson254db0f2011-11-16 16:44:11 -0500284void Compiler::CompileAll(const ClassLoader* class_loader,
Brian Carlstromae826982011-11-09 01:33:42 -0800285 const std::vector<const DexFile*>& dex_files) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700286 DCHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800287
Elliott Hughes601a1232012-02-02 17:47:38 -0800288 TimingLogger timings("compiler");
289
290 PreCompile(class_loader, dex_files, timings);
291
Brian Carlstromae826982011-11-09 01:33:42 -0800292 Compile(class_loader, dex_files);
Elliott Hughes601a1232012-02-02 17:47:38 -0800293 timings.AddSplit("Compile");
294
Brian Carlstromae826982011-11-09 01:33:42 -0800295 PostCompile(class_loader, dex_files);
Elliott Hughes601a1232012-02-02 17:47:38 -0800296 timings.AddSplit("PostCompile");
297
298 if (timings.GetTotalNs() > MsToNs(1000)) {
299 timings.Dump();
300 }
Ian Rogers996cc582012-02-14 22:23:29 -0800301
Ian Rogersc8b306f2012-02-17 21:34:44 -0800302 stats_->Dump();
Brian Carlstrom8a487412011-08-29 20:08:52 -0700303}
304
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700305void Compiler::CompileOne(const Method* method) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700306 DCHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800307
Brian Carlstrom8a487412011-08-29 20:08:52 -0700308 const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
Brian Carlstromae826982011-11-09 01:33:42 -0800309
Ian Rogers0571d352011-11-03 19:51:38 -0700310 // Find the dex_file
311 const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
312 const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
Brian Carlstromae826982011-11-09 01:33:42 -0800313 std::vector<const DexFile*> dex_files;
314 dex_files.push_back(&dex_file);
315
Elliott Hughes601a1232012-02-02 17:47:38 -0800316 TimingLogger timings("CompileOne");
317 PreCompile(class_loader, dex_files, timings);
Brian Carlstromae826982011-11-09 01:33:42 -0800318
Ian Rogers0571d352011-11-03 19:51:38 -0700319 uint32_t method_idx = method->GetDexMethodIndex();
Ian Rogersa3760aa2011-11-14 14:32:37 -0800320 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
321 CompileMethod(code_item, method->GetAccessFlags(), method_idx, class_loader, dex_file);
Brian Carlstromae826982011-11-09 01:33:42 -0800322
323 PostCompile(class_loader, dex_files);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700324}
325
Brian Carlstromae826982011-11-09 01:33:42 -0800326void Compiler::Resolve(const ClassLoader* class_loader,
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800327 const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
Brian Carlstromae826982011-11-09 01:33:42 -0800328 for (size_t i = 0; i != dex_files.size(); ++i) {
329 const DexFile* dex_file = dex_files[i];
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700330 CHECK(dex_file != NULL);
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800331 ResolveDexFile(class_loader, *dex_file, timings);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700332 }
333}
334
Brian Carlstromae826982011-11-09 01:33:42 -0800335void Compiler::PreCompile(const ClassLoader* class_loader,
Elliott Hughes601a1232012-02-02 17:47:38 -0800336 const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800337 Resolve(class_loader, dex_files, timings);
Elliott Hughes601a1232012-02-02 17:47:38 -0800338
Brian Carlstromae826982011-11-09 01:33:42 -0800339 Verify(class_loader, dex_files);
Elliott Hughes601a1232012-02-02 17:47:38 -0800340 timings.AddSplit("PreCompile.Verify");
341
Brian Carlstromae826982011-11-09 01:33:42 -0800342 InitializeClassesWithoutClinit(class_loader, dex_files);
Elliott Hughes601a1232012-02-02 17:47:38 -0800343 timings.AddSplit("PreCompile.InitializeClassesWithoutClinit");
Brian Carlstromae826982011-11-09 01:33:42 -0800344}
345
346void Compiler::PostCompile(const ClassLoader* class_loader,
347 const std::vector<const DexFile*>& dex_files) {
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800348 SetGcMaps(class_loader, dex_files);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800349#if defined(ART_USE_LLVM_COMPILER)
350 compiler_llvm_->MaterializeLLVMModule();
351#endif
Brian Carlstromae826982011-11-09 01:33:42 -0800352}
353
354bool Compiler::IsImageClass(const std::string& descriptor) const {
355 if (image_classes_ == NULL) {
356 return true;
357 }
358 return image_classes_->find(descriptor) != image_classes_->end();
359}
360
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800361bool Compiler::CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache,
Ian Rogers996cc582012-02-14 22:23:29 -0800362 uint32_t type_idx) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800363 if (!IsImage()) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800364 stats_->TypeNotInDexCache();
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800365 return false;
366 }
Ian Rogers1bddec32012-02-04 12:27:34 -0800367 Class* resolved_class = dex_cache->GetResolvedType(type_idx);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800368 if (resolved_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800369 stats_->TypeNotInDexCache();
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800370 return false;
371 }
Ian Rogers996cc582012-02-14 22:23:29 -0800372 bool result = IsImageClass(ClassHelper(resolved_class).GetDescriptor());
373 if (result) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800374 stats_->TypeInDexCache();
Ian Rogers996cc582012-02-14 22:23:29 -0800375 } else {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800376 stats_->TypeNotInDexCache();
Ian Rogers996cc582012-02-14 22:23:29 -0800377 }
378 return result;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800379}
380
Ian Rogers1bddec32012-02-04 12:27:34 -0800381bool Compiler::CanAssumeStringIsPresentInDexCache(const DexCache* dex_cache,
Ian Rogers996cc582012-02-14 22:23:29 -0800382 uint32_t string_idx) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800383 // TODO: Add support for loading strings referenced by image_classes_
384 // See also Compiler::ResolveDexFile
385
386 // The following is a test saying that if we're building the image without a restricted set of
387 // image classes then we can assume the string is present in the dex cache if it is there now
Ian Rogers996cc582012-02-14 22:23:29 -0800388 bool result = IsImage() && image_classes_ == NULL && dex_cache->GetResolvedString(string_idx) != NULL;
389 if (result) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800390 stats_->StringInDexCache();
Ian Rogers996cc582012-02-14 22:23:29 -0800391 } else {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800392 stats_->StringNotInDexCache();
Ian Rogers996cc582012-02-14 22:23:29 -0800393 }
394 return result;
Ian Rogers1bddec32012-02-04 12:27:34 -0800395}
396
397bool Compiler::CanAccessTypeWithoutChecks(uint32_t referrer_idx, const DexCache* dex_cache,
Ian Rogers996cc582012-02-14 22:23:29 -0800398 const DexFile& dex_file, uint32_t type_idx) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800399 // Get type from dex cache assuming it was populated by the verifier
400 Class* resolved_class = dex_cache->GetResolvedType(type_idx);
401 if (resolved_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800402 stats_->TypeNeedsAccessCheck();
Ian Rogers1bddec32012-02-04 12:27:34 -0800403 return false; // Unknown class needs access checks.
404 }
405 const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
406 Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
407 if (referrer_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800408 stats_->TypeNeedsAccessCheck();
Ian Rogers1bddec32012-02-04 12:27:34 -0800409 return false; // Incomplete referrer knowledge needs access check.
410 }
411 // Perform access check, will return true if access is ok or false if we're going to have to
412 // check this at runtime (for example for class loaders).
Ian Rogers996cc582012-02-14 22:23:29 -0800413 bool result = referrer_class->CanAccess(resolved_class);
414 if (result) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800415 stats_->TypeDoesntNeedAccessCheck();
Ian Rogers996cc582012-02-14 22:23:29 -0800416 } else {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800417 stats_->TypeNeedsAccessCheck();
Ian Rogers996cc582012-02-14 22:23:29 -0800418 }
419 return result;
Ian Rogers1bddec32012-02-04 12:27:34 -0800420}
421
422bool Compiler::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx,
423 const DexCache* dex_cache,
424 const DexFile& dex_file,
Ian Rogers996cc582012-02-14 22:23:29 -0800425 uint32_t type_idx) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800426 // Get type from dex cache assuming it was populated by the verifier.
427 Class* resolved_class = dex_cache->GetResolvedType(type_idx);
428 if (resolved_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800429 stats_->TypeNeedsAccessCheck();
Ian Rogers1bddec32012-02-04 12:27:34 -0800430 return false; // Unknown class needs access checks.
431 }
432 const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
433 Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
434 if (referrer_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800435 stats_->TypeNeedsAccessCheck();
Ian Rogers1bddec32012-02-04 12:27:34 -0800436 return false; // Incomplete referrer knowledge needs access check.
437 }
438 // Perform access and instantiable checks, will return true if access is ok or false if we're
439 // going to have to check this at runtime (for example for class loaders).
Ian Rogers996cc582012-02-14 22:23:29 -0800440 bool result = referrer_class->CanAccess(resolved_class) && resolved_class->IsInstantiable();
441 if (result) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800442 stats_->TypeDoesntNeedAccessCheck();
Ian Rogers996cc582012-02-14 22:23:29 -0800443 } else {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800444 stats_->TypeNeedsAccessCheck();
Ian Rogers996cc582012-02-14 22:23:29 -0800445 }
446 return result;
Ian Rogers1bddec32012-02-04 12:27:34 -0800447}
448
Logan Chien4dd96f52012-02-29 01:26:58 +0800449static Class* ComputeReferrerClass(OatCompilationUnit* mUnit) {
450 const DexFile::MethodId& referrer_method_id =
451 mUnit->dex_file_->GetMethodId(mUnit->method_idx_);
452
453 return mUnit->class_linker_->ResolveType(
454 *mUnit->dex_file_, referrer_method_id.class_idx_,
455 mUnit->dex_cache_, mUnit->class_loader_);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800456}
457
Logan Chien4dd96f52012-02-29 01:26:58 +0800458static Field* ComputeReferrerField(OatCompilationUnit* mUnit, uint32_t field_idx) {
459 return mUnit->class_linker_->ResolveField(
460 *mUnit->dex_file_, field_idx, mUnit->dex_cache_,
461 mUnit->class_loader_, false);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800462}
463
Logan Chien4dd96f52012-02-29 01:26:58 +0800464static Method* ComputeReferrerMethod(OatCompilationUnit* mUnit, uint32_t method_idx) {
465 return mUnit->class_linker_->ResolveMethod(
466 *mUnit->dex_file_, method_idx, mUnit->dex_cache_,
467 mUnit->class_loader_, true);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800468}
469
Logan Chien4dd96f52012-02-29 01:26:58 +0800470bool Compiler::ComputeInstanceFieldInfo(uint32_t field_idx, OatCompilationUnit* mUnit,
jeffhao8cd6dda2012-02-22 10:15:34 -0800471 int& field_offset, bool& is_volatile, bool is_put) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800472 // Conservative defaults
473 field_offset = -1;
474 is_volatile = true;
475 // Try to resolve field
Logan Chien4dd96f52012-02-29 01:26:58 +0800476 Field* resolved_field = ComputeReferrerField(mUnit, field_idx);
Ian Rogers1bddec32012-02-04 12:27:34 -0800477 if (resolved_field != NULL) {
Logan Chien4dd96f52012-02-29 01:26:58 +0800478 Class* referrer_class = ComputeReferrerClass(mUnit);
Ian Rogers1bddec32012-02-04 12:27:34 -0800479 // Try to resolve referring class then access check, failure to pass the
480 Class* fields_class = resolved_field->GetDeclaringClass();
jeffhao8cd6dda2012-02-22 10:15:34 -0800481 bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal() &&
482 fields_class != referrer_class;
483 if (referrer_class != NULL && referrer_class->CanAccess(fields_class) &&
484 referrer_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) &&
485 !is_write_to_final_from_wrong_class) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800486 field_offset = resolved_field->GetOffset().Int32Value();
487 is_volatile = resolved_field->IsVolatile();
Ian Rogersc8b306f2012-02-17 21:34:44 -0800488 stats_->ResolvedInstanceField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800489 return true; // Fast path.
490 }
491 }
492 // Clean up any exception left by field/type resolution
493 Thread* thread = Thread::Current();
494 if (thread->IsExceptionPending()) {
495 thread->ClearException();
496 }
Ian Rogersc8b306f2012-02-17 21:34:44 -0800497 stats_->UnresolvedInstanceField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800498 return false; // Incomplete knowledge needs slow path.
499}
500
Logan Chien4dd96f52012-02-29 01:26:58 +0800501bool Compiler::ComputeStaticFieldInfo(uint32_t field_idx, OatCompilationUnit* mUnit,
Ian Rogers1bddec32012-02-04 12:27:34 -0800502 int& field_offset, int& ssb_index,
jeffhao8cd6dda2012-02-22 10:15:34 -0800503 bool& is_referrers_class, bool& is_volatile, bool is_put) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800504 // Conservative defaults
505 field_offset = -1;
506 ssb_index = -1;
507 is_referrers_class = false;
508 is_volatile = true;
509 // Try to resolve field
Logan Chien4dd96f52012-02-29 01:26:58 +0800510 Field* resolved_field = ComputeReferrerField(mUnit, field_idx);
Ian Rogers1bddec32012-02-04 12:27:34 -0800511 if (resolved_field != NULL) {
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800512 DCHECK(resolved_field->IsStatic());
Logan Chien4dd96f52012-02-29 01:26:58 +0800513 Class* referrer_class = ComputeReferrerClass(mUnit);
Ian Rogers1bddec32012-02-04 12:27:34 -0800514 if (referrer_class != NULL) {
jeffhao8cd6dda2012-02-22 10:15:34 -0800515 Class* fields_class = resolved_field->GetDeclaringClass();
516 if (fields_class == referrer_class) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800517 is_referrers_class = true; // implies no worrying about class initialization
518 field_offset = resolved_field->GetOffset().Int32Value();
519 is_volatile = resolved_field->IsVolatile();
Ian Rogersc8b306f2012-02-17 21:34:44 -0800520 stats_->ResolvedLocalStaticField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800521 return true; // fast path
522 } else {
jeffhao8cd6dda2012-02-22 10:15:34 -0800523 bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal();
Ian Rogers1bddec32012-02-04 12:27:34 -0800524 if (referrer_class->CanAccess(fields_class) &&
jeffhao8cd6dda2012-02-22 10:15:34 -0800525 referrer_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) &&
526 !is_write_to_final_from_wrong_class) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800527 // We have the resolved field, we must make it into a ssbIndex for the referrer
528 // in its static storage base (which may fail if it doesn't have a slot for it)
Ian Rogers4103ad22012-02-06 09:18:25 -0800529 // TODO: for images we can elide the static storage base null check
530 // if we know there's a non-null entry in the image
Logan Chien4dd96f52012-02-29 01:26:58 +0800531 if (fields_class->GetDexCache() == mUnit->dex_cache_) {
Ian Rogers4103ad22012-02-06 09:18:25 -0800532 // common case where the dex cache of both the referrer and the field are the same,
533 // no need to search the dex file
534 ssb_index = fields_class->GetDexTypeIndex();
535 field_offset = resolved_field->GetOffset().Int32Value();
536 is_volatile = resolved_field->IsVolatile();
Ian Rogersc8b306f2012-02-17 21:34:44 -0800537 stats_->ResolvedStaticField();
Ian Rogers4103ad22012-02-06 09:18:25 -0800538 return true;
539 }
540 // Search dex file for localized ssb index
Ian Rogers1bddec32012-02-04 12:27:34 -0800541 std::string descriptor(FieldHelper(resolved_field).GetDeclaringClassDescriptor());
542 const DexFile::StringId* string_id =
Logan Chien4dd96f52012-02-29 01:26:58 +0800543 mUnit->dex_file_->FindStringId(descriptor);
Ian Rogers1bddec32012-02-04 12:27:34 -0800544 if (string_id != NULL) {
545 const DexFile::TypeId* type_id =
Logan Chien4dd96f52012-02-29 01:26:58 +0800546 mUnit->dex_file_->FindTypeId(mUnit->dex_file_->GetIndexForStringId(*string_id));
Ian Rogers1bddec32012-02-04 12:27:34 -0800547 if(type_id != NULL) {
548 // medium path, needs check of static storage base being initialized
Logan Chien4dd96f52012-02-29 01:26:58 +0800549 ssb_index = mUnit->dex_file_->GetIndexForTypeId(*type_id);
Ian Rogers1bddec32012-02-04 12:27:34 -0800550 field_offset = resolved_field->GetOffset().Int32Value();
551 is_volatile = resolved_field->IsVolatile();
Ian Rogersc8b306f2012-02-17 21:34:44 -0800552 stats_->ResolvedStaticField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800553 return true;
554 }
555 }
556 }
557 }
558 }
559 }
560 // Clean up any exception left by field/type resolution
561 Thread* thread = Thread::Current();
562 if (thread->IsExceptionPending()) {
563 thread->ClearException();
564 }
Ian Rogersc8b306f2012-02-17 21:34:44 -0800565 stats_->UnresolvedStaticField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800566 return false; // Incomplete knowledge needs slow path.
567}
568
Logan Chien4dd96f52012-02-29 01:26:58 +0800569bool Compiler::ComputeInvokeInfo(uint32_t method_idx, OatCompilationUnit* mUnit, InvokeType type,
Ian Rogers996cc582012-02-14 22:23:29 -0800570 int& vtable_idx) {
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800571 vtable_idx = -1;
Logan Chien4dd96f52012-02-29 01:26:58 +0800572 Method* resolved_method = ComputeReferrerMethod(mUnit, method_idx);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800573 if (resolved_method != NULL) {
Logan Chien4dd96f52012-02-29 01:26:58 +0800574 Class* referrer_class = ComputeReferrerClass(mUnit);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800575 if (referrer_class != NULL) {
576 Class* methods_class = resolved_method->GetDeclaringClass();
577 if (!referrer_class->CanAccess(methods_class) ||
578 !referrer_class->CanAccessMember(methods_class,
Ian Rogers996cc582012-02-14 22:23:29 -0800579 resolved_method->GetAccessFlags())) {
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800580 // The referring class can't access the resolved method, this may occur as a result of a
581 // protected method being made public by implementing an interface that re-declares the
582 // method public. Resort to the dex file to determine the correct class for the access check
Logan Chien4dd96f52012-02-29 01:26:58 +0800583 const DexFile& dex_file = mUnit->class_linker_->FindDexFile(referrer_class->GetDexCache());
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800584 methods_class =
Logan Chien4dd96f52012-02-29 01:26:58 +0800585 mUnit->class_linker_->ResolveType(dex_file,
586 dex_file.GetMethodId(method_idx).class_idx_,
587 referrer_class);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800588
589 }
590 if (referrer_class->CanAccess(methods_class) &&
591 referrer_class->CanAccessMember(methods_class,
592 resolved_method->GetAccessFlags())) {
593 vtable_idx = resolved_method->GetMethodIndex();
Ian Rogersc8b306f2012-02-17 21:34:44 -0800594 if (type != kSuper) {
595 // nothing left to do for static/direct/virtual/interface dispatch
596 stats_->ResolvedMethod(type);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800597 return true;
598 } else {
599 // ensure the vtable index will be correct to dispatch in the vtable of the super class
Ian Rogers996cc582012-02-14 22:23:29 -0800600 if (referrer_class->IsSubClass(methods_class) &&
601 vtable_idx < methods_class->GetVTable()->GetLength()) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800602 stats_->ResolvedMethod(type);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800603 return true;
604 }
605 }
606 }
607 }
608 }
609 // Clean up any exception left by method/type resolution
610 Thread* thread = Thread::Current();
611 if (thread->IsExceptionPending()) {
612 thread->ClearException();
613 }
Ian Rogersc8b306f2012-02-17 21:34:44 -0800614 stats_->UnresolvedMethod(type);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800615 return false; // Incomplete knowledge needs slow path.
616}
617
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800618// Return true if the class should be skipped during compilation. We
619// never skip classes in the boot class loader. However, if we have a
620// non-boot class loader and we can resolve the class in the boot
621// class loader, we do skip the class. This happens if an app bundles
622// classes found in the boot classpath. Since at runtime we will
623// select the class from the boot classpath, do not attempt to resolve
624// or compile it now.
625static bool SkipClass(const ClassLoader* class_loader,
626 const DexFile& dex_file,
627 const DexFile::ClassDef& class_def) {
628 if (class_loader == NULL) {
629 return false;
630 }
631 const char* descriptor = dex_file.GetClassDescriptor(class_def);
632 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
633 Class* klass = class_linker->FindClass(descriptor, NULL);
634 if (klass == NULL) {
635 Thread* self = Thread::Current();
636 CHECK(self->IsExceptionPending());
637 self->ClearException();
638 return false;
639 }
640 return true;
641}
642
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800643struct Context {
644 ClassLinker* class_linker;
645 const ClassLoader* class_loader;
Elliott Hughesc225caa2012-02-03 15:43:37 -0800646 Compiler* compiler;
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800647 DexCache* dex_cache;
648 const DexFile* dex_file;
649};
650
651typedef void Callback(Context* context, size_t index);
652
653class WorkerThread {
654 public:
Elliott Hughes1e409252012-02-06 11:21:27 -0800655 WorkerThread(Context* context, size_t begin, size_t end, Callback callback, size_t stripe, bool spawn)
656 : spawn_(spawn), context_(context), begin_(begin), end_(end), callback_(callback), stripe_(stripe) {
657 if (spawn_) {
658 CHECK_PTHREAD_CALL(pthread_create, (&pthread_, NULL, &Go, this), "compiler worker thread");
659 }
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800660 }
661
662 ~WorkerThread() {
Elliott Hughes1e409252012-02-06 11:21:27 -0800663 if (spawn_) {
664 CHECK_PTHREAD_CALL(pthread_join, (pthread_, NULL), "compiler worker shutdown");
665 }
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800666 }
667
668 private:
Elliott Hughes1e409252012-02-06 11:21:27 -0800669 static void* Go(void* arg) {
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800670 WorkerThread* worker = reinterpret_cast<WorkerThread*>(arg);
671 Runtime* runtime = Runtime::Current();
Elliott Hughes1e409252012-02-06 11:21:27 -0800672 if (worker->spawn_) {
673 runtime->AttachCurrentThread("Compiler Worker", true);
674 }
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800675 Thread::Current()->SetState(Thread::kRunnable);
676 worker->Run();
Elliott Hughes1e409252012-02-06 11:21:27 -0800677 if (worker->spawn_) {
678 Thread::Current()->SetState(Thread::kNative);
679 runtime->DetachCurrentThread();
680 }
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800681 return NULL;
682 }
683
Elliott Hughes1e409252012-02-06 11:21:27 -0800684 void Go() {
685 Go(this);
686 }
687
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800688 void Run() {
689 for (size_t i = begin_; i < end_; i += stripe_) {
690 callback_(context_, i);
691 }
692 }
693
694 pthread_t pthread_;
Elliott Hughes1e409252012-02-06 11:21:27 -0800695 bool spawn_;
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800696
697 Context* context_;
698 size_t begin_;
699 size_t end_;
700 Callback* callback_;
701 size_t stripe_;
Elliott Hughes1e409252012-02-06 11:21:27 -0800702
703 friend void ForAll(Context*, size_t, size_t, Callback, size_t);
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800704};
705
Elliott Hughes5523ee02012-02-03 18:18:34 -0800706void ForAll(Context* context, size_t begin, size_t end, Callback callback, size_t thread_count) {
Elliott Hughes1e409252012-02-06 11:21:27 -0800707 CHECK_GT(thread_count, 0U);
Elliott Hughes81d91512012-02-03 16:38:43 -0800708
Elliott Hughes1e409252012-02-06 11:21:27 -0800709 std::vector<WorkerThread*> threads;
Elliott Hughes81d91512012-02-03 16:38:43 -0800710 for (size_t i = 0; i < thread_count; ++i) {
Elliott Hughes1e409252012-02-06 11:21:27 -0800711 threads.push_back(new WorkerThread(context, begin + i, end, callback, thread_count, (i != 0)));
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800712 }
Elliott Hughes1e409252012-02-06 11:21:27 -0800713 threads[0]->Go();
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800714
Elliott Hughes81d91512012-02-03 16:38:43 -0800715 // Switch to kVmWait while we're blocked waiting for the other threads to finish.
716 ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
717 STLDeleteElements(&threads);
718}
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800719
720static void ResolveClassFieldsAndMethods(Context* context, size_t class_def_index) {
721 const DexFile& dex_file = *context->dex_file;
722
723 // Method and Field are the worst. We can't resolve without either
724 // context from the code use (to disambiguate virtual vs direct
725 // method and instance vs static field) or from class
726 // definitions. While the compiler will resolve what it can as it
727 // needs it, here we try to resolve fields and methods used in class
728 // definitions, since many of them many never be referenced by
729 // generated code.
730 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
731 if (SkipClass(context->class_loader, dex_file, class_def)) {
732 return;
733 }
734
735 // Note the class_data pointer advances through the headers,
736 // static fields, instance fields, direct methods, and virtual
737 // methods.
738 const byte* class_data = dex_file.GetClassData(class_def);
739 if (class_data == NULL) {
740 // empty class such as a marker interface
741 return;
742 }
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800743 Thread* self = Thread::Current();
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800744 ClassLinker* class_linker = context->class_linker;
745 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
746 ClassDataItemIterator it(dex_file, class_data);
747 while (it.HasNextStaticField()) {
748 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
749 context->class_loader, true);
750 if (field == NULL) {
751 CHECK(self->IsExceptionPending());
752 self->ClearException();
753 }
754 it.Next();
755 }
756 while (it.HasNextInstanceField()) {
757 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
758 context->class_loader, false);
759 if (field == NULL) {
760 CHECK(self->IsExceptionPending());
761 self->ClearException();
762 }
763 it.Next();
764 }
765 while (it.HasNextDirectMethod()) {
766 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
767 context->class_loader, true);
768 if (method == NULL) {
769 CHECK(self->IsExceptionPending());
770 self->ClearException();
771 }
772 it.Next();
773 }
774 while (it.HasNextVirtualMethod()) {
775 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
776 context->class_loader, false);
777 if (method == NULL) {
778 CHECK(self->IsExceptionPending());
779 self->ClearException();
780 }
781 it.Next();
782 }
783 DCHECK(!it.HasNext());
784}
785
786static void ResolveType(Context* context, size_t type_idx) {
787 // Class derived values are more complicated, they require the linker and loader.
788 Thread* self = Thread::Current();
789 ClassLinker* class_linker = context->class_linker;
790 const DexFile& dex_file = *context->dex_file;
791 Class* klass = class_linker->ResolveType(dex_file, type_idx, context->dex_cache, context->class_loader);
792 if (klass == NULL) {
793 CHECK(self->IsExceptionPending());
794 Thread::Current()->ClearException();
795 }
796}
797
798void Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file, TimingLogger& timings) {
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700799 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromaded5f72011-10-07 17:15:04 -0700800 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700801
Brian Carlstromae826982011-11-09 01:33:42 -0800802 // Strings are easy in that they always are simply resolved to literals in the same file
803 if (image_ && image_classes_ == NULL) {
804 // TODO: Add support for loading strings referenced by image_classes_
805 // See also Compiler::CanAssumeTypeIsPresentInDexCache.
Brian Carlstromaded5f72011-10-07 17:15:04 -0700806 for (size_t string_idx = 0; string_idx < dex_cache->NumStrings(); string_idx++) {
807 class_linker->ResolveString(dex_file, string_idx, dex_cache);
808 }
Elliott Hughesff738062012-02-03 15:00:42 -0800809 timings.AddSplit("Resolve " + dex_file.GetLocation() + " Strings");
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700810 }
811
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800812 Context context;
813 context.class_linker = class_linker;
814 context.class_loader = class_loader;
815 context.dex_cache = dex_cache;
816 context.dex_file = &dex_file;
817
Elliott Hughes5523ee02012-02-03 18:18:34 -0800818 ForAll(&context, 0, dex_cache->NumResolvedTypes(), ResolveType, thread_count_);
Elliott Hughesff738062012-02-03 15:00:42 -0800819 timings.AddSplit("Resolve " + dex_file.GetLocation() + " Types");
Brian Carlstrom845490b2011-09-19 15:56:53 -0700820
Elliott Hughes5523ee02012-02-03 18:18:34 -0800821 ForAll(&context, 0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods, thread_count_);
Elliott Hughesff738062012-02-03 15:00:42 -0800822 timings.AddSplit("Resolve " + dex_file.GetLocation() + " MethodsAndFields");
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700823}
824
Brian Carlstromae826982011-11-09 01:33:42 -0800825void Compiler::Verify(const ClassLoader* class_loader,
826 const std::vector<const DexFile*>& dex_files) {
827 for (size_t i = 0; i != dex_files.size(); ++i) {
828 const DexFile* dex_file = dex_files[i];
jeffhao98eacac2011-09-14 16:11:53 -0700829 CHECK(dex_file != NULL);
830 VerifyDexFile(class_loader, *dex_file);
831 }
832}
833
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800834static void VerifyClass(Context* context, size_t class_def_index) {
835 const DexFile::ClassDef& class_def = context->dex_file->GetClassDef(class_def_index);
836 const char* descriptor = context->dex_file->GetClassDescriptor(class_def);
837 Class* klass = context->class_linker->FindClass(descriptor, context->class_loader);
838 if (klass == NULL) {
839 Thread* self = Thread::Current();
840 CHECK(self->IsExceptionPending());
841 self->ClearException();
842 return;
843 }
844 CHECK(klass->IsResolved()) << PrettyClass(klass);
845 context->class_linker->VerifyClass(klass);
846
847 if (klass->IsErroneous()) {
848 // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
849 CHECK(Thread::Current()->IsExceptionPending());
850 Thread::Current()->ClearException();
851 // We want to try verification again at run-time, so move back into the resolved state.
852 klass->SetStatus(Class::kStatusResolved);
853 }
854
855 CHECK(klass->IsVerified() || klass->IsResolved()) << PrettyClass(klass);
856 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
857}
858
jeffhao98eacac2011-09-14 16:11:53 -0700859void Compiler::VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
jeffhaob4df5142011-09-19 20:25:32 -0700860 dex_file.ChangePermissions(PROT_READ | PROT_WRITE);
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700861
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800862 Context context;
863 context.class_linker = Runtime::Current()->GetClassLinker();
864 context.class_loader = class_loader;
865 context.dex_file = &dex_file;
Elliott Hughes5523ee02012-02-03 18:18:34 -0800866 ForAll(&context, 0, dex_file.NumClassDefs(), VerifyClass, thread_count_);
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700867
jeffhaob4df5142011-09-19 20:25:32 -0700868 dex_file.ChangePermissions(PROT_READ);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700869}
870
Brian Carlstromae826982011-11-09 01:33:42 -0800871void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader,
872 const std::vector<const DexFile*>& dex_files) {
873 for (size_t i = 0; i != dex_files.size(); ++i) {
874 const DexFile* dex_file = dex_files[i];
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700875 CHECK(dex_file != NULL);
876 InitializeClassesWithoutClinit(class_loader, *dex_file);
877 }
878}
879
880void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, const DexFile& dex_file) {
881 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700882 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
883 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700884 const char* descriptor = dex_file.GetClassDescriptor(class_def);
885 Class* klass = class_linker->FindClass(descriptor, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700886 if (klass != NULL) {
887 class_linker->EnsureInitialized(klass, false);
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800888 // record the final class status if necessary
889 Class::Status status = klass->GetStatus();
890 ClassReference ref(&dex_file, class_def_index);
Elliott Hughesc225caa2012-02-03 15:43:37 -0800891 MutexLock mu(compiled_classes_lock_);
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800892 CompiledClass* compiled_class = GetCompiledClass(ref);
893 if (compiled_class == NULL) {
894 compiled_class = new CompiledClass(status);
895 compiled_classes_[ref] = compiled_class;
896 } else {
897 DCHECK_EQ(status, compiled_class->GetStatus());
898 }
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700899 }
900 // clear any class not found or verification exceptions
901 Thread::Current()->ClearException();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700902 }
903
904 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
905 for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
906 Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700907 if (klass == NULL) {
908 Thread::Current()->ClearException();
909 } else if (klass->IsInitialized()) {
Brian Carlstromffca45d2011-09-16 12:10:49 -0700910 dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
911 }
jeffhao98eacac2011-09-14 16:11:53 -0700912 }
913}
914
Brian Carlstromae826982011-11-09 01:33:42 -0800915void Compiler::Compile(const ClassLoader* class_loader,
916 const std::vector<const DexFile*>& dex_files) {
917 for (size_t i = 0; i != dex_files.size(); ++i) {
918 const DexFile* dex_file = dex_files[i];
Brian Carlstrom83db7722011-08-26 17:32:56 -0700919 CHECK(dex_file != NULL);
920 CompileDexFile(class_loader, *dex_file);
921 }
922}
923
Elliott Hughesc225caa2012-02-03 15:43:37 -0800924void Compiler::CompileClass(Context* context, size_t class_def_index) {
925 const ClassLoader* class_loader = context->class_loader;
926 const DexFile& dex_file = *context->dex_file;
927 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800928 if (SkipClass(class_loader, dex_file, class_def)) {
929 return;
930 }
jeffhaod1224c72012-02-29 13:43:08 -0800931 ClassReference ref(&dex_file, class_def_index);
932 // Skip compiling classes with generic verifier failures since they will still fail at runtime
933 if (verifier::DexVerifier::IsClassRejected(ref)) {
934 return;
935 }
Ian Rogers0571d352011-11-03 19:51:38 -0700936 const byte* class_data = dex_file.GetClassData(class_def);
937 if (class_data == NULL) {
938 // empty class, probably a marker interface
939 return;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700940 }
Ian Rogers0571d352011-11-03 19:51:38 -0700941 ClassDataItemIterator it(dex_file, class_data);
942 // Skip fields
943 while (it.HasNextStaticField()) {
944 it.Next();
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700945 }
Ian Rogers0571d352011-11-03 19:51:38 -0700946 while (it.HasNextInstanceField()) {
947 it.Next();
948 }
949 // Compile direct methods
950 while (it.HasNextDirectMethod()) {
Elliott Hughesc225caa2012-02-03 15:43:37 -0800951 context->compiler->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
952 it.GetMemberIndex(), class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700953 it.Next();
954 }
955 // Compile virtual methods
956 while (it.HasNextVirtualMethod()) {
Elliott Hughesc225caa2012-02-03 15:43:37 -0800957 context->compiler->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
958 it.GetMemberIndex(), class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700959 it.Next();
960 }
961 DCHECK(!it.HasNext());
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700962}
963
Elliott Hughesc225caa2012-02-03 15:43:37 -0800964void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
965 Context context;
966 context.class_loader = class_loader;
967 context.compiler = this;
968 context.dex_file = &dex_file;
Elliott Hughes5523ee02012-02-03 18:18:34 -0800969 ForAll(&context, 0, dex_file.NumClassDefs(), Compiler::CompileClass, thread_count_);
Elliott Hughesc225caa2012-02-03 15:43:37 -0800970}
971
Ian Rogersa3760aa2011-11-14 14:32:37 -0800972void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
973 uint32_t method_idx, const ClassLoader* class_loader,
974 const DexFile& dex_file) {
Elliott Hughesf09afe82011-10-16 14:24:21 -0700975 CompiledMethod* compiled_method = NULL;
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800976 uint64_t start_ns = NanoTime();
Logan Chien4dd96f52012-02-29 01:26:58 +0800977
978#if defined(ART_USE_LLVM_COMPILER)
979 ClassLinker *class_linker = Runtime::Current()->GetClassLinker();
980 DexCache *dex_cache = class_linker->FindDexCache(dex_file);
981
982 UniquePtr<OatCompilationUnit> oat_compilation_unit(
983 new OatCompilationUnit(class_loader, class_linker, dex_file, *dex_cache, code_item,
984 method_idx, access_flags));
985#endif
986
Ian Rogers169c9a72011-11-13 20:13:17 -0800987 if ((access_flags & kAccNative) != 0) {
988 compiled_method = jni_compiler_.Compile(access_flags, method_idx, class_loader, dex_file);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700989 CHECK(compiled_method != NULL);
Ian Rogers169c9a72011-11-13 20:13:17 -0800990 } else if ((access_flags & kAccAbstract) != 0) {
Brian Carlstrom2cc022b2011-08-25 10:05:39 -0700991 } else {
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800992#if defined(ART_USE_LLVM_COMPILER)
Logan Chien4dd96f52012-02-29 01:26:58 +0800993 compiled_method = compiler_llvm_->CompileDexMethod(oat_compilation_unit.get());
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800994#else
Ian Rogersa3760aa2011-11-14 14:32:37 -0800995 compiled_method = oatCompileMethod(*this, code_item, access_flags, method_idx, class_loader,
996 dex_file, kThumb2);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800997#endif
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800998 CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
999 }
Ian Rogers3bb17a62012-01-27 23:56:44 -08001000 uint64_t duration_ns = NanoTime() - start_ns;
buzbee5abfa3e2012-01-31 17:01:43 -08001001 if (duration_ns > MsToNs(100)) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -08001002 LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
Ian Rogers3bb17a62012-01-27 23:56:44 -08001003 << " took " << PrettyDuration(duration_ns);
Elliott Hughesf09afe82011-10-16 14:24:21 -07001004 }
1005
1006 if (compiled_method != NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -07001007 MethodReference ref(&dex_file, method_idx);
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001008 CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file);
Elliott Hughesc225caa2012-02-03 15:43:37 -08001009 MutexLock mu(compiled_methods_lock_);
Ian Rogers0571d352011-11-03 19:51:38 -07001010 compiled_methods_[ref] = compiled_method;
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001011 DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file);
Brian Carlstrom2cc022b2011-08-25 10:05:39 -07001012 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -07001013
Ian Rogers45619fc2012-02-29 11:15:25 -08001014 uint32_t shorty_len;
1015 const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx), &shorty_len);
Ian Rogers169c9a72011-11-13 20:13:17 -08001016 bool is_static = (access_flags & kAccStatic) != 0;
Ian Rogers0571d352011-11-03 19:51:38 -07001017 const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
1018 if (compiled_invoke_stub == NULL) {
Logan Chienf04364f2012-02-10 12:01:39 +08001019#if defined(ART_USE_LLVM_COMPILER)
1020 compiled_invoke_stub = compiler_llvm_->CreateInvokeStub(is_static, shorty);
1021#else
Ian Rogers0571d352011-11-03 19:51:38 -07001022 if (instruction_set_ == kX86) {
Ian Rogers45619fc2012-02-29 11:15:25 -08001023 compiled_invoke_stub = ::art::x86::X86CreateInvokeStub(is_static, shorty, shorty_len);
Ian Rogers0571d352011-11-03 19:51:38 -07001024 } else {
1025 CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
1026 // Generates invocation stub using ARM instruction set
Ian Rogers45619fc2012-02-29 11:15:25 -08001027 compiled_invoke_stub = ::art::arm::ArmCreateInvokeStub(is_static, shorty, shorty_len);
Ian Rogers0571d352011-11-03 19:51:38 -07001028 }
Logan Chienf04364f2012-02-10 12:01:39 +08001029#endif
1030
Ian Rogers0571d352011-11-03 19:51:38 -07001031 CHECK(compiled_invoke_stub != NULL);
1032 InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001033 }
Ian Rogers0571d352011-11-03 19:51:38 -07001034 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001035}
1036
Ian Rogers0571d352011-11-03 19:51:38 -07001037static std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
1038 std::string key(shorty);
1039 if (is_static) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -08001040 key += "$"; // Must not be a shorty type character.
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001041 }
Ian Rogers0571d352011-11-03 19:51:38 -07001042 return key;
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001043}
1044
Ian Rogers0571d352011-11-03 19:51:38 -07001045const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
Elliott Hughesc225caa2012-02-03 15:43:37 -08001046 MutexLock mu(compiled_invoke_stubs_lock_);
Elliott Hughes95572412011-12-13 18:14:20 -08001047 const std::string key(MakeInvokeStubKey(is_static, shorty));
Ian Rogers0571d352011-11-03 19:51:38 -07001048 InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001049 if (it == compiled_invoke_stubs_.end()) {
1050 return NULL;
Ian Rogers0571d352011-11-03 19:51:38 -07001051 } else {
1052 DCHECK(it->second != NULL);
1053 return it->second;
1054 }
1055}
1056
1057void Compiler::InsertInvokeStub(bool is_static, const char* shorty,
1058 const CompiledInvokeStub* compiled_invoke_stub) {
Elliott Hughesc225caa2012-02-03 15:43:37 -08001059 MutexLock mu(compiled_invoke_stubs_lock_);
Elliott Hughes95572412011-12-13 18:14:20 -08001060 std::string key(MakeInvokeStubKey(is_static, shorty));
Ian Rogers0571d352011-11-03 19:51:38 -07001061 compiled_invoke_stubs_[key] = compiled_invoke_stub;
1062}
1063
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001064CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const {
Elliott Hughesc225caa2012-02-03 15:43:37 -08001065 MutexLock mu(compiled_classes_lock_);
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001066 ClassTable::const_iterator it = compiled_classes_.find(ref);
1067 if (it == compiled_classes_.end()) {
1068 return NULL;
1069 }
1070 CHECK(it->second != NULL);
1071 return it->second;
1072}
1073
Ian Rogers0571d352011-11-03 19:51:38 -07001074CompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
Elliott Hughesc225caa2012-02-03 15:43:37 -08001075 MutexLock mu(compiled_methods_lock_);
Ian Rogers0571d352011-11-03 19:51:38 -07001076 MethodTable::const_iterator it = compiled_methods_.find(ref);
1077 if (it == compiled_methods_.end()) {
1078 return NULL;
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001079 }
1080 CHECK(it->second != NULL);
1081 return it->second;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -07001082}
1083
Brian Carlstrome7d856b2012-01-11 18:10:55 -08001084void Compiler::SetGcMaps(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files) {
1085 for (size_t i = 0; i != dex_files.size(); ++i) {
1086 const DexFile* dex_file = dex_files[i];
1087 CHECK(dex_file != NULL);
1088 SetGcMapsDexFile(class_loader, *dex_file);
1089 }
1090}
1091
1092void Compiler::SetGcMapsDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
1093 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1094 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
1095 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
1096 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
1097 const char* descriptor = dex_file.GetClassDescriptor(class_def);
1098 Class* klass = class_linker->FindClass(descriptor, class_loader);
1099 if (klass == NULL || !klass->IsVerified()) {
1100 Thread::Current()->ClearException();
1101 continue;
1102 }
1103 const byte* class_data = dex_file.GetClassData(class_def);
1104 if (class_data == NULL) {
1105 // empty class such as a marker interface
1106 continue;
1107 }
1108 ClassDataItemIterator it(dex_file, class_data);
1109 while (it.HasNextStaticField()) {
1110 it.Next();
1111 }
1112 while (it.HasNextInstanceField()) {
1113 it.Next();
1114 }
1115 while (it.HasNextDirectMethod()) {
1116 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1117 class_loader, true);
1118 SetGcMapsMethod(dex_file, method);
1119 it.Next();
1120 }
1121 while (it.HasNextVirtualMethod()) {
1122 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1123 class_loader, false);
1124 SetGcMapsMethod(dex_file, method);
1125 it.Next();
1126 }
1127 }
1128}
1129
1130void Compiler::SetGcMapsMethod(const DexFile& dex_file, Method* method) {
1131 if (method == NULL) {
1132 Thread::Current()->ClearException();
1133 return;
1134 }
1135 uint16_t method_idx = method->GetDexMethodIndex();
1136 MethodReference ref(&dex_file, method_idx);
1137 CompiledMethod* compiled_method = GetCompiledMethod(ref);
1138 if (compiled_method == NULL) {
1139 return;
1140 }
1141 const std::vector<uint8_t>* gc_map = verifier::DexVerifier::GetGcMap(ref);
1142 if (gc_map == NULL) {
1143 return;
1144 }
1145 compiled_method->SetGcMap(*gc_map);
1146}
1147
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -07001148} // namespace art