blob: 98d8facb901f378c470ebbc5b67079c766070ca2 [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),
Ian Rogersfb6adba2012-03-04 21:51:51 -080089 resolved_local_static_fields_(0), resolved_static_fields_(0), unresolved_static_fields_(0),
90 virtual_made_direct_(0) {
Ian Rogersc8b306f2012-02-17 21:34:44 -080091 for (size_t i = 0; i < kMaxInvokeType; i++) {
92 resolved_methods_[i] = 0;
93 unresolved_methods_[i] = 0;
94 }
95 }
96
97 void Dump() {
98 DumpStat(types_in_dex_cache_, types_not_in_dex_cache_, "types known to be in dex cache");
99 DumpStat(strings_in_dex_cache_, strings_not_in_dex_cache_, "strings known to be in dex cache");
100 DumpStat(resolved_types_, unresolved_types_, "types resolved");
101 DumpStat(resolved_instance_fields_, unresolved_instance_fields_, "instance fields resolved");
102 DumpStat(resolved_local_static_fields_ + resolved_static_fields_, unresolved_static_fields_,
103 "static fields resolved");
104 DumpStat(resolved_local_static_fields_, resolved_static_fields_ + unresolved_static_fields_,
105 "static fields local to a class");
106
107 for (size_t i = 0; i < kMaxInvokeType; i++) {
108 std::ostringstream oss;
109 oss << "resolved " << static_cast<InvokeType>(i) << " methods";
110 DumpStat(resolved_methods_[i], unresolved_methods_[i], oss.str().c_str());
111 }
Ian Rogersfb6adba2012-03-04 21:51:51 -0800112 DumpStat(virtual_made_direct_, resolved_methods_[kVirtual] + unresolved_methods_[kVirtual],
113 "made direct from virtual");
Ian Rogersc8b306f2012-02-17 21:34:44 -0800114 }
Ian Rogers996cc582012-02-14 22:23:29 -0800115
116// Allow lossy statistics in non-debug builds
117#ifndef NDEBUG
118#define STATS_LOCK() MutexLock mu(stats_lock_)
119#else
120#define STATS_LOCK()
121#endif
122
Ian Rogersc8b306f2012-02-17 21:34:44 -0800123 void TypeInDexCache() {
124 STATS_LOCK();
125 types_in_dex_cache_++;
Ian Rogers996cc582012-02-14 22:23:29 -0800126 }
Ian Rogers996cc582012-02-14 22:23:29 -0800127
Ian Rogersc8b306f2012-02-17 21:34:44 -0800128 void TypeNotInDexCache() {
129 STATS_LOCK();
130 types_not_in_dex_cache_++;
Ian Rogers996cc582012-02-14 22:23:29 -0800131 }
Ian Rogersc8b306f2012-02-17 21:34:44 -0800132
133 void StringInDexCache() {
134 STATS_LOCK();
135 strings_in_dex_cache_++;
136 }
137
138 void StringNotInDexCache() {
139 STATS_LOCK();
140 strings_not_in_dex_cache_++;
141 }
142
143 void TypeDoesntNeedAccessCheck() {
144 STATS_LOCK();
145 resolved_types_++;
146 }
147
148 void TypeNeedsAccessCheck() {
149 STATS_LOCK();
150 unresolved_types_++;
151 }
152
153 void ResolvedInstanceField() {
154 STATS_LOCK();
155 resolved_instance_fields_++;
156 }
157
158 void UnresolvedInstanceField(){
159 STATS_LOCK();
160 unresolved_instance_fields_++;
161 }
162
163 void ResolvedLocalStaticField() {
164 STATS_LOCK();
165 resolved_local_static_fields_++;
166 }
167
168 void ResolvedStaticField() {
169 STATS_LOCK();
170 resolved_static_fields_++;
171 }
172
173 void UnresolvedStaticField() {
174 STATS_LOCK();
175 unresolved_static_fields_++;
176 }
177
178 void ResolvedMethod(InvokeType type) {
179 DCHECK_LE(type, kMaxInvokeType);
180 STATS_LOCK();
181 resolved_methods_[type]++;
182 }
183
184 void UnresolvedMethod(InvokeType type) {
185 DCHECK_LE(type, kMaxInvokeType);
186 STATS_LOCK();
187 unresolved_methods_[type]++;
188 }
189
Ian Rogersfb6adba2012-03-04 21:51:51 -0800190 void VirtualMadeDirect() {
191 STATS_LOCK();
192 virtual_made_direct_++;
193 }
Ian Rogersc8b306f2012-02-17 21:34:44 -0800194 private:
195 Mutex stats_lock_;
196
197 size_t types_in_dex_cache_;
198 size_t types_not_in_dex_cache_;
199
200 size_t strings_in_dex_cache_;
201 size_t strings_not_in_dex_cache_;
202
203 size_t resolved_types_;
204 size_t unresolved_types_;
205
206 size_t resolved_instance_fields_;
207 size_t unresolved_instance_fields_;
208
209 size_t resolved_local_static_fields_;
210 size_t resolved_static_fields_;
211 size_t unresolved_static_fields_;
212
213 size_t resolved_methods_[kMaxInvokeType + 1];
214 size_t unresolved_methods_[kMaxInvokeType + 1];
Ian Rogersfb6adba2012-03-04 21:51:51 -0800215 size_t virtual_made_direct_;
Ian Rogersc8b306f2012-02-17 21:34:44 -0800216
217 DISALLOW_COPY_AND_ASSIGN(AOTCompilationStats);;
218};
Ian Rogers996cc582012-02-14 22:23:29 -0800219
Elliott Hughes5523ee02012-02-03 18:18:34 -0800220Compiler::Compiler(InstructionSet instruction_set, bool image, size_t thread_count,
Elliott Hughesde6e4cf2012-02-27 14:46:06 -0800221 bool support_debugging, const std::set<std::string>* image_classes)
Brian Carlstromaded5f72011-10-07 17:15:04 -0700222 : instruction_set_(instruction_set),
223 jni_compiler_(instruction_set),
Elliott Hughesc225caa2012-02-03 15:43:37 -0800224 compiled_classes_lock_("compiled classes lock"),
225 compiled_methods_lock_("compiled method lock"),
226 compiled_invoke_stubs_lock_("compiled invoke stubs lock"),
Brian Carlstromaded5f72011-10-07 17:15:04 -0700227 image_(image),
Elliott Hughes5523ee02012-02-03 18:18:34 -0800228 thread_count_(thread_count),
Elliott Hughesde6e4cf2012-02-27 14:46:06 -0800229 support_debugging_(support_debugging),
Ian Rogersc8b306f2012-02-17 21:34:44 -0800230 stats_(new AOTCompilationStats),
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800231 image_classes_(image_classes)
232#if defined(ART_USE_LLVM_COMPILER)
233 ,
234 compiler_llvm_(new compiler_llvm::CompilerLLVM(this, instruction_set))
235#endif
236 {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700237 CHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800238 if (!image_) {
239 CHECK(image_classes_ == NULL);
240 }
Shih-wei Liaoc486c112011-09-13 16:43:52 -0700241}
242
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700243Compiler::~Compiler() {
Elliott Hughesc225caa2012-02-03 15:43:37 -0800244 {
245 MutexLock mu(compiled_classes_lock_);
246 STLDeleteValues(&compiled_classes_);
247 }
248 {
249 MutexLock mu(compiled_methods_lock_);
250 STLDeleteValues(&compiled_methods_);
251 }
252 {
253 MutexLock mu(compiled_invoke_stubs_lock_);
254 STLDeleteValues(&compiled_invoke_stubs_);
Elliott Hughesbb551fa2012-01-25 16:35:29 -0800255 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700256}
257
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700258ByteArray* Compiler::CreateResolutionStub(InstructionSet instruction_set,
259 Runtime::TrampolineType type) {
Ian Rogersad25ac52011-10-04 19:13:33 -0700260 if (instruction_set == kX86) {
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700261 return x86::X86CreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -0700262 } else {
263 CHECK(instruction_set == kArm || instruction_set == kThumb2);
264 // Generates resolution stub using ARM instruction set
Ian Rogers1cb0a1d2011-10-06 15:24:35 -0700265 return arm::ArmCreateResolutionTrampoline(type);
Ian Rogersad25ac52011-10-04 19:13:33 -0700266 }
267}
268
Elliott Hughes8add92d2012-01-18 18:18:43 -0800269ByteArray* Compiler::CreateJniDlsymLookupStub(InstructionSet instruction_set) {
Ian Rogers169c9a72011-11-13 20:13:17 -0800270 switch (instruction_set) {
271 case kArm:
272 case kThumb2:
Elliott Hughes8add92d2012-01-18 18:18:43 -0800273 return arm::CreateJniDlsymLookupStub();
Ian Rogers169c9a72011-11-13 20:13:17 -0800274 case kX86:
Elliott Hughes8add92d2012-01-18 18:18:43 -0800275 return x86::CreateJniDlsymLookupStub();
Ian Rogers169c9a72011-11-13 20:13:17 -0800276 default:
Elliott Hughesba8eee12012-01-24 20:25:24 -0800277 LOG(FATAL) << "Unknown InstructionSet: " << static_cast<int>(instruction_set);
Ian Rogers169c9a72011-11-13 20:13:17 -0800278 return NULL;
279 }
280}
281
Ian Rogersad25ac52011-10-04 19:13:33 -0700282ByteArray* Compiler::CreateAbstractMethodErrorStub(InstructionSet instruction_set) {
283 if (instruction_set == kX86) {
284 return x86::CreateAbstractMethodErrorStub();
285 } else {
286 CHECK(instruction_set == kArm || instruction_set == kThumb2);
287 // Generates resolution stub using ARM instruction set
288 return arm::CreateAbstractMethodErrorStub();
289 }
290}
291
Jesse Wilson254db0f2011-11-16 16:44:11 -0500292void Compiler::CompileAll(const ClassLoader* class_loader,
Brian Carlstromae826982011-11-09 01:33:42 -0800293 const std::vector<const DexFile*>& dex_files) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700294 DCHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800295
Elliott Hughes601a1232012-02-02 17:47:38 -0800296 TimingLogger timings("compiler");
297
298 PreCompile(class_loader, dex_files, timings);
299
Brian Carlstromae826982011-11-09 01:33:42 -0800300 Compile(class_loader, dex_files);
Elliott Hughes601a1232012-02-02 17:47:38 -0800301 timings.AddSplit("Compile");
302
Brian Carlstromae826982011-11-09 01:33:42 -0800303 PostCompile(class_loader, dex_files);
Elliott Hughes601a1232012-02-02 17:47:38 -0800304 timings.AddSplit("PostCompile");
305
306 if (timings.GetTotalNs() > MsToNs(1000)) {
307 timings.Dump();
308 }
Ian Rogers996cc582012-02-14 22:23:29 -0800309
Ian Rogersc8b306f2012-02-17 21:34:44 -0800310 stats_->Dump();
Brian Carlstrom8a487412011-08-29 20:08:52 -0700311}
312
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700313void Compiler::CompileOne(const Method* method) {
Brian Carlstrom25c33252011-09-18 15:58:35 -0700314 DCHECK(!Runtime::Current()->IsStarted());
Brian Carlstromae826982011-11-09 01:33:42 -0800315
Brian Carlstrom8a487412011-08-29 20:08:52 -0700316 const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
Brian Carlstromae826982011-11-09 01:33:42 -0800317
Ian Rogers0571d352011-11-03 19:51:38 -0700318 // Find the dex_file
319 const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
320 const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
Brian Carlstromae826982011-11-09 01:33:42 -0800321 std::vector<const DexFile*> dex_files;
322 dex_files.push_back(&dex_file);
323
Elliott Hughes601a1232012-02-02 17:47:38 -0800324 TimingLogger timings("CompileOne");
325 PreCompile(class_loader, dex_files, timings);
Brian Carlstromae826982011-11-09 01:33:42 -0800326
Ian Rogers0571d352011-11-03 19:51:38 -0700327 uint32_t method_idx = method->GetDexMethodIndex();
Ian Rogersa3760aa2011-11-14 14:32:37 -0800328 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
329 CompileMethod(code_item, method->GetAccessFlags(), method_idx, class_loader, dex_file);
Brian Carlstromae826982011-11-09 01:33:42 -0800330
331 PostCompile(class_loader, dex_files);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700332}
333
Brian Carlstromae826982011-11-09 01:33:42 -0800334void Compiler::Resolve(const ClassLoader* class_loader,
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800335 const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
Brian Carlstromae826982011-11-09 01:33:42 -0800336 for (size_t i = 0; i != dex_files.size(); ++i) {
337 const DexFile* dex_file = dex_files[i];
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700338 CHECK(dex_file != NULL);
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800339 ResolveDexFile(class_loader, *dex_file, timings);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700340 }
341}
342
Brian Carlstromae826982011-11-09 01:33:42 -0800343void Compiler::PreCompile(const ClassLoader* class_loader,
Elliott Hughes601a1232012-02-02 17:47:38 -0800344 const std::vector<const DexFile*>& dex_files, TimingLogger& timings) {
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800345 Resolve(class_loader, dex_files, timings);
Elliott Hughes601a1232012-02-02 17:47:38 -0800346
Brian Carlstromae826982011-11-09 01:33:42 -0800347 Verify(class_loader, dex_files);
Elliott Hughes601a1232012-02-02 17:47:38 -0800348 timings.AddSplit("PreCompile.Verify");
349
Brian Carlstromae826982011-11-09 01:33:42 -0800350 InitializeClassesWithoutClinit(class_loader, dex_files);
Elliott Hughes601a1232012-02-02 17:47:38 -0800351 timings.AddSplit("PreCompile.InitializeClassesWithoutClinit");
Brian Carlstromae826982011-11-09 01:33:42 -0800352}
353
354void Compiler::PostCompile(const ClassLoader* class_loader,
355 const std::vector<const DexFile*>& dex_files) {
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800356 SetGcMaps(class_loader, dex_files);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800357#if defined(ART_USE_LLVM_COMPILER)
Logan Chien7f767612012-03-01 18:54:49 +0800358 compiler_llvm_->MaterializeRemainder();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800359#endif
Brian Carlstromae826982011-11-09 01:33:42 -0800360}
361
362bool Compiler::IsImageClass(const std::string& descriptor) const {
363 if (image_classes_ == NULL) {
364 return true;
365 }
366 return image_classes_->find(descriptor) != image_classes_->end();
367}
368
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800369bool Compiler::CanAssumeTypeIsPresentInDexCache(const DexCache* dex_cache,
Ian Rogers996cc582012-02-14 22:23:29 -0800370 uint32_t type_idx) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800371 if (!IsImage()) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800372 stats_->TypeNotInDexCache();
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800373 return false;
374 }
Ian Rogers1bddec32012-02-04 12:27:34 -0800375 Class* resolved_class = dex_cache->GetResolvedType(type_idx);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800376 if (resolved_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800377 stats_->TypeNotInDexCache();
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800378 return false;
379 }
Ian Rogers996cc582012-02-14 22:23:29 -0800380 bool result = IsImageClass(ClassHelper(resolved_class).GetDescriptor());
381 if (result) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800382 stats_->TypeInDexCache();
Ian Rogers996cc582012-02-14 22:23:29 -0800383 } else {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800384 stats_->TypeNotInDexCache();
Ian Rogers996cc582012-02-14 22:23:29 -0800385 }
386 return result;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800387}
388
Ian Rogers1bddec32012-02-04 12:27:34 -0800389bool Compiler::CanAssumeStringIsPresentInDexCache(const DexCache* dex_cache,
Ian Rogers996cc582012-02-14 22:23:29 -0800390 uint32_t string_idx) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800391 // TODO: Add support for loading strings referenced by image_classes_
392 // See also Compiler::ResolveDexFile
393
394 // The following is a test saying that if we're building the image without a restricted set of
395 // 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 -0800396 bool result = IsImage() && image_classes_ == NULL && dex_cache->GetResolvedString(string_idx) != NULL;
397 if (result) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800398 stats_->StringInDexCache();
Ian Rogers996cc582012-02-14 22:23:29 -0800399 } else {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800400 stats_->StringNotInDexCache();
Ian Rogers996cc582012-02-14 22:23:29 -0800401 }
402 return result;
Ian Rogers1bddec32012-02-04 12:27:34 -0800403}
404
405bool Compiler::CanAccessTypeWithoutChecks(uint32_t referrer_idx, const DexCache* dex_cache,
Ian Rogers996cc582012-02-14 22:23:29 -0800406 const DexFile& dex_file, uint32_t type_idx) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800407 // Get type from dex cache assuming it was populated by the verifier
408 Class* resolved_class = dex_cache->GetResolvedType(type_idx);
409 if (resolved_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800410 stats_->TypeNeedsAccessCheck();
Ian Rogers1bddec32012-02-04 12:27:34 -0800411 return false; // Unknown class needs access checks.
412 }
413 const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
414 Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
415 if (referrer_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800416 stats_->TypeNeedsAccessCheck();
Ian Rogers1bddec32012-02-04 12:27:34 -0800417 return false; // Incomplete referrer knowledge needs access check.
418 }
419 // Perform access check, will return true if access is ok or false if we're going to have to
420 // check this at runtime (for example for class loaders).
Ian Rogers996cc582012-02-14 22:23:29 -0800421 bool result = referrer_class->CanAccess(resolved_class);
422 if (result) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800423 stats_->TypeDoesntNeedAccessCheck();
Ian Rogers996cc582012-02-14 22:23:29 -0800424 } else {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800425 stats_->TypeNeedsAccessCheck();
Ian Rogers996cc582012-02-14 22:23:29 -0800426 }
427 return result;
Ian Rogers1bddec32012-02-04 12:27:34 -0800428}
429
430bool Compiler::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx,
431 const DexCache* dex_cache,
432 const DexFile& dex_file,
Ian Rogers996cc582012-02-14 22:23:29 -0800433 uint32_t type_idx) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800434 // Get type from dex cache assuming it was populated by the verifier.
435 Class* resolved_class = dex_cache->GetResolvedType(type_idx);
436 if (resolved_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800437 stats_->TypeNeedsAccessCheck();
Ian Rogers1bddec32012-02-04 12:27:34 -0800438 return false; // Unknown class needs access checks.
439 }
440 const DexFile::MethodId& method_id = dex_file.GetMethodId(referrer_idx);
441 Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
442 if (referrer_class == NULL) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800443 stats_->TypeNeedsAccessCheck();
Ian Rogers1bddec32012-02-04 12:27:34 -0800444 return false; // Incomplete referrer knowledge needs access check.
445 }
446 // Perform access and instantiable checks, will return true if access is ok or false if we're
447 // going to have to check this at runtime (for example for class loaders).
Ian Rogers996cc582012-02-14 22:23:29 -0800448 bool result = referrer_class->CanAccess(resolved_class) && resolved_class->IsInstantiable();
449 if (result) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800450 stats_->TypeDoesntNeedAccessCheck();
Ian Rogers996cc582012-02-14 22:23:29 -0800451 } else {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800452 stats_->TypeNeedsAccessCheck();
Ian Rogers996cc582012-02-14 22:23:29 -0800453 }
454 return result;
Ian Rogers1bddec32012-02-04 12:27:34 -0800455}
456
Logan Chien4dd96f52012-02-29 01:26:58 +0800457static Class* ComputeReferrerClass(OatCompilationUnit* mUnit) {
458 const DexFile::MethodId& referrer_method_id =
459 mUnit->dex_file_->GetMethodId(mUnit->method_idx_);
460
461 return mUnit->class_linker_->ResolveType(
462 *mUnit->dex_file_, referrer_method_id.class_idx_,
463 mUnit->dex_cache_, mUnit->class_loader_);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800464}
465
Logan Chien4dd96f52012-02-29 01:26:58 +0800466static Field* ComputeReferrerField(OatCompilationUnit* mUnit, uint32_t field_idx) {
467 return mUnit->class_linker_->ResolveField(
468 *mUnit->dex_file_, field_idx, mUnit->dex_cache_,
469 mUnit->class_loader_, false);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800470}
471
Logan Chien4dd96f52012-02-29 01:26:58 +0800472static Method* ComputeReferrerMethod(OatCompilationUnit* mUnit, uint32_t method_idx) {
473 return mUnit->class_linker_->ResolveMethod(
474 *mUnit->dex_file_, method_idx, mUnit->dex_cache_,
475 mUnit->class_loader_, true);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800476}
477
Logan Chien4dd96f52012-02-29 01:26:58 +0800478bool Compiler::ComputeInstanceFieldInfo(uint32_t field_idx, OatCompilationUnit* mUnit,
jeffhao8cd6dda2012-02-22 10:15:34 -0800479 int& field_offset, bool& is_volatile, bool is_put) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800480 // Conservative defaults
481 field_offset = -1;
482 is_volatile = true;
483 // Try to resolve field
Logan Chien4dd96f52012-02-29 01:26:58 +0800484 Field* resolved_field = ComputeReferrerField(mUnit, field_idx);
Ian Rogers1bddec32012-02-04 12:27:34 -0800485 if (resolved_field != NULL) {
Logan Chien4dd96f52012-02-29 01:26:58 +0800486 Class* referrer_class = ComputeReferrerClass(mUnit);
Ian Rogers1bddec32012-02-04 12:27:34 -0800487 // Try to resolve referring class then access check, failure to pass the
488 Class* fields_class = resolved_field->GetDeclaringClass();
jeffhao8cd6dda2012-02-22 10:15:34 -0800489 bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal() &&
490 fields_class != referrer_class;
491 if (referrer_class != NULL && referrer_class->CanAccess(fields_class) &&
492 referrer_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) &&
493 !is_write_to_final_from_wrong_class) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800494 field_offset = resolved_field->GetOffset().Int32Value();
495 is_volatile = resolved_field->IsVolatile();
Ian Rogersc8b306f2012-02-17 21:34:44 -0800496 stats_->ResolvedInstanceField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800497 return true; // Fast path.
498 }
499 }
500 // Clean up any exception left by field/type resolution
501 Thread* thread = Thread::Current();
502 if (thread->IsExceptionPending()) {
503 thread->ClearException();
504 }
Ian Rogersc8b306f2012-02-17 21:34:44 -0800505 stats_->UnresolvedInstanceField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800506 return false; // Incomplete knowledge needs slow path.
507}
508
Logan Chien4dd96f52012-02-29 01:26:58 +0800509bool Compiler::ComputeStaticFieldInfo(uint32_t field_idx, OatCompilationUnit* mUnit,
Ian Rogers1bddec32012-02-04 12:27:34 -0800510 int& field_offset, int& ssb_index,
jeffhao8cd6dda2012-02-22 10:15:34 -0800511 bool& is_referrers_class, bool& is_volatile, bool is_put) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800512 // Conservative defaults
513 field_offset = -1;
514 ssb_index = -1;
515 is_referrers_class = false;
516 is_volatile = true;
517 // Try to resolve field
Logan Chien4dd96f52012-02-29 01:26:58 +0800518 Field* resolved_field = ComputeReferrerField(mUnit, field_idx);
Ian Rogers1bddec32012-02-04 12:27:34 -0800519 if (resolved_field != NULL) {
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800520 DCHECK(resolved_field->IsStatic());
Logan Chien4dd96f52012-02-29 01:26:58 +0800521 Class* referrer_class = ComputeReferrerClass(mUnit);
Ian Rogers1bddec32012-02-04 12:27:34 -0800522 if (referrer_class != NULL) {
jeffhao8cd6dda2012-02-22 10:15:34 -0800523 Class* fields_class = resolved_field->GetDeclaringClass();
524 if (fields_class == referrer_class) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800525 is_referrers_class = true; // implies no worrying about class initialization
526 field_offset = resolved_field->GetOffset().Int32Value();
527 is_volatile = resolved_field->IsVolatile();
Ian Rogersc8b306f2012-02-17 21:34:44 -0800528 stats_->ResolvedLocalStaticField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800529 return true; // fast path
530 } else {
jeffhao8cd6dda2012-02-22 10:15:34 -0800531 bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal();
Ian Rogers1bddec32012-02-04 12:27:34 -0800532 if (referrer_class->CanAccess(fields_class) &&
jeffhao8cd6dda2012-02-22 10:15:34 -0800533 referrer_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) &&
534 !is_write_to_final_from_wrong_class) {
Ian Rogers1bddec32012-02-04 12:27:34 -0800535 // We have the resolved field, we must make it into a ssbIndex for the referrer
536 // in its static storage base (which may fail if it doesn't have a slot for it)
Ian Rogers4103ad22012-02-06 09:18:25 -0800537 // TODO: for images we can elide the static storage base null check
538 // if we know there's a non-null entry in the image
Logan Chien4dd96f52012-02-29 01:26:58 +0800539 if (fields_class->GetDexCache() == mUnit->dex_cache_) {
Ian Rogers4103ad22012-02-06 09:18:25 -0800540 // common case where the dex cache of both the referrer and the field are the same,
541 // no need to search the dex file
542 ssb_index = fields_class->GetDexTypeIndex();
543 field_offset = resolved_field->GetOffset().Int32Value();
544 is_volatile = resolved_field->IsVolatile();
Ian Rogersc8b306f2012-02-17 21:34:44 -0800545 stats_->ResolvedStaticField();
Ian Rogers4103ad22012-02-06 09:18:25 -0800546 return true;
547 }
548 // Search dex file for localized ssb index
Ian Rogers1bddec32012-02-04 12:27:34 -0800549 std::string descriptor(FieldHelper(resolved_field).GetDeclaringClassDescriptor());
550 const DexFile::StringId* string_id =
Logan Chien4dd96f52012-02-29 01:26:58 +0800551 mUnit->dex_file_->FindStringId(descriptor);
Ian Rogers1bddec32012-02-04 12:27:34 -0800552 if (string_id != NULL) {
553 const DexFile::TypeId* type_id =
Logan Chien4dd96f52012-02-29 01:26:58 +0800554 mUnit->dex_file_->FindTypeId(mUnit->dex_file_->GetIndexForStringId(*string_id));
Ian Rogers1bddec32012-02-04 12:27:34 -0800555 if(type_id != NULL) {
556 // medium path, needs check of static storage base being initialized
Logan Chien4dd96f52012-02-29 01:26:58 +0800557 ssb_index = mUnit->dex_file_->GetIndexForTypeId(*type_id);
Ian Rogers1bddec32012-02-04 12:27:34 -0800558 field_offset = resolved_field->GetOffset().Int32Value();
559 is_volatile = resolved_field->IsVolatile();
Ian Rogersc8b306f2012-02-17 21:34:44 -0800560 stats_->ResolvedStaticField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800561 return true;
562 }
563 }
564 }
565 }
566 }
567 }
568 // Clean up any exception left by field/type resolution
569 Thread* thread = Thread::Current();
570 if (thread->IsExceptionPending()) {
571 thread->ClearException();
572 }
Ian Rogersc8b306f2012-02-17 21:34:44 -0800573 stats_->UnresolvedStaticField();
Ian Rogers1bddec32012-02-04 12:27:34 -0800574 return false; // Incomplete knowledge needs slow path.
575}
576
Ian Rogersfb6adba2012-03-04 21:51:51 -0800577bool Compiler::ComputeInvokeInfo(uint32_t method_idx, OatCompilationUnit* mUnit, InvokeType& type,
Ian Rogers996cc582012-02-14 22:23:29 -0800578 int& vtable_idx) {
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800579 vtable_idx = -1;
Logan Chien4dd96f52012-02-29 01:26:58 +0800580 Method* resolved_method = ComputeReferrerMethod(mUnit, method_idx);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800581 if (resolved_method != NULL) {
Logan Chien4dd96f52012-02-29 01:26:58 +0800582 Class* referrer_class = ComputeReferrerClass(mUnit);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800583 if (referrer_class != NULL) {
584 Class* methods_class = resolved_method->GetDeclaringClass();
585 if (!referrer_class->CanAccess(methods_class) ||
586 !referrer_class->CanAccessMember(methods_class,
Ian Rogers996cc582012-02-14 22:23:29 -0800587 resolved_method->GetAccessFlags())) {
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800588 // The referring class can't access the resolved method, this may occur as a result of a
589 // protected method being made public by implementing an interface that re-declares the
590 // method public. Resort to the dex file to determine the correct class for the access check
Logan Chien4dd96f52012-02-29 01:26:58 +0800591 const DexFile& dex_file = mUnit->class_linker_->FindDexFile(referrer_class->GetDexCache());
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800592 methods_class =
Logan Chien4dd96f52012-02-29 01:26:58 +0800593 mUnit->class_linker_->ResolveType(dex_file,
594 dex_file.GetMethodId(method_idx).class_idx_,
595 referrer_class);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800596
597 }
598 if (referrer_class->CanAccess(methods_class) &&
599 referrer_class->CanAccessMember(methods_class,
600 resolved_method->GetAccessFlags())) {
601 vtable_idx = resolved_method->GetMethodIndex();
Ian Rogersfb6adba2012-03-04 21:51:51 -0800602 if (type == kVirtual && (resolved_method->IsFinal() || methods_class->IsFinal())) {
603 stats_->ResolvedMethod(kVirtual);
604 // Sharpen a virtual call into a direct call. The method_idx is into referrer's
605 // dex cache, check that this resolved method is where we expect it.
606 CHECK(referrer_class->GetDexCache()->GetResolvedMethod(method_idx) == resolved_method)
607 << PrettyMethod(resolved_method);
608 type = kDirect;
609 stats_->VirtualMadeDirect();
610 return true;
611 } else if (type != kSuper) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800612 // nothing left to do for static/direct/virtual/interface dispatch
613 stats_->ResolvedMethod(type);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800614 return true;
615 } else {
616 // ensure the vtable index will be correct to dispatch in the vtable of the super class
Ian Rogers996cc582012-02-14 22:23:29 -0800617 if (referrer_class->IsSubClass(methods_class) &&
618 vtable_idx < methods_class->GetVTable()->GetLength()) {
Ian Rogersc8b306f2012-02-17 21:34:44 -0800619 stats_->ResolvedMethod(type);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800620 return true;
621 }
622 }
623 }
624 }
625 }
626 // Clean up any exception left by method/type resolution
627 Thread* thread = Thread::Current();
628 if (thread->IsExceptionPending()) {
629 thread->ClearException();
630 }
Ian Rogersc8b306f2012-02-17 21:34:44 -0800631 stats_->UnresolvedMethod(type);
Ian Rogersa32a6fd2012-02-06 20:18:44 -0800632 return false; // Incomplete knowledge needs slow path.
633}
634
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800635// Return true if the class should be skipped during compilation. We
636// never skip classes in the boot class loader. However, if we have a
637// non-boot class loader and we can resolve the class in the boot
638// class loader, we do skip the class. This happens if an app bundles
639// classes found in the boot classpath. Since at runtime we will
640// select the class from the boot classpath, do not attempt to resolve
641// or compile it now.
642static bool SkipClass(const ClassLoader* class_loader,
643 const DexFile& dex_file,
644 const DexFile::ClassDef& class_def) {
645 if (class_loader == NULL) {
646 return false;
647 }
648 const char* descriptor = dex_file.GetClassDescriptor(class_def);
649 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
650 Class* klass = class_linker->FindClass(descriptor, NULL);
651 if (klass == NULL) {
652 Thread* self = Thread::Current();
653 CHECK(self->IsExceptionPending());
654 self->ClearException();
655 return false;
656 }
657 return true;
658}
659
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800660struct Context {
661 ClassLinker* class_linker;
662 const ClassLoader* class_loader;
Elliott Hughesc225caa2012-02-03 15:43:37 -0800663 Compiler* compiler;
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800664 DexCache* dex_cache;
665 const DexFile* dex_file;
666};
667
668typedef void Callback(Context* context, size_t index);
669
670class WorkerThread {
671 public:
Elliott Hughes1e409252012-02-06 11:21:27 -0800672 WorkerThread(Context* context, size_t begin, size_t end, Callback callback, size_t stripe, bool spawn)
673 : spawn_(spawn), context_(context), begin_(begin), end_(end), callback_(callback), stripe_(stripe) {
674 if (spawn_) {
675 CHECK_PTHREAD_CALL(pthread_create, (&pthread_, NULL, &Go, this), "compiler worker thread");
676 }
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800677 }
678
679 ~WorkerThread() {
Elliott Hughes1e409252012-02-06 11:21:27 -0800680 if (spawn_) {
681 CHECK_PTHREAD_CALL(pthread_join, (pthread_, NULL), "compiler worker shutdown");
682 }
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800683 }
684
685 private:
Elliott Hughes1e409252012-02-06 11:21:27 -0800686 static void* Go(void* arg) {
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800687 WorkerThread* worker = reinterpret_cast<WorkerThread*>(arg);
688 Runtime* runtime = Runtime::Current();
Elliott Hughes1e409252012-02-06 11:21:27 -0800689 if (worker->spawn_) {
690 runtime->AttachCurrentThread("Compiler Worker", true);
691 }
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800692 Thread::Current()->SetState(Thread::kRunnable);
693 worker->Run();
Elliott Hughes1e409252012-02-06 11:21:27 -0800694 if (worker->spawn_) {
695 Thread::Current()->SetState(Thread::kNative);
696 runtime->DetachCurrentThread();
697 }
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800698 return NULL;
699 }
700
Elliott Hughes1e409252012-02-06 11:21:27 -0800701 void Go() {
702 Go(this);
703 }
704
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800705 void Run() {
706 for (size_t i = begin_; i < end_; i += stripe_) {
707 callback_(context_, i);
708 }
709 }
710
711 pthread_t pthread_;
Elliott Hughes1e409252012-02-06 11:21:27 -0800712 bool spawn_;
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800713
714 Context* context_;
715 size_t begin_;
716 size_t end_;
717 Callback* callback_;
718 size_t stripe_;
Elliott Hughes1e409252012-02-06 11:21:27 -0800719
720 friend void ForAll(Context*, size_t, size_t, Callback, size_t);
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800721};
722
Elliott Hughes5523ee02012-02-03 18:18:34 -0800723void ForAll(Context* context, size_t begin, size_t end, Callback callback, size_t thread_count) {
Elliott Hughes1e409252012-02-06 11:21:27 -0800724 CHECK_GT(thread_count, 0U);
Elliott Hughes81d91512012-02-03 16:38:43 -0800725
Elliott Hughes1e409252012-02-06 11:21:27 -0800726 std::vector<WorkerThread*> threads;
Elliott Hughes81d91512012-02-03 16:38:43 -0800727 for (size_t i = 0; i < thread_count; ++i) {
Elliott Hughes1e409252012-02-06 11:21:27 -0800728 threads.push_back(new WorkerThread(context, begin + i, end, callback, thread_count, (i != 0)));
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800729 }
Elliott Hughes1e409252012-02-06 11:21:27 -0800730 threads[0]->Go();
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800731
Elliott Hughes81d91512012-02-03 16:38:43 -0800732 // Switch to kVmWait while we're blocked waiting for the other threads to finish.
733 ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
734 STLDeleteElements(&threads);
735}
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800736
737static void ResolveClassFieldsAndMethods(Context* context, size_t class_def_index) {
738 const DexFile& dex_file = *context->dex_file;
739
740 // Method and Field are the worst. We can't resolve without either
741 // context from the code use (to disambiguate virtual vs direct
742 // method and instance vs static field) or from class
743 // definitions. While the compiler will resolve what it can as it
744 // needs it, here we try to resolve fields and methods used in class
745 // definitions, since many of them many never be referenced by
746 // generated code.
747 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
748 if (SkipClass(context->class_loader, dex_file, class_def)) {
749 return;
750 }
751
752 // Note the class_data pointer advances through the headers,
753 // static fields, instance fields, direct methods, and virtual
754 // methods.
755 const byte* class_data = dex_file.GetClassData(class_def);
756 if (class_data == NULL) {
757 // empty class such as a marker interface
758 return;
759 }
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800760 Thread* self = Thread::Current();
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800761 ClassLinker* class_linker = context->class_linker;
762 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
763 ClassDataItemIterator it(dex_file, class_data);
764 while (it.HasNextStaticField()) {
765 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
766 context->class_loader, true);
767 if (field == NULL) {
768 CHECK(self->IsExceptionPending());
769 self->ClearException();
770 }
771 it.Next();
772 }
773 while (it.HasNextInstanceField()) {
774 Field* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
775 context->class_loader, false);
776 if (field == NULL) {
777 CHECK(self->IsExceptionPending());
778 self->ClearException();
779 }
780 it.Next();
781 }
782 while (it.HasNextDirectMethod()) {
783 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
784 context->class_loader, true);
785 if (method == NULL) {
786 CHECK(self->IsExceptionPending());
787 self->ClearException();
788 }
789 it.Next();
790 }
791 while (it.HasNextVirtualMethod()) {
792 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
793 context->class_loader, false);
794 if (method == NULL) {
795 CHECK(self->IsExceptionPending());
796 self->ClearException();
797 }
798 it.Next();
799 }
800 DCHECK(!it.HasNext());
801}
802
803static void ResolveType(Context* context, size_t type_idx) {
804 // Class derived values are more complicated, they require the linker and loader.
805 Thread* self = Thread::Current();
806 ClassLinker* class_linker = context->class_linker;
807 const DexFile& dex_file = *context->dex_file;
808 Class* klass = class_linker->ResolveType(dex_file, type_idx, context->dex_cache, context->class_loader);
809 if (klass == NULL) {
810 CHECK(self->IsExceptionPending());
811 Thread::Current()->ClearException();
812 }
813}
814
815void Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file, TimingLogger& timings) {
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700816 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromaded5f72011-10-07 17:15:04 -0700817 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700818
Brian Carlstromae826982011-11-09 01:33:42 -0800819 // Strings are easy in that they always are simply resolved to literals in the same file
820 if (image_ && image_classes_ == NULL) {
821 // TODO: Add support for loading strings referenced by image_classes_
822 // See also Compiler::CanAssumeTypeIsPresentInDexCache.
Brian Carlstromaded5f72011-10-07 17:15:04 -0700823 for (size_t string_idx = 0; string_idx < dex_cache->NumStrings(); string_idx++) {
824 class_linker->ResolveString(dex_file, string_idx, dex_cache);
825 }
Elliott Hughesff738062012-02-03 15:00:42 -0800826 timings.AddSplit("Resolve " + dex_file.GetLocation() + " Strings");
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700827 }
828
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800829 Context context;
830 context.class_linker = class_linker;
831 context.class_loader = class_loader;
832 context.dex_cache = dex_cache;
833 context.dex_file = &dex_file;
834
Elliott Hughes5523ee02012-02-03 18:18:34 -0800835 ForAll(&context, 0, dex_cache->NumResolvedTypes(), ResolveType, thread_count_);
Elliott Hughesff738062012-02-03 15:00:42 -0800836 timings.AddSplit("Resolve " + dex_file.GetLocation() + " Types");
Brian Carlstrom845490b2011-09-19 15:56:53 -0700837
Elliott Hughes5523ee02012-02-03 18:18:34 -0800838 ForAll(&context, 0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods, thread_count_);
Elliott Hughesff738062012-02-03 15:00:42 -0800839 timings.AddSplit("Resolve " + dex_file.GetLocation() + " MethodsAndFields");
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700840}
841
Brian Carlstromae826982011-11-09 01:33:42 -0800842void Compiler::Verify(const ClassLoader* class_loader,
843 const std::vector<const DexFile*>& dex_files) {
844 for (size_t i = 0; i != dex_files.size(); ++i) {
845 const DexFile* dex_file = dex_files[i];
jeffhao98eacac2011-09-14 16:11:53 -0700846 CHECK(dex_file != NULL);
847 VerifyDexFile(class_loader, *dex_file);
848 }
849}
850
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800851static void VerifyClass(Context* context, size_t class_def_index) {
852 const DexFile::ClassDef& class_def = context->dex_file->GetClassDef(class_def_index);
853 const char* descriptor = context->dex_file->GetClassDescriptor(class_def);
854 Class* klass = context->class_linker->FindClass(descriptor, context->class_loader);
855 if (klass == NULL) {
856 Thread* self = Thread::Current();
857 CHECK(self->IsExceptionPending());
858 self->ClearException();
859 return;
860 }
861 CHECK(klass->IsResolved()) << PrettyClass(klass);
862 context->class_linker->VerifyClass(klass);
863
864 if (klass->IsErroneous()) {
865 // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
866 CHECK(Thread::Current()->IsExceptionPending());
867 Thread::Current()->ClearException();
868 // We want to try verification again at run-time, so move back into the resolved state.
869 klass->SetStatus(Class::kStatusResolved);
870 }
871
872 CHECK(klass->IsVerified() || klass->IsResolved()) << PrettyClass(klass);
873 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyTypeOf(Thread::Current()->GetException());
874}
875
jeffhao98eacac2011-09-14 16:11:53 -0700876void Compiler::VerifyDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
jeffhaob4df5142011-09-19 20:25:32 -0700877 dex_file.ChangePermissions(PROT_READ | PROT_WRITE);
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700878
Elliott Hughesd9c67be2012-02-02 19:54:06 -0800879 Context context;
880 context.class_linker = Runtime::Current()->GetClassLinker();
881 context.class_loader = class_loader;
882 context.dex_file = &dex_file;
Elliott Hughes5523ee02012-02-03 18:18:34 -0800883 ForAll(&context, 0, dex_file.NumClassDefs(), VerifyClass, thread_count_);
Elliott Hughesd9cdfe92011-10-06 16:09:04 -0700884
jeffhaob4df5142011-09-19 20:25:32 -0700885 dex_file.ChangePermissions(PROT_READ);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700886}
887
Brian Carlstromae826982011-11-09 01:33:42 -0800888void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader,
889 const std::vector<const DexFile*>& dex_files) {
890 for (size_t i = 0; i != dex_files.size(); ++i) {
891 const DexFile* dex_file = dex_files[i];
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700892 CHECK(dex_file != NULL);
893 InitializeClassesWithoutClinit(class_loader, *dex_file);
894 }
895}
896
897void Compiler::InitializeClassesWithoutClinit(const ClassLoader* class_loader, const DexFile& dex_file) {
898 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700899 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
900 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700901 const char* descriptor = dex_file.GetClassDescriptor(class_def);
902 Class* klass = class_linker->FindClass(descriptor, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700903 if (klass != NULL) {
904 class_linker->EnsureInitialized(klass, false);
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800905 // record the final class status if necessary
906 Class::Status status = klass->GetStatus();
907 ClassReference ref(&dex_file, class_def_index);
Elliott Hughesc225caa2012-02-03 15:43:37 -0800908 MutexLock mu(compiled_classes_lock_);
Brian Carlstrom0755ec52012-01-11 15:19:46 -0800909 CompiledClass* compiled_class = GetCompiledClass(ref);
910 if (compiled_class == NULL) {
911 compiled_class = new CompiledClass(status);
912 compiled_classes_[ref] = compiled_class;
913 } else {
914 DCHECK_EQ(status, compiled_class->GetStatus());
915 }
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700916 }
917 // clear any class not found or verification exceptions
918 Thread::Current()->ClearException();
Brian Carlstromffca45d2011-09-16 12:10:49 -0700919 }
920
921 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
922 for (size_t type_idx = 0; type_idx < dex_cache->NumResolvedTypes(); type_idx++) {
923 Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
Brian Carlstrom27ec9612011-09-19 20:20:38 -0700924 if (klass == NULL) {
925 Thread::Current()->ClearException();
926 } else if (klass->IsInitialized()) {
Brian Carlstromffca45d2011-09-16 12:10:49 -0700927 dex_cache->GetInitializedStaticStorage()->Set(type_idx, klass);
928 }
jeffhao98eacac2011-09-14 16:11:53 -0700929 }
930}
931
Brian Carlstromae826982011-11-09 01:33:42 -0800932void Compiler::Compile(const ClassLoader* class_loader,
933 const std::vector<const DexFile*>& dex_files) {
934 for (size_t i = 0; i != dex_files.size(); ++i) {
935 const DexFile* dex_file = dex_files[i];
Brian Carlstrom83db7722011-08-26 17:32:56 -0700936 CHECK(dex_file != NULL);
937 CompileDexFile(class_loader, *dex_file);
938 }
939}
940
Elliott Hughesc225caa2012-02-03 15:43:37 -0800941void Compiler::CompileClass(Context* context, size_t class_def_index) {
942 const ClassLoader* class_loader = context->class_loader;
943 const DexFile& dex_file = *context->dex_file;
944 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
Logan Chien7f767612012-03-01 18:54:49 +0800945
946#if defined(ART_USE_LLVM_COMPILER)
947 compiler_llvm::CompilerLLVM* compiler_llvm = context->compiler->GetCompilerLLVM();
948
949 MutexLock GUARD(compiler_llvm->compiler_lock_);
950 // TODO: Remove this. We should not lock the compiler_lock_ in CompileClass()
951 // However, without this mutex lock, we will get segmentation fault.
952#endif
953
Brian Carlstrom5ead0952011-11-28 22:55:52 -0800954 if (SkipClass(class_loader, dex_file, class_def)) {
955 return;
956 }
jeffhaod1224c72012-02-29 13:43:08 -0800957 ClassReference ref(&dex_file, class_def_index);
958 // Skip compiling classes with generic verifier failures since they will still fail at runtime
959 if (verifier::DexVerifier::IsClassRejected(ref)) {
960 return;
961 }
Ian Rogers0571d352011-11-03 19:51:38 -0700962 const byte* class_data = dex_file.GetClassData(class_def);
963 if (class_data == NULL) {
964 // empty class, probably a marker interface
965 return;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700966 }
Ian Rogers0571d352011-11-03 19:51:38 -0700967 ClassDataItemIterator it(dex_file, class_data);
968 // Skip fields
969 while (it.HasNextStaticField()) {
970 it.Next();
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700971 }
Ian Rogers0571d352011-11-03 19:51:38 -0700972 while (it.HasNextInstanceField()) {
973 it.Next();
974 }
975 // Compile direct methods
976 while (it.HasNextDirectMethod()) {
Elliott Hughesc225caa2012-02-03 15:43:37 -0800977 context->compiler->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
978 it.GetMemberIndex(), class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700979 it.Next();
980 }
981 // Compile virtual methods
982 while (it.HasNextVirtualMethod()) {
Elliott Hughesc225caa2012-02-03 15:43:37 -0800983 context->compiler->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
984 it.GetMemberIndex(), class_loader, dex_file);
Ian Rogers0571d352011-11-03 19:51:38 -0700985 it.Next();
986 }
987 DCHECK(!it.HasNext());
Logan Chien7f767612012-03-01 18:54:49 +0800988
989#if defined(ART_USE_LLVM_COMPILER)
990 compiler_llvm->MaterializeIfThresholdReached();
991#endif
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700992}
993
Elliott Hughesc225caa2012-02-03 15:43:37 -0800994void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
995 Context context;
996 context.class_loader = class_loader;
997 context.compiler = this;
998 context.dex_file = &dex_file;
Elliott Hughes5523ee02012-02-03 18:18:34 -0800999 ForAll(&context, 0, dex_file.NumClassDefs(), Compiler::CompileClass, thread_count_);
Elliott Hughesc225caa2012-02-03 15:43:37 -08001000}
1001
Ian Rogersa3760aa2011-11-14 14:32:37 -08001002void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
1003 uint32_t method_idx, const ClassLoader* class_loader,
1004 const DexFile& dex_file) {
Elliott Hughesf09afe82011-10-16 14:24:21 -07001005 CompiledMethod* compiled_method = NULL;
Elliott Hughesbb551fa2012-01-25 16:35:29 -08001006 uint64_t start_ns = NanoTime();
Logan Chien4dd96f52012-02-29 01:26:58 +08001007
1008#if defined(ART_USE_LLVM_COMPILER)
1009 ClassLinker *class_linker = Runtime::Current()->GetClassLinker();
1010 DexCache *dex_cache = class_linker->FindDexCache(dex_file);
1011
Logan Chiendbe72bd2012-03-01 18:27:33 +08001012 OatCompilationUnit oat_compilation_unit(
1013 class_loader, class_linker, dex_file, *dex_cache, code_item,
1014 method_idx, access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +08001015#endif
1016
Ian Rogers169c9a72011-11-13 20:13:17 -08001017 if ((access_flags & kAccNative) != 0) {
Logan Chien88894ee2012-02-13 16:42:22 +08001018#if defined(ART_USE_LLVM_COMPILER)
Logan Chiendbe72bd2012-03-01 18:27:33 +08001019 compiled_method = compiler_llvm_->CompileNativeMethod(&oat_compilation_unit);
Logan Chien88894ee2012-02-13 16:42:22 +08001020#else
Ian Rogers169c9a72011-11-13 20:13:17 -08001021 compiled_method = jni_compiler_.Compile(access_flags, method_idx, class_loader, dex_file);
Logan Chien88894ee2012-02-13 16:42:22 +08001022#endif
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001023 CHECK(compiled_method != NULL);
Ian Rogers169c9a72011-11-13 20:13:17 -08001024 } else if ((access_flags & kAccAbstract) != 0) {
Brian Carlstrom2cc022b2011-08-25 10:05:39 -07001025 } else {
Shih-wei Liaod1fec812012-02-13 09:51:10 -08001026#if defined(ART_USE_LLVM_COMPILER)
Logan Chiendbe72bd2012-03-01 18:27:33 +08001027 compiled_method = compiler_llvm_->CompileDexMethod(&oat_compilation_unit);
Shih-wei Liaod1fec812012-02-13 09:51:10 -08001028#else
Ian Rogersa3760aa2011-11-14 14:32:37 -08001029 compiled_method = oatCompileMethod(*this, code_item, access_flags, method_idx, class_loader,
1030 dex_file, kThumb2);
Shih-wei Liaod1fec812012-02-13 09:51:10 -08001031#endif
Elliott Hughesbb551fa2012-01-25 16:35:29 -08001032 CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
1033 }
Ian Rogers3bb17a62012-01-27 23:56:44 -08001034 uint64_t duration_ns = NanoTime() - start_ns;
buzbee5abfa3e2012-01-31 17:01:43 -08001035 if (duration_ns > MsToNs(100)) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -08001036 LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
Ian Rogers3bb17a62012-01-27 23:56:44 -08001037 << " took " << PrettyDuration(duration_ns);
Elliott Hughesf09afe82011-10-16 14:24:21 -07001038 }
1039
1040 if (compiled_method != NULL) {
Ian Rogers0571d352011-11-03 19:51:38 -07001041 MethodReference ref(&dex_file, method_idx);
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001042 CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file);
Elliott Hughesc225caa2012-02-03 15:43:37 -08001043 MutexLock mu(compiled_methods_lock_);
Ian Rogers0571d352011-11-03 19:51:38 -07001044 compiled_methods_[ref] = compiled_method;
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001045 DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file);
Brian Carlstrom2cc022b2011-08-25 10:05:39 -07001046 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -07001047
Ian Rogers45619fc2012-02-29 11:15:25 -08001048 uint32_t shorty_len;
1049 const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx), &shorty_len);
Ian Rogers169c9a72011-11-13 20:13:17 -08001050 bool is_static = (access_flags & kAccStatic) != 0;
Ian Rogers0571d352011-11-03 19:51:38 -07001051 const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
1052 if (compiled_invoke_stub == NULL) {
Logan Chienf04364f2012-02-10 12:01:39 +08001053#if defined(ART_USE_LLVM_COMPILER)
1054 compiled_invoke_stub = compiler_llvm_->CreateInvokeStub(is_static, shorty);
1055#else
Ian Rogers0571d352011-11-03 19:51:38 -07001056 if (instruction_set_ == kX86) {
Ian Rogers45619fc2012-02-29 11:15:25 -08001057 compiled_invoke_stub = ::art::x86::X86CreateInvokeStub(is_static, shorty, shorty_len);
Ian Rogers0571d352011-11-03 19:51:38 -07001058 } else {
1059 CHECK(instruction_set_ == kArm || instruction_set_ == kThumb2);
1060 // Generates invocation stub using ARM instruction set
Ian Rogers45619fc2012-02-29 11:15:25 -08001061 compiled_invoke_stub = ::art::arm::ArmCreateInvokeStub(is_static, shorty, shorty_len);
Ian Rogers0571d352011-11-03 19:51:38 -07001062 }
Logan Chienf04364f2012-02-10 12:01:39 +08001063#endif
1064
Ian Rogers0571d352011-11-03 19:51:38 -07001065 CHECK(compiled_invoke_stub != NULL);
1066 InsertInvokeStub(is_static, shorty, compiled_invoke_stub);
Ian Rogers2c8f6532011-09-02 17:16:34 -07001067 }
Ian Rogers0571d352011-11-03 19:51:38 -07001068 CHECK(!Thread::Current()->IsExceptionPending()) << PrettyMethod(method_idx, dex_file);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001069}
1070
Ian Rogers0571d352011-11-03 19:51:38 -07001071static std::string MakeInvokeStubKey(bool is_static, const char* shorty) {
1072 std::string key(shorty);
1073 if (is_static) {
Elliott Hughesbb551fa2012-01-25 16:35:29 -08001074 key += "$"; // Must not be a shorty type character.
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001075 }
Ian Rogers0571d352011-11-03 19:51:38 -07001076 return key;
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001077}
1078
Ian Rogers0571d352011-11-03 19:51:38 -07001079const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* shorty) const {
Elliott Hughesc225caa2012-02-03 15:43:37 -08001080 MutexLock mu(compiled_invoke_stubs_lock_);
Elliott Hughes95572412011-12-13 18:14:20 -08001081 const std::string key(MakeInvokeStubKey(is_static, shorty));
Ian Rogers0571d352011-11-03 19:51:38 -07001082 InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001083 if (it == compiled_invoke_stubs_.end()) {
1084 return NULL;
Ian Rogers0571d352011-11-03 19:51:38 -07001085 } else {
1086 DCHECK(it->second != NULL);
1087 return it->second;
1088 }
1089}
1090
1091void Compiler::InsertInvokeStub(bool is_static, const char* shorty,
1092 const CompiledInvokeStub* compiled_invoke_stub) {
Elliott Hughesc225caa2012-02-03 15:43:37 -08001093 MutexLock mu(compiled_invoke_stubs_lock_);
Elliott Hughes95572412011-12-13 18:14:20 -08001094 std::string key(MakeInvokeStubKey(is_static, shorty));
Ian Rogers0571d352011-11-03 19:51:38 -07001095 compiled_invoke_stubs_[key] = compiled_invoke_stub;
1096}
1097
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001098CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const {
Elliott Hughesc225caa2012-02-03 15:43:37 -08001099 MutexLock mu(compiled_classes_lock_);
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001100 ClassTable::const_iterator it = compiled_classes_.find(ref);
1101 if (it == compiled_classes_.end()) {
1102 return NULL;
1103 }
1104 CHECK(it->second != NULL);
1105 return it->second;
1106}
1107
Ian Rogers0571d352011-11-03 19:51:38 -07001108CompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const {
Elliott Hughesc225caa2012-02-03 15:43:37 -08001109 MutexLock mu(compiled_methods_lock_);
Ian Rogers0571d352011-11-03 19:51:38 -07001110 MethodTable::const_iterator it = compiled_methods_.find(ref);
1111 if (it == compiled_methods_.end()) {
1112 return NULL;
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001113 }
1114 CHECK(it->second != NULL);
1115 return it->second;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -07001116}
1117
Brian Carlstrome7d856b2012-01-11 18:10:55 -08001118void Compiler::SetGcMaps(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files) {
1119 for (size_t i = 0; i != dex_files.size(); ++i) {
1120 const DexFile* dex_file = dex_files[i];
1121 CHECK(dex_file != NULL);
1122 SetGcMapsDexFile(class_loader, *dex_file);
1123 }
1124}
1125
1126void Compiler::SetGcMapsDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
1127 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1128 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
1129 for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
1130 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
1131 const char* descriptor = dex_file.GetClassDescriptor(class_def);
1132 Class* klass = class_linker->FindClass(descriptor, class_loader);
1133 if (klass == NULL || !klass->IsVerified()) {
1134 Thread::Current()->ClearException();
1135 continue;
1136 }
1137 const byte* class_data = dex_file.GetClassData(class_def);
1138 if (class_data == NULL) {
1139 // empty class such as a marker interface
1140 continue;
1141 }
1142 ClassDataItemIterator it(dex_file, class_data);
1143 while (it.HasNextStaticField()) {
1144 it.Next();
1145 }
1146 while (it.HasNextInstanceField()) {
1147 it.Next();
1148 }
1149 while (it.HasNextDirectMethod()) {
1150 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1151 class_loader, true);
1152 SetGcMapsMethod(dex_file, method);
1153 it.Next();
1154 }
1155 while (it.HasNextVirtualMethod()) {
1156 Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
1157 class_loader, false);
1158 SetGcMapsMethod(dex_file, method);
1159 it.Next();
1160 }
1161 }
1162}
1163
1164void Compiler::SetGcMapsMethod(const DexFile& dex_file, Method* method) {
1165 if (method == NULL) {
1166 Thread::Current()->ClearException();
1167 return;
1168 }
1169 uint16_t method_idx = method->GetDexMethodIndex();
1170 MethodReference ref(&dex_file, method_idx);
1171 CompiledMethod* compiled_method = GetCompiledMethod(ref);
1172 if (compiled_method == NULL) {
1173 return;
1174 }
1175 const std::vector<uint8_t>* gc_map = verifier::DexVerifier::GetGcMap(ref);
1176 if (gc_map == NULL) {
1177 return;
1178 }
1179 compiled_method->SetGcMap(*gc_map);
1180}
1181
Logan Chien8b977d32012-02-21 19:14:55 +08001182#if defined(ART_USE_LLVM_COMPILER)
1183void Compiler::SetElfFileName(std::string const& filename) {
1184 compiler_llvm_->SetElfFileName(filename);
1185}
1186
1187void Compiler::SetBitcodeFileName(std::string const& filename) {
1188 compiler_llvm_->SetBitcodeFileName(filename);
1189}
1190#endif
1191
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -07001192} // namespace art