blob: 19f2f93353a107a28e6940f5f4287c4882ec507f [file] [log] [blame]
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2// Author: cshapiro@google.com (Carl Shapiro)
3
4#include "src/class_linker.h"
5
6#include <vector>
7#include <utility>
8
Carl Shapiro5fafe2b2011-07-09 15:34:41 -07009#include "src/casts.h"
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070010#include "src/dex_verifier.h"
Carl Shapiro5fafe2b2011-07-09 15:34:41 -070011#include "src/heap.h"
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070012#include "src/logging.h"
13#include "src/monitor.h"
14#include "src/object.h"
15#include "src/raw_dex_file.h"
16#include "src/scoped_ptr.h"
17#include "src/thread.h"
18#include "src/utils.h"
19
20namespace art {
21
Carl Shapiro61e019d2011-07-14 16:53:09 -070022ClassLinker* ClassLinker::Create() {
23 scoped_ptr<ClassLinker> class_linker(new ClassLinker);
24 class_linker->Init();
25 // TODO: check for failure during initialization
26 return class_linker.release();
27}
28
Carl Shapiro565f5072011-07-10 13:39:43 -070029void ClassLinker::Init() {
Brian Carlstroma0808032011-07-18 00:39:23 -070030 // Allocate and partially initialize the Class, Object, Field, Method classes.
Brian Carlstrom934486c2011-07-12 23:42:50 -070031 // Initialization will be completed when the definitions are loaded.
Brian Carlstroma0808032011-07-18 00:39:23 -070032 java_lang_Class_ = reinterpret_cast<Class*>(Heap::AllocRaw(sizeof(Class), NULL));
Carl Shapiro565f5072011-07-10 13:39:43 -070033 java_lang_Class_->descriptor_ = "Ljava/lang/Class;";
Brian Carlstroma0808032011-07-18 00:39:23 -070034 java_lang_Class_->object_size_ = sizeof(Class);
35 java_lang_Class_->klass_ = java_lang_Class_;
36
37 java_lang_Object_ = AllocClass(NULL);
38 java_lang_Object_->descriptor_ = "Ljava/lang/Object;";
39
40 java_lang_Class_->super_class_ = java_lang_Object_;
41
42 java_lang_ref_Field_ = AllocClass(NULL);
43 java_lang_ref_Field_->descriptor_ = "Ljava/lang/ref/Field;";
44
45 java_lang_ref_Method_ = AllocClass(NULL);
46 java_lang_ref_Method_->descriptor_ = "Ljava/lang/Method;";
Carl Shapiro565f5072011-07-10 13:39:43 -070047
48 // Allocate and initialize the primitive type classes.
49 primitive_byte_ = CreatePrimitiveClass(kTypeByte, "B");
50 primitive_char_ = CreatePrimitiveClass(kTypeChar, "C");
51 primitive_double_ = CreatePrimitiveClass(kTypeDouble, "D");
52 primitive_float_ = CreatePrimitiveClass(kTypeFloat, "F");
53 primitive_int_ = CreatePrimitiveClass(kTypeInt, "I");
54 primitive_long_ = CreatePrimitiveClass(kTypeLong, "J");
55 primitive_short_ = CreatePrimitiveClass(kTypeShort, "S");
56 primitive_boolean_ = CreatePrimitiveClass(kTypeBoolean, "Z");
57 primitive_void_ = CreatePrimitiveClass(kTypeVoid, "V");
Brian Carlstroma0808032011-07-18 00:39:23 -070058
59 char_array_class_ = AllocClass(NULL);
60 char_array_class_->descriptor_ = "[C";
61 char_array_class_->status_ = Class::kStatusInitialized;
62 char_array_class_->component_type_ = primitive_char_;
63 char_array_class_->array_rank_ = 1;
64 char_array_class_->primitive_type_ = Class::kPrimNot;
65 char_array_class_->super_class_ = java_lang_Object_;
66}
67
68Class* ClassLinker::AllocClass(DexFile* dex_file) {
69 Class* klass = reinterpret_cast<Class*>(Heap::AllocObject(java_lang_Class_));
70 klass->dex_file_ = dex_file;
71 return klass;
72}
73
74StaticField* ClassLinker::AllocStaticField() {
75 return reinterpret_cast<StaticField*>(Heap::AllocRaw(sizeof(StaticField), java_lang_ref_Field_));
76}
77
78InstanceField* ClassLinker::AllocInstanceField() {
79 return reinterpret_cast<InstanceField*>(Heap::AllocRaw(sizeof(InstanceField), java_lang_ref_Field_));
80}
81
82Method* ClassLinker::AllocMethod() {
83 return reinterpret_cast<Method*>(Heap::AllocRaw(sizeof(Method), java_lang_ref_Method_));
Carl Shapiro565f5072011-07-10 13:39:43 -070084}
85
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070086Class* ClassLinker::FindClass(const char* descriptor,
87 Object* class_loader,
88 DexFile* dex_file) {
Carl Shapirob5573532011-07-12 18:22:59 -070089 Thread* self = Thread::Current();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070090 CHECK(!self->IsExceptionPending());
91 // Find the class in the loaded classes table.
92 Class* klass = LookupClass(descriptor, class_loader);
93 if (klass == NULL) {
94 // Class is not yet loaded.
Brian Carlstroma0808032011-07-18 00:39:23 -070095 const RawDexFile::ClassDef* class_def;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070096 if (dex_file == NULL) {
97 // No .dex file specified, search the class path.
Brian Carlstroma0808032011-07-18 00:39:23 -070098 ClassPathEntry pair = FindInClassPath(descriptor);
99 if (pair.first == NULL) {
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700100 LG << "Class " << descriptor << " really not found";
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700101 return NULL;
102 }
Brian Carlstroma0808032011-07-18 00:39:23 -0700103 dex_file = pair.first;
104 class_def = pair.second;
105 } else {
106 class_def = dex_file->GetRaw()->FindClassDef(descriptor);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700107 }
108 // Load the class from the dex file.
Brian Carlstrom934486c2011-07-12 23:42:50 -0700109 if (!strcmp(descriptor, "Ljava/lang/Object;")) {
110 klass = java_lang_Object_;
111 klass->dex_file_ = dex_file;
Brian Carlstroma0808032011-07-18 00:39:23 -0700112 klass->object_size_ = sizeof(Object);
113 if (class_def != NULL) {
114 char_array_class_->super_class_idx_ = class_def->class_idx_;
115 }
Brian Carlstrom934486c2011-07-12 23:42:50 -0700116 } else if (!strcmp(descriptor, "Ljava/lang/Class;")) {
Carl Shapiro565f5072011-07-10 13:39:43 -0700117 klass = java_lang_Class_;
Brian Carlstrom934486c2011-07-12 23:42:50 -0700118 klass->dex_file_ = dex_file;
Brian Carlstroma0808032011-07-18 00:39:23 -0700119 klass->object_size_ = sizeof(Class);
120 } else if (!strcmp(descriptor, "Ljava/lang/ref/Field;")) {
121 klass = java_lang_ref_Field_;
122 klass->dex_file_ = dex_file;
123 klass->object_size_ = sizeof(Field);
124 } else if (!strcmp(descriptor, "Ljava/lang/ref/Method;")) {
125 klass = java_lang_ref_Method_;
126 klass->dex_file_ = dex_file;
127 klass->object_size_ = sizeof(Method);
128 } else if (!strcmp(descriptor, "Ljava/lang/String;")) {
129 klass = java_lang_String_;
130 klass->dex_file_ = dex_file;
131 klass->object_size_ = sizeof(String);
Carl Shapiro565f5072011-07-10 13:39:43 -0700132 } else {
Brian Carlstroma0808032011-07-18 00:39:23 -0700133 klass = AllocClass(dex_file);
Carl Shapiro565f5072011-07-10 13:39:43 -0700134 }
Brian Carlstroma0808032011-07-18 00:39:23 -0700135 bool is_loaded;
136 if (class_def == NULL) {
137 is_loaded = false;
138 } else {
139 is_loaded = LoadClass(*class_def, klass);
140 }
Carl Shapiro565f5072011-07-10 13:39:43 -0700141 if (!is_loaded) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700142 // TODO: this occurs only when a dex file is provided.
143 LG << "Class not found"; // TODO: NoClassDefFoundError
144 return NULL;
145 }
146 // Check for a pending exception during load
147 if (self->IsExceptionPending()) {
148 // TODO: free native allocations in klass
149 return NULL;
150 }
151 {
152 ObjectLock lock(klass);
Carl Shapirob5573532011-07-12 18:22:59 -0700153 klass->clinit_thread_id_ = self->GetId();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700154 // Add the newly loaded class to the loaded classes table.
155 bool success = InsertClass(klass);
156 if (!success) {
157 // We may fail to insert if we raced with another thread.
158 klass->clinit_thread_id_ = 0;
159 // TODO: free native allocations in klass
160 klass = LookupClass(descriptor, class_loader);
161 CHECK(klass != NULL);
162 } else {
163 // Link the class.
164 if (!LinkClass(klass)) {
165 // Linking failed.
166 // TODO: CHECK(self->IsExceptionPending());
167 lock.NotifyAll();
168 return NULL;
169 }
170 }
171 }
172 }
173 // Link the class if it has not already been linked.
174 if (!klass->IsLinked() && !klass->IsErroneous()) {
175 ObjectLock lock(klass);
176 // Check for circular dependencies between classes.
Carl Shapirob5573532011-07-12 18:22:59 -0700177 if (!klass->IsLinked() && klass->clinit_thread_id_ == self->GetId()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700178 LG << "Recursive link"; // TODO: ClassCircularityError
179 return NULL;
180 }
181 // Wait for the pending initialization to complete.
182 while (!klass->IsLinked() && !klass->IsErroneous()) {
183 lock.Wait();
184 }
185 }
186 if (klass->IsErroneous()) {
187 LG << "EarlierClassFailure"; // TODO: EarlierClassFailure
188 return NULL;
189 }
190 // Return the loaded class. No exceptions should be pending.
191 CHECK(!self->IsExceptionPending());
192 return klass;
193}
194
Brian Carlstrom934486c2011-07-12 23:42:50 -0700195bool ClassLinker::LoadClass(const char* descriptor, Class* klass) {
196 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
197 const RawDexFile::ClassDef* class_def = raw->FindClassDef(descriptor);
198 if (class_def == NULL) {
199 return false;
200 } else {
201 return LoadClass(*class_def, klass);
202 }
203}
204
205bool ClassLinker::LoadClass(const RawDexFile::ClassDef& class_def, Class* klass) {
206 CHECK(klass != NULL);
207 CHECK(klass->dex_file_ != NULL);
208 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
209 const byte* class_data = raw->GetClassData(class_def);
210 RawDexFile::ClassDataHeader header = raw->ReadClassDataHeader(&class_data);
211
212 const char* descriptor = raw->GetClassDescriptor(class_def);
213 CHECK(descriptor != NULL);
214
215 klass->klass_ = java_lang_Class_;
216 klass->descriptor_.set(descriptor);
217 klass->descriptor_alloc_ = NULL;
218 klass->access_flags_ = class_def.access_flags_;
219 klass->class_loader_ = NULL; // TODO
220 klass->primitive_type_ = Class::kPrimNot;
221 klass->status_ = Class::kStatusIdx;
222
223 klass->super_class_ = NULL;
224 klass->super_class_idx_ = class_def.superclass_idx_;
225
226 klass->num_sfields_ = header.static_fields_size_;
227 klass->num_ifields_ = header.instance_fields_size_;
228 klass->num_direct_methods_ = header.direct_methods_size_;
229 klass->num_virtual_methods_ = header.virtual_methods_size_;
230
231 klass->source_file_ = raw->dexGetSourceFile(class_def);
232
233 // Load class interfaces.
234 LoadInterfaces(class_def, klass);
235
236 // Load static fields.
237 if (klass->num_sfields_ != 0) {
238 // TODO: allocate on the object heap.
Brian Carlstroma7f4f482011-07-17 17:01:34 -0700239 klass->sfields_ = new StaticField*[klass->NumStaticFields()]();
Brian Carlstrom934486c2011-07-12 23:42:50 -0700240 uint32_t last_idx = 0;
241 for (size_t i = 0; i < klass->num_sfields_; ++i) {
242 RawDexFile::Field raw_field;
243 raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
Brian Carlstroma0808032011-07-18 00:39:23 -0700244 StaticField* sfield = AllocStaticField();
Brian Carlstroma7f4f482011-07-17 17:01:34 -0700245 klass->sfields_[i] = sfield;
246 LoadField(klass, raw_field, sfield);
Brian Carlstrom934486c2011-07-12 23:42:50 -0700247 }
248 }
249
250 // Load instance fields.
251 if (klass->NumInstanceFields() != 0) {
252 // TODO: allocate on the object heap.
Brian Carlstroma7f4f482011-07-17 17:01:34 -0700253 klass->ifields_ = new InstanceField*[klass->NumInstanceFields()]();
Brian Carlstrom934486c2011-07-12 23:42:50 -0700254 uint32_t last_idx = 0;
255 for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
256 RawDexFile::Field raw_field;
257 raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
Brian Carlstroma0808032011-07-18 00:39:23 -0700258 InstanceField* ifield = AllocInstanceField();
Brian Carlstroma7f4f482011-07-17 17:01:34 -0700259 klass->ifields_[i] = ifield;
260 LoadField(klass, raw_field, ifield);
Brian Carlstrom934486c2011-07-12 23:42:50 -0700261 }
262 }
263
264 // Load direct methods.
265 if (klass->NumDirectMethods() != 0) {
266 // TODO: append direct methods to class object
Brian Carlstroma7f4f482011-07-17 17:01:34 -0700267 klass->direct_methods_ = new Method*[klass->NumDirectMethods()]();
Brian Carlstrom934486c2011-07-12 23:42:50 -0700268 uint32_t last_idx = 0;
269 for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
270 RawDexFile::Method raw_method;
271 raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
Brian Carlstroma0808032011-07-18 00:39:23 -0700272 Method* meth = AllocMethod();
Brian Carlstroma7f4f482011-07-17 17:01:34 -0700273 klass->direct_methods_[i] = meth;
274 LoadMethod(klass, raw_method, meth);
Brian Carlstrom934486c2011-07-12 23:42:50 -0700275 // TODO: register maps
276 }
277 }
278
279 // Load virtual methods.
280 if (klass->NumVirtualMethods() != 0) {
281 // TODO: append virtual methods to class object
Brian Carlstroma7f4f482011-07-17 17:01:34 -0700282 klass->virtual_methods_ = new Method*[klass->NumVirtualMethods()]();
Brian Carlstrom934486c2011-07-12 23:42:50 -0700283 uint32_t last_idx = 0;
284 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
285 RawDexFile::Method raw_method;
286 raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
Brian Carlstroma0808032011-07-18 00:39:23 -0700287 Method* meth = AllocMethod();
Brian Carlstroma7f4f482011-07-17 17:01:34 -0700288 klass->virtual_methods_[i] = meth;
289 LoadMethod(klass, raw_method, meth);
Brian Carlstrom934486c2011-07-12 23:42:50 -0700290 // TODO: register maps
291 }
292 }
Brian Carlstroma0808032011-07-18 00:39:23 -0700293 return true;
Brian Carlstrom934486c2011-07-12 23:42:50 -0700294}
295
296void ClassLinker::LoadInterfaces(const RawDexFile::ClassDef& class_def,
297 Class* klass) {
298 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
299 const RawDexFile::TypeList* list = raw->GetInterfacesList(class_def);
300 if (list != NULL) {
301 klass->interface_count_ = list->Size();
302 // TODO: allocate the interfaces array on the object heap.
303 klass->interfaces_ = new Class*[list->Size()]();
304 for (size_t i = 0; i < list->Size(); ++i) {
305 const RawDexFile::TypeItem& type_item = list->GetTypeItem(i);
306 klass->interfaces_[i] = reinterpret_cast<Class*>(type_item.type_idx_);
307 }
308 }
309}
310
311void ClassLinker::LoadField(Class* klass, const RawDexFile::Field& src,
312 Field* dst) {
313 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
314 const RawDexFile::FieldId& field_id = raw->GetFieldId(src.field_idx_);
315 dst->klass_ = klass;
316 dst->name_ = raw->dexStringById(field_id.name_idx_);
317 dst->signature_ = raw->dexStringByTypeIdx(field_id.type_idx_);
318 dst->access_flags_ = src.access_flags_;
319}
320
321void ClassLinker::LoadMethod(Class* klass, const RawDexFile::Method& src,
322 Method* dst) {
323 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
324 const RawDexFile::MethodId& method_id = raw->GetMethodId(src.method_idx_);
325 dst->klass_ = klass;
326 dst->name_.set(raw->dexStringById(method_id.name_idx_));
327 dst->proto_idx_ = method_id.proto_idx_;
328 dst->shorty_.set(raw->GetShorty(method_id.proto_idx_));
329 dst->access_flags_ = src.access_flags_;
330
331 // TODO: check for finalize method
332
333 const RawDexFile::CodeItem* code_item = raw->GetCodeItem(src);
334 if (code_item != NULL) {
335 dst->num_registers_ = code_item->registers_size_;
336 dst->num_ins_ = code_item->ins_size_;
337 dst->num_outs_ = code_item->outs_size_;
338 dst->insns_ = code_item->insns_;
339 } else {
340 uint16_t num_args = dst->NumArgRegisters();
341 if (!dst->IsStatic()) {
342 ++num_args;
343 }
344 dst->num_registers_ = dst->num_ins_ + num_args;
345 // TODO: native methods
346 }
347}
348
Brian Carlstroma0808032011-07-18 00:39:23 -0700349ClassLinker::ClassPathEntry ClassLinker::FindInClassPath(const char* descriptor) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700350 for (size_t i = 0; i != class_path_.size(); ++i) {
351 DexFile* dex_file = class_path_[i];
Brian Carlstroma0808032011-07-18 00:39:23 -0700352 const RawDexFile::ClassDef* class_def = dex_file->GetRaw()->FindClassDef(descriptor);
353 if (class_def != NULL) {
354 return ClassPathEntry(dex_file, class_def);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700355 }
356 }
Brian Carlstroma0808032011-07-18 00:39:23 -0700357 return ClassPathEntry(NULL, NULL);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700358}
359
360void ClassLinker::AppendToClassPath(DexFile* dex_file) {
361 class_path_.push_back(dex_file);
362}
363
Carl Shapiro565f5072011-07-10 13:39:43 -0700364Class* ClassLinker::CreatePrimitiveClass(JType type, const char* descriptor) {
Brian Carlstroma0808032011-07-18 00:39:23 -0700365 Class* klass = AllocClass(NULL);
Carl Shapiro565f5072011-07-10 13:39:43 -0700366 CHECK(klass != NULL);
Brian Carlstroma0808032011-07-18 00:39:23 -0700367 klass->super_class_ = NULL;
Carl Shapiro565f5072011-07-10 13:39:43 -0700368 klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract;
369 klass->descriptor_ = descriptor;
370 klass->status_ = Class::kStatusInitialized;
371 return klass;
372}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700373
Carl Shapiro565f5072011-07-10 13:39:43 -0700374Class* ClassLinker::FindPrimitiveClass(JType type) {
375 switch (type) {
376 case kTypeByte:
377 CHECK(primitive_byte_ != NULL);
378 return primitive_byte_;
379 case kTypeChar:
380 CHECK(primitive_char_ != NULL);
381 return primitive_char_;
382 case kTypeDouble:
383 CHECK(primitive_double_ != NULL);
384 return primitive_double_;
385 case kTypeFloat:
386 CHECK(primitive_float_ != NULL);
387 return primitive_float_;
388 case kTypeInt:
389 CHECK(primitive_int_ != NULL);
390 return primitive_int_;
391 case kTypeLong:
392 CHECK(primitive_long_ != NULL);
393 return primitive_long_;
394 case kTypeShort:
395 CHECK(primitive_short_ != NULL);
396 return primitive_short_;
397 case kTypeBoolean:
398 CHECK(primitive_boolean_ != NULL);
399 return primitive_boolean_;
400 case kTypeVoid:
401 CHECK(primitive_void_ != NULL);
402 return primitive_void_;
403 default:
404 LOG(FATAL) << "Unknown primitive type " << static_cast<int>(type);
405 };
406 return NULL; // Not reachable.
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700407}
408
409bool ClassLinker::InsertClass(Class* klass) {
410 // TODO: acquire classes_lock_
411 const char* key = klass->GetDescriptor().data();
412 bool success = classes_.insert(std::make_pair(key, klass)).second;
413 // TODO: release classes_lock_
414 return success;
415}
416
417Class* ClassLinker::LookupClass(const char* descriptor, Object* class_loader) {
418 // TODO: acquire classes_lock_
419 Table::iterator it = classes_.find(descriptor);
420 // TODO: release classes_lock_
421 if (it == classes_.end()) {
422 return NULL;
423 } else {
424 return (*it).second;
425 }
426}
427
428bool ClassLinker::InitializeClass(Class* klass) {
429 CHECK(klass->GetStatus() == Class::kStatusResolved ||
430 klass->GetStatus() == Class::kStatusError);
431
Carl Shapirob5573532011-07-12 18:22:59 -0700432 Thread* self = Thread::Current();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700433
434 {
435 ObjectLock lock(klass);
436
437 if (klass->GetStatus() < Class::kStatusVerified) {
438 if (klass->IsErroneous()) {
439 LG << "re-initializing failed class"; // TODO: throw
440 return false;
441 }
442
443 CHECK(klass->GetStatus() == Class::kStatusResolved);
444
445 klass->status_ = Class::kStatusVerifying;
446 if (!DexVerify::VerifyClass(klass)) {
447 LG << "Verification failed"; // TODO: ThrowVerifyError
448 Object* exception = self->GetException();
449 klass->SetObjectAt(OFFSETOF_MEMBER(Class, verify_error_class_),
450 exception->GetClass());
451 klass->SetStatus(Class::kStatusError);
452 return false;
453 }
454
455 klass->SetStatus(Class::kStatusVerified);
456 }
457
458 if (klass->status_ == Class::kStatusInitialized) {
459 return true;
460 }
461
462 while (klass->status_ == Class::kStatusInitializing) {
463 // we caught somebody else in the act; was it us?
Carl Shapirob5573532011-07-12 18:22:59 -0700464 if (klass->clinit_thread_id_ == self->GetId()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700465 LG << "recursive <clinit>";
466 return true;
467 }
468
469 CHECK(!self->IsExceptionPending());
470
471 lock.Wait(); // TODO: check for interruption
472
473 // When we wake up, repeat the test for init-in-progress. If
474 // there's an exception pending (only possible if
475 // "interruptShouldThrow" was set), bail out.
476 if (self->IsExceptionPending()) {
477 CHECK(false);
478 LG << "Exception in initialization."; // TODO: ExceptionInInitializerError
479 klass->SetStatus(Class::kStatusError);
480 return false;
481 }
482 if (klass->GetStatus() == Class::kStatusInitializing) {
483 continue;
484 }
485 assert(klass->GetStatus() == Class::kStatusInitialized ||
486 klass->GetStatus() == Class::kStatusError);
487 if (klass->IsErroneous()) {
488 /*
489 * The caller wants an exception, but it was thrown in a
490 * different thread. Synthesize one here.
491 */
492 LG << "<clinit> failed"; // TODO: throw UnsatisfiedLinkError
493 return false;
494 }
495 return true; // otherwise, initialized
496 }
497
498 // see if we failed previously
499 if (klass->IsErroneous()) {
500 // might be wise to unlock before throwing; depends on which class
501 // it is that we have locked
502
503 // TODO: throwEarlierClassFailure(klass);
504 return false;
505 }
506
507 if (!ValidateSuperClassDescriptors(klass)) {
508 klass->SetStatus(Class::kStatusError);
509 return false;
510 }
511
512 assert(klass->status < CLASS_INITIALIZING);
513
Carl Shapirob5573532011-07-12 18:22:59 -0700514 klass->clinit_thread_id_ = self->GetId();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700515 klass->status_ = Class::kStatusInitializing;
516 }
517
518 if (!InitializeSuperClass(klass)) {
519 return false;
520 }
521
522 InitializeStaticFields(klass);
523
524 Method* clinit = klass->FindDirectMethodLocally("<clinit>", "()V");
525 if (clinit != NULL) {
526 } else {
527 // JValue unused;
528 // TODO: dvmCallMethod(self, method, NULL, &unused);
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700529 //CHECK(!"unimplemented");
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700530 }
531
532 {
533 ObjectLock lock(klass);
534
535 if (self->IsExceptionPending()) {
536 klass->SetStatus(Class::kStatusError);
537 } else {
538 klass->SetStatus(Class::kStatusInitialized);
539 }
540 lock.NotifyAll();
541 }
542
543 return true;
544}
545
546bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) {
547 if (klass->IsInterface()) {
548 return true;
549 }
550 // begin with the methods local to the superclass
551 if (klass->HasSuperClass() &&
552 klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
553 const Class* super = klass->GetSuperClass();
554 for (int i = super->NumVirtualMethods() - 1; i >= 0; --i) {
555 const Method* method = klass->GetVirtualMethod(i);
556 if (method != super->GetVirtualMethod(i) &&
557 !HasSameMethodDescriptorClasses(method, super, klass)) {
558 LG << "Classes resolve differently in superclass";
559 return false;
560 }
561 }
562 }
563 for (size_t i = 0; i < klass->iftable_count_; ++i) {
564 const InterfaceEntry* iftable = &klass->iftable_[i];
565 Class* interface = iftable->GetClass();
566 if (klass->GetClassLoader() != interface->GetClassLoader()) {
567 for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
568 uint32_t vtable_index = iftable->method_index_array_[j];
569 const Method* method = klass->GetVirtualMethod(vtable_index);
570 if (!HasSameMethodDescriptorClasses(method, interface,
571 method->GetClass())) {
572 LG << "Classes resolve differently in interface"; // TODO: LinkageError
573 return false;
574 }
575 }
576 }
577 }
578 return true;
579}
580
581bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
Brian Carlstrom934486c2011-07-12 23:42:50 -0700582 const Class* klass1,
583 const Class* klass2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700584 const RawDexFile* raw = method->GetClass()->GetDexFile()->GetRaw();
585 const RawDexFile::ProtoId& proto_id = raw->GetProtoId(method->proto_idx_);
586 RawDexFile::ParameterIterator *it;
587 for (it = raw->GetParameterIterator(proto_id); it->HasNext(); it->Next()) {
588 const char* descriptor = it->GetDescriptor();
589 if (descriptor == NULL) {
590 break;
591 }
592 if (descriptor[0] == 'L' || descriptor[0] == '[') {
593 // Found a non-primitive type.
594 if (!HasSameDescriptorClasses(descriptor, klass1, klass2)) {
595 return false;
596 }
597 }
598 }
599 // Check the return type
600 const char* descriptor = raw->GetReturnTypeDescriptor(proto_id);
601 if (descriptor[0] == 'L' || descriptor[0] == '[') {
602 if (HasSameDescriptorClasses(descriptor, klass1, klass2)) {
603 return false;
604 }
605 }
606 return true;
607}
608
609// Returns true if classes referenced by the descriptor are the
610// same classes in klass1 as they are in klass2.
611bool ClassLinker::HasSameDescriptorClasses(const char* descriptor,
Brian Carlstrom934486c2011-07-12 23:42:50 -0700612 const Class* klass1,
613 const Class* klass2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700614 CHECK(descriptor != NULL);
615 CHECK(klass1 != NULL);
616 CHECK(klass2 != NULL);
617#if 0
618 Class* found1 = FindClassNoInit(descriptor, klass1->GetClassLoader());
619 // TODO: found1 == NULL
620 Class* found2 = FindClassNoInit(descriptor, klass2->GetClassLoader());
621 // TODO: found2 == NULL
622 // TODO: lookup found1 in initiating loader list
623 if (found1 == NULL || found2 == NULL) {
Carl Shapirob5573532011-07-12 18:22:59 -0700624 Thread::Current()->ClearException();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700625 if (found1 == found2) {
626 return true;
627 } else {
628 return false;
629 }
630 }
631#endif
632 return true;
633}
634
635bool ClassLinker::InitializeSuperClass(Class* klass) {
636 CHECK(klass != NULL);
637 // TODO: assert klass lock is acquired
638 if (!klass->IsInterface() && klass->HasSuperClass()) {
639 Class* super_class = klass->GetSuperClass();
640 if (super_class->GetStatus() != Class::kStatusInitialized) {
641 CHECK(!super_class->IsInterface());
642 klass->MonitorExit();
643 bool super_initialized = InitializeClass(super_class);
644 klass->MonitorEnter();
645 // TODO: check for a pending exception
646 if (!super_initialized) {
647 klass->SetStatus(Class::kStatusError);
648 klass->NotifyAll();
649 return false;
650 }
651 }
652 }
653 return true;
654}
655
656void ClassLinker::InitializeStaticFields(Class* klass) {
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700657 size_t num_static_fields = klass->NumStaticFields();
658 if (num_static_fields == 0) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700659 return;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700660 }
661 DexFile* dex_file = klass->GetDexFile();
662 if (dex_file == NULL) {
663 return;
664 }
665 const char* descriptor = klass->GetDescriptor().data();
Brian Carlstrom934486c2011-07-12 23:42:50 -0700666 const RawDexFile* raw = dex_file->GetRaw();
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700667 const RawDexFile::ClassDef* class_def = raw->FindClassDef(descriptor);
668 CHECK(class_def != NULL);
669 const byte* addr = raw->GetEncodedArray(*class_def);
670 size_t array_size = DecodeUnsignedLeb128(&addr);
671 for (size_t i = 0; i < array_size; ++i) {
672 StaticField* field = klass->GetStaticField(i);
673 JValue value;
674 RawDexFile::ValueType type = raw->ReadEncodedValue(&addr, &value);
675 switch (type) {
676 case RawDexFile::kByte:
677 field->SetByte(value.b);
678 break;
679 case RawDexFile::kShort:
680 field->SetShort(value.s);
681 break;
682 case RawDexFile::kChar:
683 field->SetChar(value.c);
684 break;
685 case RawDexFile::kInt:
686 field->SetInt(value.i);
687 break;
688 case RawDexFile::kLong:
689 field->SetLong(value.j);
690 break;
691 case RawDexFile::kFloat:
692 field->SetFloat(value.f);
693 break;
694 case RawDexFile::kDouble:
695 field->SetDouble(value.d);
696 break;
697 case RawDexFile::kString: {
698 uint32_t string_idx = value.i;
699 String* resolved = ResolveString(klass, string_idx);
700 field->SetObject(resolved);
701 break;
702 }
703 case RawDexFile::kBoolean:
704 field->SetBoolean(value.z);
705 break;
706 case RawDexFile::kNull:
707 field->SetObject(value.l);
708 break;
709 default:
Carl Shapiro606258b2011-07-09 16:09:09 -0700710 LOG(FATAL) << "Unknown type " << static_cast<int>(type);
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700711 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700712 }
713}
714
715bool ClassLinker::LinkClass(Class* klass) {
716 CHECK(klass->status_ == Class::kStatusIdx ||
717 klass->status_ == Class::kStatusLoaded);
718 if (klass->status_ == Class::kStatusIdx) {
719 if (!LinkInterfaces(klass)) {
720 return false;
721 }
722 }
723 if (!LinkSuperClass(klass)) {
724 return false;
725 }
726 if (!LinkMethods(klass)) {
727 return false;
728 }
729 if (!LinkInstanceFields(klass)) {
730 return false;
731 }
732 CreateReferenceOffsets(klass);
733 CHECK_EQ(klass->status_, Class::kStatusLoaded);
734 klass->status_ = Class::kStatusResolved;
735 return true;
736}
737
738bool ClassLinker::LinkInterfaces(Class* klass) {
739 scoped_array<uint32_t> interfaces_idx;
740 // TODO: store interfaces_idx in the Class object
741 // TODO: move this outside of link interfaces
742 if (klass->interface_count_ > 0) {
Carl Shapiro565f5072011-07-10 13:39:43 -0700743 size_t length = klass->interface_count_ * sizeof(klass->interfaces_[0]);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700744 interfaces_idx.reset(new uint32_t[klass->interface_count_]);
Carl Shapiro565f5072011-07-10 13:39:43 -0700745 memcpy(interfaces_idx.get(), klass->interfaces_, length);
746 memset(klass->interfaces_, 0xFF, length);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700747 }
748 // Mark the class as loaded.
749 klass->status_ = Class::kStatusLoaded;
750 if (klass->super_class_idx_ != RawDexFile::kDexNoIndex) {
751 Class* super_class = ResolveClass(klass, klass->super_class_idx_);
752 if (super_class == NULL) {
753 LG << "Failed to resolve superclass";
754 return false;
755 }
756 klass->super_class_ = super_class; // TODO: write barrier
757 }
758 if (klass->interface_count_ > 0) {
759 for (size_t i = 0; i < klass->interface_count_; ++i) {
760 uint32_t idx = interfaces_idx[i];
761 klass->interfaces_[i] = ResolveClass(klass, idx);
762 if (klass->interfaces_[i] == NULL) {
763 LG << "Failed to resolve interface";
764 return false;
765 }
766 // Verify
767 if (!klass->CanAccess(klass->interfaces_[i])) {
768 LG << "Inaccessible interface";
769 return false;
770 }
771 }
772 }
773 return true;
774}
775
776bool ClassLinker::LinkSuperClass(Class* klass) {
777 CHECK(!klass->IsPrimitive());
778 const Class* super = klass->GetSuperClass();
779 if (klass->GetDescriptor() == "Ljava/lang/Object;") {
780 if (super != NULL) {
781 LG << "Superclass must not be defined"; // TODO: ClassFormatError
782 return false;
783 }
784 // TODO: clear finalize attribute
785 return true;
786 }
787 if (super == NULL) {
788 LG << "No superclass defined"; // TODO: LinkageError
789 return false;
790 }
791 // Verify
792 if (super->IsFinal()) {
793 LG << "Superclass is declared final"; // TODO: IncompatibleClassChangeError
794 return false;
795 }
796 if (super->IsInterface()) {
797 LG << "Superclass is an interface"; // TODO: IncompatibleClassChangeError
798 return false;
799 }
800 if (!klass->CanAccess(super)) {
801 LG << "Superclass is inaccessible"; // TODO: IllegalAccessError
802 return false;
803 }
804 return true;
805}
806
807// Populate the class vtable and itable.
808bool ClassLinker::LinkMethods(Class* klass) {
809 if (klass->IsInterface()) {
810 // No vtable.
811 size_t count = klass->NumVirtualMethods();
812 if (!IsUint(16, count)) {
813 LG << "Too many methods on interface"; // TODO: VirtualMachineError
814 return false;
815 }
Carl Shapiro565f5072011-07-10 13:39:43 -0700816 for (size_t i = 0; i < count; ++i) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700817 klass->GetVirtualMethod(i)->method_index_ = i;
818 }
819 } else {
820 // Link virtual method tables
821 LinkVirtualMethods(klass);
822
823 // Link interface method tables
824 LinkInterfaceMethods(klass);
825
826 // Insert stubs.
827 LinkAbstractMethods(klass);
828 }
829 return true;
830}
831
832bool ClassLinker::LinkVirtualMethods(Class* klass) {
833 uint32_t max_count = klass->NumVirtualMethods();
834 if (klass->GetSuperClass() != NULL) {
835 max_count += klass->GetSuperClass()->NumVirtualMethods();
836 } else {
837 CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
838 }
839 // TODO: do not assign to the vtable field until it is fully constructed.
840 // TODO: make this a vector<Method*> instead?
841 klass->vtable_ = new Method*[max_count];
842 if (klass->HasSuperClass()) {
843 memcpy(klass->vtable_,
844 klass->GetSuperClass()->vtable_,
845 klass->GetSuperClass()->vtable_count_ * sizeof(Method*));
846 size_t actual_count = klass->GetSuperClass()->vtable_count_;
847 // See if any of our virtual methods override the superclass.
848 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
849 Method* local_method = klass->GetVirtualMethod(i);
850 size_t j = 0;
851 for (; j < klass->GetSuperClass()->vtable_count_; ++j) {
852 const Method* super_method = klass->vtable_[j];
853 if (local_method->HasSameNameAndPrototype(super_method)) {
854 // Verify
855 if (super_method->IsFinal()) {
856 LG << "Method overrides final method"; // TODO: VirtualMachineError
857 return false;
858 }
859 klass->vtable_[j] = local_method;
860 local_method->method_index_ = j;
861 break;
862 }
863 }
864 if (j == klass->GetSuperClass()->vtable_count_) {
865 // Not overriding, append.
866 klass->vtable_[actual_count] = local_method;
867 local_method->method_index_ = actual_count;
868 actual_count += 1;
869 }
870 }
871 if (!IsUint(16, actual_count)) {
872 LG << "Too many methods defined on class"; // TODO: VirtualMachineError
873 return false;
874 }
875 CHECK_LE(actual_count, max_count);
876 if (actual_count < max_count) {
877 Method** new_vtable = new Method*[actual_count];
878 memcpy(new_vtable, klass->vtable_, actual_count * sizeof(Method*));
Carl Shapiro565f5072011-07-10 13:39:43 -0700879 delete[] klass->vtable_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700880 klass->vtable_ = new_vtable;
881 LG << "shrunk vtable: "
882 << "was " << max_count << ", "
883 << "now " << actual_count;
884 }
885 klass->vtable_count_ = actual_count;
886 } else {
887 CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
888 if (!IsUint(16, klass->NumVirtualMethods())) {
889 LG << "Too many methods"; // TODO: VirtualMachineError
890 return false;
891 }
892 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
893 klass->vtable_[i] = klass->GetVirtualMethod(i);
894 klass->GetVirtualMethod(i)->method_index_ = i & 0xFFFF;
895 }
896 klass->vtable_count_ = klass->NumVirtualMethods();
897 }
898 return true;
899}
900
901bool ClassLinker::LinkInterfaceMethods(Class* klass) {
902 int pool_offset = 0;
903 int pool_size = 0;
904 int miranda_count = 0;
905 int miranda_alloc = 0;
906 size_t super_ifcount;
907 if (klass->HasSuperClass()) {
908 super_ifcount = klass->GetSuperClass()->iftable_count_;
909 } else {
910 super_ifcount = 0;
911 }
912 size_t ifCount = super_ifcount;
913 ifCount += klass->interface_count_;
914 for (size_t i = 0; i < klass->interface_count_; i++) {
915 ifCount += klass->interfaces_[i]->iftable_count_;
916 }
917 if (ifCount == 0) {
918 assert(klass->iftable_count_ == 0);
919 assert(klass->iftable == NULL);
920 return true;
921 }
922 klass->iftable_ = new InterfaceEntry[ifCount * sizeof(InterfaceEntry)];
923 memset(klass->iftable_, 0x00, sizeof(InterfaceEntry) * ifCount);
924 if (super_ifcount != 0) {
925 memcpy(klass->iftable_, klass->GetSuperClass()->iftable_,
926 sizeof(InterfaceEntry) * super_ifcount);
927 }
928 // Flatten the interface inheritance hierarchy.
929 size_t idx = super_ifcount;
930 for (size_t i = 0; i < klass->interface_count_; i++) {
931 Class* interf = klass->interfaces_[i];
932 assert(interf != NULL);
933 if (!interf->IsInterface()) {
934 LG << "Class implements non-interface class"; // TODO: IncompatibleClassChangeError
935 return false;
936 }
937 klass->iftable_[idx++].SetClass(interf);
938 for (size_t j = 0; j < interf->iftable_count_; j++) {
939 klass->iftable_[idx++].SetClass(interf->iftable_[j].GetClass());
940 }
941 }
942 CHECK_EQ(idx, ifCount);
943 klass->iftable_count_ = ifCount;
944 if (klass->IsInterface() || super_ifcount == ifCount) {
945 return true;
946 }
947 for (size_t i = super_ifcount; i < ifCount; i++) {
948 pool_size += klass->iftable_[i].GetClass()->NumVirtualMethods();
949 }
950 if (pool_size == 0) {
951 return true;
952 }
953 klass->ifvi_pool_count_ = pool_size;
954 klass->ifvi_pool_ = new uint32_t[pool_size];
955 std::vector<Method*> miranda_list;
956 for (size_t i = super_ifcount; i < ifCount; ++i) {
957 klass->iftable_[i].method_index_array_ = klass->ifvi_pool_ + pool_offset;
958 Class* interface = klass->iftable_[i].GetClass();
959 pool_offset += interface->NumVirtualMethods(); // end here
960 for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
961 Method* interface_method = interface->GetVirtualMethod(j);
962 int k; // must be signed
963 for (k = klass->vtable_count_ - 1; k >= 0; --k) {
964 if (interface_method->HasSameNameAndPrototype(klass->vtable_[k])) {
Carl Shapiro565f5072011-07-10 13:39:43 -0700965 if (!klass->vtable_[k]->IsPublic()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700966 LG << "Implementation not public";
967 return false;
968 }
969 klass->iftable_[i].method_index_array_[j] = k;
970 break;
971 }
972 }
973 if (k < 0) {
974 if (miranda_count == miranda_alloc) {
975 miranda_alloc += 8;
976 if (miranda_list.empty()) {
977 miranda_list.resize(miranda_alloc);
978 } else {
979 miranda_list.resize(miranda_alloc);
980 }
981 }
982 int mir;
983 for (mir = 0; mir < miranda_count; mir++) {
984 if (miranda_list[mir]->HasSameNameAndPrototype(interface_method)) {
985 break;
986 }
987 }
988 // point the interface table at a phantom slot index
989 klass->iftable_[i].method_index_array_[j] = klass->vtable_count_ + mir;
990 if (mir == miranda_count) {
991 miranda_list[miranda_count++] = interface_method;
992 }
993 }
994 }
995 }
996 if (miranda_count != 0) {
Brian Carlstroma7f4f482011-07-17 17:01:34 -0700997 int oldMethodCount = klass->NumVirtualMethods();
998 int newMethodCount = oldMethodCount + miranda_count;
999 Method** newVirtualMethods = new Method*[newMethodCount];
1000 if (klass->virtual_methods_ != NULL) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001001 memcpy(newVirtualMethods,
1002 klass->virtual_methods_,
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001003 klass->NumVirtualMethods() * sizeof(Method*));
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001004 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001005 klass->virtual_methods_ = newVirtualMethods;
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001006 klass->num_virtual_methods_ = newMethodCount;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001007
1008 CHECK(klass->vtable_ != NULL);
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001009 int oldVtableCount = klass->vtable_count_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001010 klass->vtable_count_ += miranda_count;
1011
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001012 for (int i = 0; i < miranda_count; i++) {
Brian Carlstroma0808032011-07-18 00:39:23 -07001013 Method* meth = AllocMethod();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001014 memcpy(meth, miranda_list[i], sizeof(Method));
1015 meth->klass_ = klass;
1016 meth->access_flags_ |= kAccMiranda;
1017 meth->method_index_ = 0xFFFF & (oldVtableCount + i);
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001018 klass->virtual_methods_[oldMethodCount+i] = meth;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001019 klass->vtable_[oldVtableCount + i] = meth;
1020 }
1021 }
1022 return true;
1023}
1024
1025void ClassLinker::LinkAbstractMethods(Class* klass) {
1026 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
1027 Method* method = klass->GetVirtualMethod(i);
1028 if (method->IsAbstract()) {
1029 method->insns_ = reinterpret_cast<uint16_t*>(0xFFFFFFFF); // TODO: AbstractMethodError
1030 }
1031 }
1032}
1033
1034bool ClassLinker::LinkInstanceFields(Class* klass) {
Brian Carlstroma0808032011-07-18 00:39:23 -07001035 int field_offset;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001036 if (klass->GetSuperClass() != NULL) {
Brian Carlstroma0808032011-07-18 00:39:23 -07001037 field_offset = klass->GetSuperClass()->object_size_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001038 } else {
Brian Carlstroma0808032011-07-18 00:39:23 -07001039 field_offset = OFFSETOF_MEMBER(DataObject, fields_);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001040 }
1041 // Move references to the front.
1042 klass->num_reference_ifields_ = 0;
1043 size_t i = 0;
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001044 for ( ; i < klass->NumInstanceFields(); i++) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001045 InstanceField* pField = klass->GetInstanceField(i);
1046 char c = pField->GetType();
1047
1048 if (c != '[' && c != 'L') {
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001049 for (size_t j = klass->NumInstanceFields() - 1; j > i; j--) {
1050 InstanceField* refField = klass->GetInstanceField(j);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001051 char rc = refField->GetType();
1052 if (rc == '[' || rc == 'L') {
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001053 klass->SetInstanceField(i, refField);
1054 klass->SetInstanceField(j, pField);
1055 pField = refField;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001056 c = rc;
1057 klass->num_reference_ifields_++;
1058 break;
1059 }
1060 }
1061 } else {
1062 klass->num_reference_ifields_++;
1063 }
1064 if (c != '[' && c != 'L') {
1065 break;
1066 }
Brian Carlstroma0808032011-07-18 00:39:23 -07001067 pField->SetOffset(field_offset);
1068 field_offset += sizeof(uint32_t);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001069 }
1070
1071 // Now we want to pack all of the double-wide fields together. If
1072 // we're not aligned, though, we want to shuffle one 32-bit field
1073 // into place. If we can't find one, we'll have to pad it.
Brian Carlstroma0808032011-07-18 00:39:23 -07001074 if (i != klass->NumInstanceFields() && (field_offset & 0x04) != 0) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001075 InstanceField* pField = klass->GetInstanceField(i);
1076 char c = pField->GetType();
1077
1078 if (c != 'J' && c != 'D') {
1079 // The field that comes next is 32-bit, so just advance past it.
1080 assert(c != '[' && c != 'L');
Brian Carlstroma0808032011-07-18 00:39:23 -07001081 pField->SetOffset(field_offset);
1082 field_offset += sizeof(uint32_t);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001083 i++;
1084 } else {
1085 // Next field is 64-bit, so search for a 32-bit field we can
1086 // swap into it.
1087 bool found = false;
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001088 for (size_t j = klass->NumInstanceFields() - 1; j > i; j--) {
1089 InstanceField* singleField = klass->GetInstanceField(j);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001090 char rc = singleField->GetType();
1091 if (rc != 'J' && rc != 'D') {
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001092 klass->SetInstanceField(i, singleField);
1093 klass->SetInstanceField(j, pField);
1094 pField = singleField;
Brian Carlstroma0808032011-07-18 00:39:23 -07001095 pField->SetOffset(field_offset);
1096 field_offset += sizeof(uint32_t);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001097 found = true;
1098 i++;
1099 break;
1100 }
1101 }
1102 if (!found) {
Brian Carlstroma0808032011-07-18 00:39:23 -07001103 field_offset += sizeof(uint32_t);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001104 }
1105 }
1106 }
1107
1108 // Alignment is good, shuffle any double-wide fields forward, and
1109 // finish assigning field offsets to all fields.
Brian Carlstroma0808032011-07-18 00:39:23 -07001110 assert(i == klass->NumInstanceFields() || (field_offset & 0x04) == 0);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001111 for ( ; i < klass->NumInstanceFields(); i++) {
1112 InstanceField* pField = klass->GetInstanceField(i);
1113 char c = pField->GetType();
1114 if (c != 'D' && c != 'J') {
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001115 for (size_t j = klass->NumInstanceFields() - 1; j > i; j--) {
1116 InstanceField* doubleField = klass->GetInstanceField(j);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001117 char rc = doubleField->GetType();
1118 if (rc == 'D' || rc == 'J') {
Brian Carlstroma7f4f482011-07-17 17:01:34 -07001119 klass->SetInstanceField(i, doubleField);
1120 klass->SetInstanceField(j, pField);
1121 pField = doubleField;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001122 c = rc;
1123 break;
1124 }
1125 }
1126 } else {
1127 // This is a double-wide field, leave it be.
1128 }
1129
Brian Carlstroma0808032011-07-18 00:39:23 -07001130 pField->SetOffset(field_offset);
1131 field_offset += sizeof(uint32_t);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001132 if (c == 'J' || c == 'D')
Brian Carlstroma0808032011-07-18 00:39:23 -07001133 field_offset += sizeof(uint32_t);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001134 }
1135
1136#ifndef NDEBUG
1137 /* Make sure that all reference fields appear before
1138 * non-reference fields, and all double-wide fields are aligned.
1139 */
1140 j = 0; // seen non-ref
1141 for (i = 0; i < klass->NumInstanceFields(); i++) {
1142 InstanceField *pField = &klass->ifields[i];
1143 char c = pField->GetType();
1144
1145 if (c == 'D' || c == 'J') {
1146 assert((pField->offset_ & 0x07) == 0);
1147 }
1148
1149 if (c != '[' && c != 'L') {
1150 if (!j) {
1151 assert(i == klass->num_reference_ifields_);
1152 j = 1;
1153 }
1154 } else if (j) {
1155 assert(false);
1156 }
1157 }
1158 if (!j) {
1159 assert(klass->num_reference_ifields_ == klass->NumInstanceFields());
1160 }
1161#endif
1162
Brian Carlstroma0808032011-07-18 00:39:23 -07001163 klass->object_size_ = field_offset;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001164 return true;
1165}
1166
1167// Set the bitmap of reference offsets, refOffsets, from the ifields
1168// list.
1169void ClassLinker::CreateReferenceOffsets(Class* klass) {
1170 uint32_t reference_offsets = 0;
1171 if (klass->HasSuperClass()) {
1172 reference_offsets = klass->GetSuperClass()->GetReferenceOffsets();
1173 }
1174 // If our superclass overflowed, we don't stand a chance.
1175 if (reference_offsets != CLASS_WALK_SUPER) {
1176 // All of the fields that contain object references are guaranteed
1177 // to be at the beginning of the ifields list.
1178 for (size_t i = 0; i < klass->NumReferenceInstanceFields(); ++i) {
1179 // Note that, per the comment on struct InstField, f->byteOffset
1180 // is the offset from the beginning of obj, not the offset into
1181 // obj->instanceData.
1182 const InstanceField* field = klass->GetInstanceField(i);
1183 size_t byte_offset = field->GetOffset();
1184 CHECK_GE(byte_offset, CLASS_SMALLEST_OFFSET);
Elliott Hughes1f359b02011-07-17 14:27:17 -07001185 CHECK_EQ(byte_offset & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001186 if (CLASS_CAN_ENCODE_OFFSET(byte_offset)) {
1187 uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset);
Elliott Hughes1f359b02011-07-17 14:27:17 -07001188 CHECK_NE(new_bit, 0U);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001189 reference_offsets |= new_bit;
1190 } else {
1191 reference_offsets = CLASS_WALK_SUPER;
1192 break;
1193 }
1194 }
1195 klass->SetReferenceOffsets(reference_offsets);
1196 }
1197}
1198
Carl Shapiro5fafe2b2011-07-09 15:34:41 -07001199Class* ClassLinker::ResolveClass(const Class* referrer, uint32_t class_idx) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001200 DexFile* dex_file = referrer->GetDexFile();
1201 Class* resolved = dex_file->GetResolvedClass(class_idx);
1202 if (resolved != NULL) {
1203 return resolved;
1204 }
1205 const char* descriptor = dex_file->GetRaw()->dexStringByTypeIdx(class_idx);
1206 if (descriptor[0] != '\0' && descriptor[1] == '\0') {
Carl Shapiro565f5072011-07-10 13:39:43 -07001207 JType type = static_cast<JType>(descriptor[0]);
1208 resolved = FindPrimitiveClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001209 } else {
1210 resolved = FindClass(descriptor, referrer->GetClassLoader(), NULL);
1211 }
1212 if (resolved != NULL) {
1213 Class* check = resolved->IsArray() ? resolved->component_type_ : resolved;
1214 if (referrer->GetDexFile() != check->GetDexFile()) {
1215 if (check->GetClassLoader() != NULL) {
1216 LG << "Class resolved by unexpected DEX"; // TODO: IllegalAccessError
1217 return NULL;
1218 }
1219 }
Carl Shapiro5fafe2b2011-07-09 15:34:41 -07001220 dex_file->SetResolvedClass(resolved, class_idx);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001221 } else {
Carl Shapirob5573532011-07-12 18:22:59 -07001222 CHECK(Thread::Current()->IsExceptionPending());
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001223 }
1224 return resolved;
1225}
1226
1227Method* ResolveMethod(const Class* referrer, uint32_t method_idx,
1228 /*MethodType*/ int method_type) {
1229 CHECK(false);
1230 return NULL;
1231}
1232
Carl Shapiro5fafe2b2011-07-09 15:34:41 -07001233String* ClassLinker::ResolveString(const Class* referring, uint32_t string_idx) {
1234 const RawDexFile* raw = referring->GetDexFile()->GetRaw();
1235 const RawDexFile::StringId& string_id = raw->GetStringId(string_idx);
1236 const char* string_data = raw->GetStringData(string_id);
Brian Carlstroma0808032011-07-18 00:39:23 -07001237 String* new_string = Heap::AllocStringFromModifiedUtf8(java_lang_String_, char_array_class_, string_data);
Carl Shapiro5fafe2b2011-07-09 15:34:41 -07001238 // TODO: intern the new string
1239 referring->GetDexFile()->SetResolvedString(new_string, string_idx);
1240 return new_string;
1241}
1242
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001243} // namespace art