blob: e2d72f54c61bb6bad765d9499ed104ded2fcf458 [file] [log] [blame]
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "compiler.h"
4
Brian Carlstrom2cc022b2011-08-25 10:05:39 -07005#include "assembler.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -07006#include "class_linker.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -07007#include "class_loader.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -07008#include "dex_cache.h"
Brian Carlstrom2cc022b2011-08-25 10:05:39 -07009#include "jni_compiler.h"
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070010#include "jni_internal.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070011#include "runtime.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070012
13extern bool oatCompileMethod(art::Method*, art::InstructionSet);
14
15namespace art {
16
Brian Carlstrom2cc022b2011-08-25 10:05:39 -070017// TODO need to specify target
Brian Carlstrom8a487412011-08-29 20:08:52 -070018void Compiler::CompileAll(const ClassLoader* class_loader) {
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070019 Resolve(class_loader);
Brian Carlstrom83db7722011-08-26 17:32:56 -070020 // TODO add verification step
21 Compile(class_loader);
Brian Carlstrom9cc262e2011-08-28 12:45:30 -070022 SetCodeAndDirectMethods(class_loader);
Brian Carlstrom8a487412011-08-29 20:08:52 -070023}
24
25void Compiler::CompileOne(Method* method) {
26 const ClassLoader* class_loader = method->GetDeclaringClass()->GetClassLoader();
27 Resolve(class_loader);
28 // TODO add verification step
29 CompileMethod(method);
30 SetCodeAndDirectMethods(class_loader);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070031}
32
33void Compiler::Resolve(const ClassLoader* class_loader) {
Brian Carlstrom8a487412011-08-29 20:08:52 -070034 const std::vector<const DexFile*>& class_path = ClassLoader::GetClassPath(class_loader);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070035 for (size_t i = 0; i != class_path.size(); ++i) {
36 const DexFile* dex_file = class_path[i];
37 CHECK(dex_file != NULL);
38 ResolveDexFile(class_loader, *dex_file);
39 }
40}
41
42void Compiler::ResolveDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
43 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
44
45 // Strings are easy, they always are simply resolved to literals in the same file
46 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
47 for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
48 class_linker->ResolveString(dex_file, i, dex_cache);
49 }
50
51 // Class derived values are more complicated, they require the linker and loader
Brian Carlstrom1caa2c22011-08-28 13:02:33 -070052 for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070053 class_linker->ResolveType(dex_file, i, dex_cache, class_loader);
54 }
Brian Carlstrom1caa2c22011-08-28 13:02:33 -070055 for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
Brian Carlstrom20cfffa2011-08-26 02:31:27 -070056 // unknown if direct or virtual, try both
57 Method* method = class_linker->ResolveMethod(dex_file, i, dex_cache, class_loader, false);
58 if (method == NULL) {
59 class_linker->ResolveMethod(dex_file, i, dex_cache, class_loader, true);
60 }
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070061 }
Brian Carlstrom1caa2c22011-08-28 13:02:33 -070062 for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
Brian Carlstrom20cfffa2011-08-26 02:31:27 -070063 // unknown if instance or static, try both
64 Field* field = class_linker->ResolveField(dex_file, i, dex_cache, class_loader, false);
65 if (field == NULL) {
Elliott Hughes1f1fa562011-08-26 10:22:53 -070066 class_linker->ResolveField(dex_file, i, dex_cache, class_loader, true);
Brian Carlstrom20cfffa2011-08-26 02:31:27 -070067 }
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070068 }
69}
70
Brian Carlstrom83db7722011-08-26 17:32:56 -070071void Compiler::Compile(const ClassLoader* class_loader) {
Brian Carlstrom8a487412011-08-29 20:08:52 -070072 const std::vector<const DexFile*>& class_path = ClassLoader::GetClassPath(class_loader);
Brian Carlstrom83db7722011-08-26 17:32:56 -070073 for (size_t i = 0; i != class_path.size(); ++i) {
74 const DexFile* dex_file = class_path[i];
75 CHECK(dex_file != NULL);
76 CompileDexFile(class_loader, *dex_file);
77 }
78}
79
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070080void Compiler::CompileDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
81 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
82 for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
83 const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
84 const char* descriptor = dex_file.GetClassDescriptor(class_def);
85 Class* klass = class_linker->FindClass(descriptor, class_loader);
86 CHECK(klass != NULL);
87 CompileClass(klass);
88 }
89}
90
91void Compiler::CompileClass(Class* klass) {
92 for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
93 CompileMethod(klass->GetDirectMethod(i));
94 }
95 for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
96 CompileMethod(klass->GetVirtualMethod(i));
97 }
98}
99
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700100// This is private API, but with two different implementations: ARM and x86.
101void CreateInvokeStub(Assembler* assembler, Method* method);
102
103namespace {
104
105void CompileInvokeStub(Method* method) {
106 if (method->GetInvokeStub() != NULL) {
107 return;
108 }
109 // TODO: use signature to find a matching stub
110 // TODO: failed, acquire a lock on the stub table
111 Assembler assembler;
112 art::CreateInvokeStub(&assembler, method);
113 // TODO: store native_entry in the stub table
114 ByteArray* code = ByteArray::Alloc(assembler.CodeSize());
115 MemoryRegion region(code->GetData(), code->GetLength());
116 assembler.FinalizeInstructions(region);
117 method->SetInvokeStub(code);
118 CHECK(method->GetInvokeStub() != NULL);
119}
120
121} // namespace
122
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700123void Compiler::CompileMethod(Method* method) {
Brian Carlstrom2cc022b2011-08-25 10:05:39 -0700124 if (method->IsNative()) {
125 Assembler jni_asm;
126 JniCompiler jni_compiler;
127 jni_compiler.Compile(&jni_asm, method);
128 } else if (method->IsAbstract()) {
Brian Carlstrombffb1552011-08-25 12:23:53 -0700129 // TODO: This might be also noted in the ClassLinker.
130 // Probably makes more sense to do here?
131 UNIMPLEMENTED(FATAL) << "compile stub to throw AbstractMethodError";
Brian Carlstrom2cc022b2011-08-25 10:05:39 -0700132 } else {
133 oatCompileMethod(method, kThumb2);
134 }
Brian Carlstrombffb1552011-08-25 12:23:53 -0700135 // CHECK(method->HasCode()); // TODO: enable this check ASAP
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700136
137 CompileInvokeStub(method);
138 CHECK(method->GetInvokeStub() != NULL);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700139}
140
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700141void Compiler::SetCodeAndDirectMethods(const ClassLoader* class_loader) {
Brian Carlstrom8a487412011-08-29 20:08:52 -0700142 const std::vector<const DexFile*>& class_path = ClassLoader::GetClassPath(class_loader);
Brian Carlstrom83db7722011-08-26 17:32:56 -0700143 for (size_t i = 0; i != class_path.size(); ++i) {
144 const DexFile* dex_file = class_path[i];
145 CHECK(dex_file != NULL);
Brian Carlstrom8a487412011-08-29 20:08:52 -0700146 SetCodeAndDirectMethodsDexFile(*dex_file);
Brian Carlstrom83db7722011-08-26 17:32:56 -0700147 }
148}
149
Brian Carlstrom8a487412011-08-29 20:08:52 -0700150void Compiler::SetCodeAndDirectMethodsDexFile(const DexFile& dex_file) {
Brian Carlstrom83db7722011-08-26 17:32:56 -0700151 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
152 DexCache* dex_cache = class_linker->FindDexCache(dex_file);
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700153 CodeAndDirectMethods* code_and_direct_methods = dex_cache->GetCodeAndDirectMethods();
Brian Carlstrom1caa2c22011-08-28 13:02:33 -0700154 for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
Brian Carlstrom83db7722011-08-26 17:32:56 -0700155 Method* method = dex_cache->GetResolvedMethod(i);
Brian Carlstrom9cc262e2011-08-28 12:45:30 -0700156 if (method == NULL) {
157 code_and_direct_methods->SetResolvedDirectMethodTrampoline(i);
158 } else if (method->IsDirect()) {
159 code_and_direct_methods->SetResolvedDirectMethod(i, method);
160 } else {
161 // TODO: we currently leave the entry blank for resolved
162 // non-direct methods. we could put in an error stub.
Brian Carlstrom83db7722011-08-26 17:32:56 -0700163 }
164 }
165}
166
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700167} // namespace art