blob: 5b50113c7f20da6c67cdd9c6d16f74fcab26c509 [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 Shapiro565f5072011-07-10 13:39:43 -070022void ClassLinker::Init() {
Brian Carlstrom934486c2011-07-12 23:42:50 -070023 // Allocate and partially initialize the Object and Class classes.
24 // Initialization will be completed when the definitions are loaded.
25 java_lang_Object_ = Heap::AllocClass(NULL);
26 java_lang_Object_->descriptor_ = "Ljava/lang/Object;";
27 java_lang_Class_ = Heap::AllocClass(NULL);
Carl Shapiro565f5072011-07-10 13:39:43 -070028 java_lang_Class_->descriptor_ = "Ljava/lang/Class;";
29
30 // Allocate and initialize the primitive type classes.
31 primitive_byte_ = CreatePrimitiveClass(kTypeByte, "B");
32 primitive_char_ = CreatePrimitiveClass(kTypeChar, "C");
33 primitive_double_ = CreatePrimitiveClass(kTypeDouble, "D");
34 primitive_float_ = CreatePrimitiveClass(kTypeFloat, "F");
35 primitive_int_ = CreatePrimitiveClass(kTypeInt, "I");
36 primitive_long_ = CreatePrimitiveClass(kTypeLong, "J");
37 primitive_short_ = CreatePrimitiveClass(kTypeShort, "S");
38 primitive_boolean_ = CreatePrimitiveClass(kTypeBoolean, "Z");
39 primitive_void_ = CreatePrimitiveClass(kTypeVoid, "V");
40}
41
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070042Class* ClassLinker::FindClass(const char* descriptor,
43 Object* class_loader,
44 DexFile* dex_file) {
Carl Shapirob5573532011-07-12 18:22:59 -070045 Thread* self = Thread::Current();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070046 CHECK(!self->IsExceptionPending());
47 // Find the class in the loaded classes table.
48 Class* klass = LookupClass(descriptor, class_loader);
49 if (klass == NULL) {
50 // Class is not yet loaded.
51 if (dex_file == NULL) {
52 // No .dex file specified, search the class path.
53 dex_file = FindInClassPath(descriptor);
54 if (dex_file == NULL) {
Carl Shapiro5fafe2b2011-07-09 15:34:41 -070055 LG << "Class " << descriptor << " really not found";
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070056 return NULL;
57 }
58 }
59 // Load the class from the dex file.
Brian Carlstrom934486c2011-07-12 23:42:50 -070060 if (!strcmp(descriptor, "Ljava/lang/Object;")) {
61 klass = java_lang_Object_;
62 klass->dex_file_ = dex_file;
63 } else if (!strcmp(descriptor, "Ljava/lang/Class;")) {
Carl Shapiro565f5072011-07-10 13:39:43 -070064 klass = java_lang_Class_;
Brian Carlstrom934486c2011-07-12 23:42:50 -070065 klass->dex_file_ = dex_file;
Carl Shapiro565f5072011-07-10 13:39:43 -070066 } else {
Brian Carlstrom934486c2011-07-12 23:42:50 -070067 klass = Heap::AllocClass(dex_file);
Carl Shapiro565f5072011-07-10 13:39:43 -070068 }
Brian Carlstrom934486c2011-07-12 23:42:50 -070069 bool is_loaded = LoadClass(descriptor, klass);
Carl Shapiro565f5072011-07-10 13:39:43 -070070 if (!is_loaded) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070071 // TODO: this occurs only when a dex file is provided.
72 LG << "Class not found"; // TODO: NoClassDefFoundError
73 return NULL;
74 }
75 // Check for a pending exception during load
76 if (self->IsExceptionPending()) {
77 // TODO: free native allocations in klass
78 return NULL;
79 }
80 {
81 ObjectLock lock(klass);
Carl Shapirob5573532011-07-12 18:22:59 -070082 klass->clinit_thread_id_ = self->GetId();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070083 // Add the newly loaded class to the loaded classes table.
84 bool success = InsertClass(klass);
85 if (!success) {
86 // We may fail to insert if we raced with another thread.
87 klass->clinit_thread_id_ = 0;
88 // TODO: free native allocations in klass
89 klass = LookupClass(descriptor, class_loader);
90 CHECK(klass != NULL);
91 } else {
92 // Link the class.
93 if (!LinkClass(klass)) {
94 // Linking failed.
95 // TODO: CHECK(self->IsExceptionPending());
96 lock.NotifyAll();
97 return NULL;
98 }
99 }
100 }
101 }
102 // Link the class if it has not already been linked.
103 if (!klass->IsLinked() && !klass->IsErroneous()) {
104 ObjectLock lock(klass);
105 // Check for circular dependencies between classes.
Carl Shapirob5573532011-07-12 18:22:59 -0700106 if (!klass->IsLinked() && klass->clinit_thread_id_ == self->GetId()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700107 LG << "Recursive link"; // TODO: ClassCircularityError
108 return NULL;
109 }
110 // Wait for the pending initialization to complete.
111 while (!klass->IsLinked() && !klass->IsErroneous()) {
112 lock.Wait();
113 }
114 }
115 if (klass->IsErroneous()) {
116 LG << "EarlierClassFailure"; // TODO: EarlierClassFailure
117 return NULL;
118 }
119 // Return the loaded class. No exceptions should be pending.
120 CHECK(!self->IsExceptionPending());
121 return klass;
122}
123
Brian Carlstrom934486c2011-07-12 23:42:50 -0700124bool ClassLinker::LoadClass(const char* descriptor, Class* klass) {
125 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
126 const RawDexFile::ClassDef* class_def = raw->FindClassDef(descriptor);
127 if (class_def == NULL) {
128 return false;
129 } else {
130 return LoadClass(*class_def, klass);
131 }
132}
133
134bool ClassLinker::LoadClass(const RawDexFile::ClassDef& class_def, Class* klass) {
135 CHECK(klass != NULL);
136 CHECK(klass->dex_file_ != NULL);
137 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
138 const byte* class_data = raw->GetClassData(class_def);
139 RawDexFile::ClassDataHeader header = raw->ReadClassDataHeader(&class_data);
140
141 const char* descriptor = raw->GetClassDescriptor(class_def);
142 CHECK(descriptor != NULL);
143
144 klass->klass_ = java_lang_Class_;
145 klass->descriptor_.set(descriptor);
146 klass->descriptor_alloc_ = NULL;
147 klass->access_flags_ = class_def.access_flags_;
148 klass->class_loader_ = NULL; // TODO
149 klass->primitive_type_ = Class::kPrimNot;
150 klass->status_ = Class::kStatusIdx;
151
152 klass->super_class_ = NULL;
153 klass->super_class_idx_ = class_def.superclass_idx_;
154
155 klass->num_sfields_ = header.static_fields_size_;
156 klass->num_ifields_ = header.instance_fields_size_;
157 klass->num_direct_methods_ = header.direct_methods_size_;
158 klass->num_virtual_methods_ = header.virtual_methods_size_;
159
160 klass->source_file_ = raw->dexGetSourceFile(class_def);
161
162 // Load class interfaces.
163 LoadInterfaces(class_def, klass);
164
165 // Load static fields.
166 if (klass->num_sfields_ != 0) {
167 // TODO: allocate on the object heap.
168 klass->sfields_ = new StaticField[klass->NumStaticFields()]();
169 uint32_t last_idx = 0;
170 for (size_t i = 0; i < klass->num_sfields_; ++i) {
171 RawDexFile::Field raw_field;
172 raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
173 LoadField(klass, raw_field, &klass->sfields_[i]);
174 }
175 }
176
177 // Load instance fields.
178 if (klass->NumInstanceFields() != 0) {
179 // TODO: allocate on the object heap.
180 klass->ifields_ = new InstanceField[klass->NumInstanceFields()]();
181 uint32_t last_idx = 0;
182 for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
183 RawDexFile::Field raw_field;
184 raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
185 LoadField(klass, raw_field, klass->GetInstanceField(i));
186 }
187 }
188
189 // Load direct methods.
190 if (klass->NumDirectMethods() != 0) {
191 // TODO: append direct methods to class object
192 klass->direct_methods_ = new Method[klass->NumDirectMethods()]();
193 uint32_t last_idx = 0;
194 for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
195 RawDexFile::Method raw_method;
196 raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
197 LoadMethod(klass, raw_method, klass->GetDirectMethod(i));
198 // TODO: register maps
199 }
200 }
201
202 // Load virtual methods.
203 if (klass->NumVirtualMethods() != 0) {
204 // TODO: append virtual methods to class object
205 klass->virtual_methods_ = new Method[klass->NumVirtualMethods()]();
206 uint32_t last_idx = 0;
207 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
208 RawDexFile::Method raw_method;
209 raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
210 LoadMethod(klass, raw_method, klass->GetVirtualMethod(i));
211 // TODO: register maps
212 }
213 }
214
215 return klass;
216}
217
218void ClassLinker::LoadInterfaces(const RawDexFile::ClassDef& class_def,
219 Class* klass) {
220 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
221 const RawDexFile::TypeList* list = raw->GetInterfacesList(class_def);
222 if (list != NULL) {
223 klass->interface_count_ = list->Size();
224 // TODO: allocate the interfaces array on the object heap.
225 klass->interfaces_ = new Class*[list->Size()]();
226 for (size_t i = 0; i < list->Size(); ++i) {
227 const RawDexFile::TypeItem& type_item = list->GetTypeItem(i);
228 klass->interfaces_[i] = reinterpret_cast<Class*>(type_item.type_idx_);
229 }
230 }
231}
232
233void ClassLinker::LoadField(Class* klass, const RawDexFile::Field& src,
234 Field* dst) {
235 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
236 const RawDexFile::FieldId& field_id = raw->GetFieldId(src.field_idx_);
237 dst->klass_ = klass;
238 dst->name_ = raw->dexStringById(field_id.name_idx_);
239 dst->signature_ = raw->dexStringByTypeIdx(field_id.type_idx_);
240 dst->access_flags_ = src.access_flags_;
241}
242
243void ClassLinker::LoadMethod(Class* klass, const RawDexFile::Method& src,
244 Method* dst) {
245 const RawDexFile* raw = klass->GetDexFile()->GetRaw();
246 const RawDexFile::MethodId& method_id = raw->GetMethodId(src.method_idx_);
247 dst->klass_ = klass;
248 dst->name_.set(raw->dexStringById(method_id.name_idx_));
249 dst->proto_idx_ = method_id.proto_idx_;
250 dst->shorty_.set(raw->GetShorty(method_id.proto_idx_));
251 dst->access_flags_ = src.access_flags_;
252
253 // TODO: check for finalize method
254
255 const RawDexFile::CodeItem* code_item = raw->GetCodeItem(src);
256 if (code_item != NULL) {
257 dst->num_registers_ = code_item->registers_size_;
258 dst->num_ins_ = code_item->ins_size_;
259 dst->num_outs_ = code_item->outs_size_;
260 dst->insns_ = code_item->insns_;
261 } else {
262 uint16_t num_args = dst->NumArgRegisters();
263 if (!dst->IsStatic()) {
264 ++num_args;
265 }
266 dst->num_registers_ = dst->num_ins_ + num_args;
267 // TODO: native methods
268 }
269}
270
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700271DexFile* ClassLinker::FindInClassPath(const char* descriptor) {
272 for (size_t i = 0; i != class_path_.size(); ++i) {
273 DexFile* dex_file = class_path_[i];
274 if (dex_file->HasClass(descriptor)) {
275 return dex_file;
276 }
277 }
278 return NULL;
279}
280
281void ClassLinker::AppendToClassPath(DexFile* dex_file) {
282 class_path_.push_back(dex_file);
283}
284
Carl Shapiro565f5072011-07-10 13:39:43 -0700285Class* ClassLinker::CreatePrimitiveClass(JType type, const char* descriptor) {
Brian Carlstrom934486c2011-07-12 23:42:50 -0700286 Class* klass = Heap::AllocClass(NULL);
Carl Shapiro565f5072011-07-10 13:39:43 -0700287 CHECK(klass != NULL);
288 klass->super_class_ = java_lang_Class_;
289 klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract;
290 klass->descriptor_ = descriptor;
291 klass->status_ = Class::kStatusInitialized;
292 return klass;
293}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700294
Carl Shapiro565f5072011-07-10 13:39:43 -0700295Class* ClassLinker::FindPrimitiveClass(JType type) {
296 switch (type) {
297 case kTypeByte:
298 CHECK(primitive_byte_ != NULL);
299 return primitive_byte_;
300 case kTypeChar:
301 CHECK(primitive_char_ != NULL);
302 return primitive_char_;
303 case kTypeDouble:
304 CHECK(primitive_double_ != NULL);
305 return primitive_double_;
306 case kTypeFloat:
307 CHECK(primitive_float_ != NULL);
308 return primitive_float_;
309 case kTypeInt:
310 CHECK(primitive_int_ != NULL);
311 return primitive_int_;
312 case kTypeLong:
313 CHECK(primitive_long_ != NULL);
314 return primitive_long_;
315 case kTypeShort:
316 CHECK(primitive_short_ != NULL);
317 return primitive_short_;
318 case kTypeBoolean:
319 CHECK(primitive_boolean_ != NULL);
320 return primitive_boolean_;
321 case kTypeVoid:
322 CHECK(primitive_void_ != NULL);
323 return primitive_void_;
324 default:
325 LOG(FATAL) << "Unknown primitive type " << static_cast<int>(type);
326 };
327 return NULL; // Not reachable.
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700328}
329
330bool ClassLinker::InsertClass(Class* klass) {
331 // TODO: acquire classes_lock_
332 const char* key = klass->GetDescriptor().data();
333 bool success = classes_.insert(std::make_pair(key, klass)).second;
334 // TODO: release classes_lock_
335 return success;
336}
337
338Class* ClassLinker::LookupClass(const char* descriptor, Object* class_loader) {
339 // TODO: acquire classes_lock_
340 Table::iterator it = classes_.find(descriptor);
341 // TODO: release classes_lock_
342 if (it == classes_.end()) {
343 return NULL;
344 } else {
345 return (*it).second;
346 }
347}
348
349bool ClassLinker::InitializeClass(Class* klass) {
350 CHECK(klass->GetStatus() == Class::kStatusResolved ||
351 klass->GetStatus() == Class::kStatusError);
352
Carl Shapirob5573532011-07-12 18:22:59 -0700353 Thread* self = Thread::Current();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700354
355 {
356 ObjectLock lock(klass);
357
358 if (klass->GetStatus() < Class::kStatusVerified) {
359 if (klass->IsErroneous()) {
360 LG << "re-initializing failed class"; // TODO: throw
361 return false;
362 }
363
364 CHECK(klass->GetStatus() == Class::kStatusResolved);
365
366 klass->status_ = Class::kStatusVerifying;
367 if (!DexVerify::VerifyClass(klass)) {
368 LG << "Verification failed"; // TODO: ThrowVerifyError
369 Object* exception = self->GetException();
370 klass->SetObjectAt(OFFSETOF_MEMBER(Class, verify_error_class_),
371 exception->GetClass());
372 klass->SetStatus(Class::kStatusError);
373 return false;
374 }
375
376 klass->SetStatus(Class::kStatusVerified);
377 }
378
379 if (klass->status_ == Class::kStatusInitialized) {
380 return true;
381 }
382
383 while (klass->status_ == Class::kStatusInitializing) {
384 // we caught somebody else in the act; was it us?
Carl Shapirob5573532011-07-12 18:22:59 -0700385 if (klass->clinit_thread_id_ == self->GetId()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700386 LG << "recursive <clinit>";
387 return true;
388 }
389
390 CHECK(!self->IsExceptionPending());
391
392 lock.Wait(); // TODO: check for interruption
393
394 // When we wake up, repeat the test for init-in-progress. If
395 // there's an exception pending (only possible if
396 // "interruptShouldThrow" was set), bail out.
397 if (self->IsExceptionPending()) {
398 CHECK(false);
399 LG << "Exception in initialization."; // TODO: ExceptionInInitializerError
400 klass->SetStatus(Class::kStatusError);
401 return false;
402 }
403 if (klass->GetStatus() == Class::kStatusInitializing) {
404 continue;
405 }
406 assert(klass->GetStatus() == Class::kStatusInitialized ||
407 klass->GetStatus() == Class::kStatusError);
408 if (klass->IsErroneous()) {
409 /*
410 * The caller wants an exception, but it was thrown in a
411 * different thread. Synthesize one here.
412 */
413 LG << "<clinit> failed"; // TODO: throw UnsatisfiedLinkError
414 return false;
415 }
416 return true; // otherwise, initialized
417 }
418
419 // see if we failed previously
420 if (klass->IsErroneous()) {
421 // might be wise to unlock before throwing; depends on which class
422 // it is that we have locked
423
424 // TODO: throwEarlierClassFailure(klass);
425 return false;
426 }
427
428 if (!ValidateSuperClassDescriptors(klass)) {
429 klass->SetStatus(Class::kStatusError);
430 return false;
431 }
432
433 assert(klass->status < CLASS_INITIALIZING);
434
Carl Shapirob5573532011-07-12 18:22:59 -0700435 klass->clinit_thread_id_ = self->GetId();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700436 klass->status_ = Class::kStatusInitializing;
437 }
438
439 if (!InitializeSuperClass(klass)) {
440 return false;
441 }
442
443 InitializeStaticFields(klass);
444
445 Method* clinit = klass->FindDirectMethodLocally("<clinit>", "()V");
446 if (clinit != NULL) {
447 } else {
448 // JValue unused;
449 // TODO: dvmCallMethod(self, method, NULL, &unused);
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700450 //CHECK(!"unimplemented");
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700451 }
452
453 {
454 ObjectLock lock(klass);
455
456 if (self->IsExceptionPending()) {
457 klass->SetStatus(Class::kStatusError);
458 } else {
459 klass->SetStatus(Class::kStatusInitialized);
460 }
461 lock.NotifyAll();
462 }
463
464 return true;
465}
466
467bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) {
468 if (klass->IsInterface()) {
469 return true;
470 }
471 // begin with the methods local to the superclass
472 if (klass->HasSuperClass() &&
473 klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
474 const Class* super = klass->GetSuperClass();
475 for (int i = super->NumVirtualMethods() - 1; i >= 0; --i) {
476 const Method* method = klass->GetVirtualMethod(i);
477 if (method != super->GetVirtualMethod(i) &&
478 !HasSameMethodDescriptorClasses(method, super, klass)) {
479 LG << "Classes resolve differently in superclass";
480 return false;
481 }
482 }
483 }
484 for (size_t i = 0; i < klass->iftable_count_; ++i) {
485 const InterfaceEntry* iftable = &klass->iftable_[i];
486 Class* interface = iftable->GetClass();
487 if (klass->GetClassLoader() != interface->GetClassLoader()) {
488 for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
489 uint32_t vtable_index = iftable->method_index_array_[j];
490 const Method* method = klass->GetVirtualMethod(vtable_index);
491 if (!HasSameMethodDescriptorClasses(method, interface,
492 method->GetClass())) {
493 LG << "Classes resolve differently in interface"; // TODO: LinkageError
494 return false;
495 }
496 }
497 }
498 }
499 return true;
500}
501
502bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
Brian Carlstrom934486c2011-07-12 23:42:50 -0700503 const Class* klass1,
504 const Class* klass2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700505 const RawDexFile* raw = method->GetClass()->GetDexFile()->GetRaw();
506 const RawDexFile::ProtoId& proto_id = raw->GetProtoId(method->proto_idx_);
507 RawDexFile::ParameterIterator *it;
508 for (it = raw->GetParameterIterator(proto_id); it->HasNext(); it->Next()) {
509 const char* descriptor = it->GetDescriptor();
510 if (descriptor == NULL) {
511 break;
512 }
513 if (descriptor[0] == 'L' || descriptor[0] == '[') {
514 // Found a non-primitive type.
515 if (!HasSameDescriptorClasses(descriptor, klass1, klass2)) {
516 return false;
517 }
518 }
519 }
520 // Check the return type
521 const char* descriptor = raw->GetReturnTypeDescriptor(proto_id);
522 if (descriptor[0] == 'L' || descriptor[0] == '[') {
523 if (HasSameDescriptorClasses(descriptor, klass1, klass2)) {
524 return false;
525 }
526 }
527 return true;
528}
529
530// Returns true if classes referenced by the descriptor are the
531// same classes in klass1 as they are in klass2.
532bool ClassLinker::HasSameDescriptorClasses(const char* descriptor,
Brian Carlstrom934486c2011-07-12 23:42:50 -0700533 const Class* klass1,
534 const Class* klass2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700535 CHECK(descriptor != NULL);
536 CHECK(klass1 != NULL);
537 CHECK(klass2 != NULL);
538#if 0
539 Class* found1 = FindClassNoInit(descriptor, klass1->GetClassLoader());
540 // TODO: found1 == NULL
541 Class* found2 = FindClassNoInit(descriptor, klass2->GetClassLoader());
542 // TODO: found2 == NULL
543 // TODO: lookup found1 in initiating loader list
544 if (found1 == NULL || found2 == NULL) {
Carl Shapirob5573532011-07-12 18:22:59 -0700545 Thread::Current()->ClearException();
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700546 if (found1 == found2) {
547 return true;
548 } else {
549 return false;
550 }
551 }
552#endif
553 return true;
554}
555
556bool ClassLinker::InitializeSuperClass(Class* klass) {
557 CHECK(klass != NULL);
558 // TODO: assert klass lock is acquired
559 if (!klass->IsInterface() && klass->HasSuperClass()) {
560 Class* super_class = klass->GetSuperClass();
561 if (super_class->GetStatus() != Class::kStatusInitialized) {
562 CHECK(!super_class->IsInterface());
563 klass->MonitorExit();
564 bool super_initialized = InitializeClass(super_class);
565 klass->MonitorEnter();
566 // TODO: check for a pending exception
567 if (!super_initialized) {
568 klass->SetStatus(Class::kStatusError);
569 klass->NotifyAll();
570 return false;
571 }
572 }
573 }
574 return true;
575}
576
577void ClassLinker::InitializeStaticFields(Class* klass) {
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700578 size_t num_static_fields = klass->NumStaticFields();
579 if (num_static_fields == 0) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700580 return;
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700581 }
582 DexFile* dex_file = klass->GetDexFile();
583 if (dex_file == NULL) {
584 return;
585 }
586 const char* descriptor = klass->GetDescriptor().data();
Brian Carlstrom934486c2011-07-12 23:42:50 -0700587 const RawDexFile* raw = dex_file->GetRaw();
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700588 const RawDexFile::ClassDef* class_def = raw->FindClassDef(descriptor);
589 CHECK(class_def != NULL);
590 const byte* addr = raw->GetEncodedArray(*class_def);
591 size_t array_size = DecodeUnsignedLeb128(&addr);
592 for (size_t i = 0; i < array_size; ++i) {
593 StaticField* field = klass->GetStaticField(i);
594 JValue value;
595 RawDexFile::ValueType type = raw->ReadEncodedValue(&addr, &value);
596 switch (type) {
597 case RawDexFile::kByte:
598 field->SetByte(value.b);
599 break;
600 case RawDexFile::kShort:
601 field->SetShort(value.s);
602 break;
603 case RawDexFile::kChar:
604 field->SetChar(value.c);
605 break;
606 case RawDexFile::kInt:
607 field->SetInt(value.i);
608 break;
609 case RawDexFile::kLong:
610 field->SetLong(value.j);
611 break;
612 case RawDexFile::kFloat:
613 field->SetFloat(value.f);
614 break;
615 case RawDexFile::kDouble:
616 field->SetDouble(value.d);
617 break;
618 case RawDexFile::kString: {
619 uint32_t string_idx = value.i;
620 String* resolved = ResolveString(klass, string_idx);
621 field->SetObject(resolved);
622 break;
623 }
624 case RawDexFile::kBoolean:
625 field->SetBoolean(value.z);
626 break;
627 case RawDexFile::kNull:
628 field->SetObject(value.l);
629 break;
630 default:
Carl Shapiro606258b2011-07-09 16:09:09 -0700631 LOG(FATAL) << "Unknown type " << static_cast<int>(type);
Carl Shapiro5fafe2b2011-07-09 15:34:41 -0700632 }
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700633 }
634}
635
636bool ClassLinker::LinkClass(Class* klass) {
637 CHECK(klass->status_ == Class::kStatusIdx ||
638 klass->status_ == Class::kStatusLoaded);
639 if (klass->status_ == Class::kStatusIdx) {
640 if (!LinkInterfaces(klass)) {
641 return false;
642 }
643 }
644 if (!LinkSuperClass(klass)) {
645 return false;
646 }
647 if (!LinkMethods(klass)) {
648 return false;
649 }
650 if (!LinkInstanceFields(klass)) {
651 return false;
652 }
653 CreateReferenceOffsets(klass);
654 CHECK_EQ(klass->status_, Class::kStatusLoaded);
655 klass->status_ = Class::kStatusResolved;
656 return true;
657}
658
659bool ClassLinker::LinkInterfaces(Class* klass) {
660 scoped_array<uint32_t> interfaces_idx;
661 // TODO: store interfaces_idx in the Class object
662 // TODO: move this outside of link interfaces
663 if (klass->interface_count_ > 0) {
Carl Shapiro565f5072011-07-10 13:39:43 -0700664 size_t length = klass->interface_count_ * sizeof(klass->interfaces_[0]);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700665 interfaces_idx.reset(new uint32_t[klass->interface_count_]);
Carl Shapiro565f5072011-07-10 13:39:43 -0700666 memcpy(interfaces_idx.get(), klass->interfaces_, length);
667 memset(klass->interfaces_, 0xFF, length);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700668 }
669 // Mark the class as loaded.
670 klass->status_ = Class::kStatusLoaded;
671 if (klass->super_class_idx_ != RawDexFile::kDexNoIndex) {
672 Class* super_class = ResolveClass(klass, klass->super_class_idx_);
673 if (super_class == NULL) {
674 LG << "Failed to resolve superclass";
675 return false;
676 }
677 klass->super_class_ = super_class; // TODO: write barrier
678 }
679 if (klass->interface_count_ > 0) {
680 for (size_t i = 0; i < klass->interface_count_; ++i) {
681 uint32_t idx = interfaces_idx[i];
682 klass->interfaces_[i] = ResolveClass(klass, idx);
683 if (klass->interfaces_[i] == NULL) {
684 LG << "Failed to resolve interface";
685 return false;
686 }
687 // Verify
688 if (!klass->CanAccess(klass->interfaces_[i])) {
689 LG << "Inaccessible interface";
690 return false;
691 }
692 }
693 }
694 return true;
695}
696
697bool ClassLinker::LinkSuperClass(Class* klass) {
698 CHECK(!klass->IsPrimitive());
699 const Class* super = klass->GetSuperClass();
700 if (klass->GetDescriptor() == "Ljava/lang/Object;") {
701 if (super != NULL) {
702 LG << "Superclass must not be defined"; // TODO: ClassFormatError
703 return false;
704 }
705 // TODO: clear finalize attribute
706 return true;
707 }
708 if (super == NULL) {
709 LG << "No superclass defined"; // TODO: LinkageError
710 return false;
711 }
712 // Verify
713 if (super->IsFinal()) {
714 LG << "Superclass is declared final"; // TODO: IncompatibleClassChangeError
715 return false;
716 }
717 if (super->IsInterface()) {
718 LG << "Superclass is an interface"; // TODO: IncompatibleClassChangeError
719 return false;
720 }
721 if (!klass->CanAccess(super)) {
722 LG << "Superclass is inaccessible"; // TODO: IllegalAccessError
723 return false;
724 }
725 return true;
726}
727
728// Populate the class vtable and itable.
729bool ClassLinker::LinkMethods(Class* klass) {
730 if (klass->IsInterface()) {
731 // No vtable.
732 size_t count = klass->NumVirtualMethods();
733 if (!IsUint(16, count)) {
734 LG << "Too many methods on interface"; // TODO: VirtualMachineError
735 return false;
736 }
Carl Shapiro565f5072011-07-10 13:39:43 -0700737 for (size_t i = 0; i < count; ++i) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700738 klass->GetVirtualMethod(i)->method_index_ = i;
739 }
740 } else {
741 // Link virtual method tables
742 LinkVirtualMethods(klass);
743
744 // Link interface method tables
745 LinkInterfaceMethods(klass);
746
747 // Insert stubs.
748 LinkAbstractMethods(klass);
749 }
750 return true;
751}
752
753bool ClassLinker::LinkVirtualMethods(Class* klass) {
754 uint32_t max_count = klass->NumVirtualMethods();
755 if (klass->GetSuperClass() != NULL) {
756 max_count += klass->GetSuperClass()->NumVirtualMethods();
757 } else {
758 CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
759 }
760 // TODO: do not assign to the vtable field until it is fully constructed.
761 // TODO: make this a vector<Method*> instead?
762 klass->vtable_ = new Method*[max_count];
763 if (klass->HasSuperClass()) {
764 memcpy(klass->vtable_,
765 klass->GetSuperClass()->vtable_,
766 klass->GetSuperClass()->vtable_count_ * sizeof(Method*));
767 size_t actual_count = klass->GetSuperClass()->vtable_count_;
768 // See if any of our virtual methods override the superclass.
769 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
770 Method* local_method = klass->GetVirtualMethod(i);
771 size_t j = 0;
772 for (; j < klass->GetSuperClass()->vtable_count_; ++j) {
773 const Method* super_method = klass->vtable_[j];
774 if (local_method->HasSameNameAndPrototype(super_method)) {
775 // Verify
776 if (super_method->IsFinal()) {
777 LG << "Method overrides final method"; // TODO: VirtualMachineError
778 return false;
779 }
780 klass->vtable_[j] = local_method;
781 local_method->method_index_ = j;
782 break;
783 }
784 }
785 if (j == klass->GetSuperClass()->vtable_count_) {
786 // Not overriding, append.
787 klass->vtable_[actual_count] = local_method;
788 local_method->method_index_ = actual_count;
789 actual_count += 1;
790 }
791 }
792 if (!IsUint(16, actual_count)) {
793 LG << "Too many methods defined on class"; // TODO: VirtualMachineError
794 return false;
795 }
796 CHECK_LE(actual_count, max_count);
797 if (actual_count < max_count) {
798 Method** new_vtable = new Method*[actual_count];
799 memcpy(new_vtable, klass->vtable_, actual_count * sizeof(Method*));
Carl Shapiro565f5072011-07-10 13:39:43 -0700800 delete[] klass->vtable_;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700801 klass->vtable_ = new_vtable;
802 LG << "shrunk vtable: "
803 << "was " << max_count << ", "
804 << "now " << actual_count;
805 }
806 klass->vtable_count_ = actual_count;
807 } else {
808 CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
809 if (!IsUint(16, klass->NumVirtualMethods())) {
810 LG << "Too many methods"; // TODO: VirtualMachineError
811 return false;
812 }
813 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
814 klass->vtable_[i] = klass->GetVirtualMethod(i);
815 klass->GetVirtualMethod(i)->method_index_ = i & 0xFFFF;
816 }
817 klass->vtable_count_ = klass->NumVirtualMethods();
818 }
819 return true;
820}
821
822bool ClassLinker::LinkInterfaceMethods(Class* klass) {
823 int pool_offset = 0;
824 int pool_size = 0;
825 int miranda_count = 0;
826 int miranda_alloc = 0;
827 size_t super_ifcount;
828 if (klass->HasSuperClass()) {
829 super_ifcount = klass->GetSuperClass()->iftable_count_;
830 } else {
831 super_ifcount = 0;
832 }
833 size_t ifCount = super_ifcount;
834 ifCount += klass->interface_count_;
835 for (size_t i = 0; i < klass->interface_count_; i++) {
836 ifCount += klass->interfaces_[i]->iftable_count_;
837 }
838 if (ifCount == 0) {
839 assert(klass->iftable_count_ == 0);
840 assert(klass->iftable == NULL);
841 return true;
842 }
843 klass->iftable_ = new InterfaceEntry[ifCount * sizeof(InterfaceEntry)];
844 memset(klass->iftable_, 0x00, sizeof(InterfaceEntry) * ifCount);
845 if (super_ifcount != 0) {
846 memcpy(klass->iftable_, klass->GetSuperClass()->iftable_,
847 sizeof(InterfaceEntry) * super_ifcount);
848 }
849 // Flatten the interface inheritance hierarchy.
850 size_t idx = super_ifcount;
851 for (size_t i = 0; i < klass->interface_count_; i++) {
852 Class* interf = klass->interfaces_[i];
853 assert(interf != NULL);
854 if (!interf->IsInterface()) {
855 LG << "Class implements non-interface class"; // TODO: IncompatibleClassChangeError
856 return false;
857 }
858 klass->iftable_[idx++].SetClass(interf);
859 for (size_t j = 0; j < interf->iftable_count_; j++) {
860 klass->iftable_[idx++].SetClass(interf->iftable_[j].GetClass());
861 }
862 }
863 CHECK_EQ(idx, ifCount);
864 klass->iftable_count_ = ifCount;
865 if (klass->IsInterface() || super_ifcount == ifCount) {
866 return true;
867 }
868 for (size_t i = super_ifcount; i < ifCount; i++) {
869 pool_size += klass->iftable_[i].GetClass()->NumVirtualMethods();
870 }
871 if (pool_size == 0) {
872 return true;
873 }
874 klass->ifvi_pool_count_ = pool_size;
875 klass->ifvi_pool_ = new uint32_t[pool_size];
876 std::vector<Method*> miranda_list;
877 for (size_t i = super_ifcount; i < ifCount; ++i) {
878 klass->iftable_[i].method_index_array_ = klass->ifvi_pool_ + pool_offset;
879 Class* interface = klass->iftable_[i].GetClass();
880 pool_offset += interface->NumVirtualMethods(); // end here
881 for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
882 Method* interface_method = interface->GetVirtualMethod(j);
883 int k; // must be signed
884 for (k = klass->vtable_count_ - 1; k >= 0; --k) {
885 if (interface_method->HasSameNameAndPrototype(klass->vtable_[k])) {
Carl Shapiro565f5072011-07-10 13:39:43 -0700886 if (!klass->vtable_[k]->IsPublic()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700887 LG << "Implementation not public";
888 return false;
889 }
890 klass->iftable_[i].method_index_array_[j] = k;
891 break;
892 }
893 }
894 if (k < 0) {
895 if (miranda_count == miranda_alloc) {
896 miranda_alloc += 8;
897 if (miranda_list.empty()) {
898 miranda_list.resize(miranda_alloc);
899 } else {
900 miranda_list.resize(miranda_alloc);
901 }
902 }
903 int mir;
904 for (mir = 0; mir < miranda_count; mir++) {
905 if (miranda_list[mir]->HasSameNameAndPrototype(interface_method)) {
906 break;
907 }
908 }
909 // point the interface table at a phantom slot index
910 klass->iftable_[i].method_index_array_[j] = klass->vtable_count_ + mir;
911 if (mir == miranda_count) {
912 miranda_list[miranda_count++] = interface_method;
913 }
914 }
915 }
916 }
917 if (miranda_count != 0) {
918 Method* newVirtualMethods;
919 Method* meth;
920 int oldMethodCount, oldVtableCount;
921 if (klass->virtual_methods_ == NULL) {
922 newVirtualMethods = new Method[klass->NumVirtualMethods() + miranda_count];
923
924 } else {
925 newVirtualMethods = new Method[klass->NumVirtualMethods() + miranda_count];
926 memcpy(newVirtualMethods,
927 klass->virtual_methods_,
928 klass->NumVirtualMethods() * sizeof(Method));
929
930 }
931 if (newVirtualMethods != klass->virtual_methods_) {
932 Method* meth = newVirtualMethods;
933 for (size_t i = 0; i < klass->NumVirtualMethods(); i++, meth++) {
934 klass->vtable_[meth->method_index_] = meth;
935 }
936 }
937 oldMethodCount = klass->NumVirtualMethods();
938 klass->virtual_methods_ = newVirtualMethods;
939 klass->num_virtual_methods_ += miranda_count;
940
941 CHECK(klass->vtable_ != NULL);
942 oldVtableCount = klass->vtable_count_;
943 klass->vtable_count_ += miranda_count;
944
945 meth = klass->virtual_methods_ + oldMethodCount;
946 for (int i = 0; i < miranda_count; i++, meth++) {
947 memcpy(meth, miranda_list[i], sizeof(Method));
948 meth->klass_ = klass;
949 meth->access_flags_ |= kAccMiranda;
950 meth->method_index_ = 0xFFFF & (oldVtableCount + i);
951 klass->vtable_[oldVtableCount + i] = meth;
952 }
953 }
954 return true;
955}
956
957void ClassLinker::LinkAbstractMethods(Class* klass) {
958 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
959 Method* method = klass->GetVirtualMethod(i);
960 if (method->IsAbstract()) {
961 method->insns_ = reinterpret_cast<uint16_t*>(0xFFFFFFFF); // TODO: AbstractMethodError
962 }
963 }
964}
965
966bool ClassLinker::LinkInstanceFields(Class* klass) {
967 int fieldOffset;
968 if (klass->GetSuperClass() != NULL) {
969 fieldOffset = klass->GetSuperClass()->object_size_;
970 } else {
971 fieldOffset = OFFSETOF_MEMBER(DataObject, fields_);
972 }
973 // Move references to the front.
974 klass->num_reference_ifields_ = 0;
975 size_t i = 0;
976 size_t j = klass->NumInstanceFields() - 1;
977 for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
978 InstanceField* pField = klass->GetInstanceField(i);
979 char c = pField->GetType();
980
981 if (c != '[' && c != 'L') {
982 while (j > i) {
983 InstanceField* refField = klass->GetInstanceField(j--);
984 char rc = refField->GetType();
985 if (rc == '[' || rc == 'L') {
986 pField->Swap(refField);
987 c = rc;
988 klass->num_reference_ifields_++;
989 break;
990 }
991 }
992 } else {
993 klass->num_reference_ifields_++;
994 }
995 if (c != '[' && c != 'L') {
996 break;
997 }
998 pField->SetOffset(fieldOffset);
999 fieldOffset += sizeof(uint32_t);
1000 }
1001
1002 // Now we want to pack all of the double-wide fields together. If
1003 // we're not aligned, though, we want to shuffle one 32-bit field
1004 // into place. If we can't find one, we'll have to pad it.
1005 if (i != klass->NumInstanceFields() && (fieldOffset & 0x04) != 0) {
1006 InstanceField* pField = klass->GetInstanceField(i);
1007 char c = pField->GetType();
1008
1009 if (c != 'J' && c != 'D') {
1010 // The field that comes next is 32-bit, so just advance past it.
1011 assert(c != '[' && c != 'L');
1012 pField->SetOffset(fieldOffset);
1013 fieldOffset += sizeof(uint32_t);
1014 i++;
1015 } else {
1016 // Next field is 64-bit, so search for a 32-bit field we can
1017 // swap into it.
1018 bool found = false;
1019 j = klass->NumInstanceFields() - 1;
1020 while (j > i) {
1021 InstanceField* singleField = klass->GetInstanceField(j--);
1022 char rc = singleField->GetType();
1023 if (rc != 'J' && rc != 'D') {
1024 pField->Swap(singleField);
1025 pField->SetOffset(fieldOffset);
1026 fieldOffset += sizeof(uint32_t);
1027 found = true;
1028 i++;
1029 break;
1030 }
1031 }
1032 if (!found) {
1033 fieldOffset += sizeof(uint32_t);
1034 }
1035 }
1036 }
1037
1038 // Alignment is good, shuffle any double-wide fields forward, and
1039 // finish assigning field offsets to all fields.
1040 assert(i == klass->NumInstanceFields() || (fieldOffset & 0x04) == 0);
1041 j = klass->NumInstanceFields() - 1;
1042 for ( ; i < klass->NumInstanceFields(); i++) {
1043 InstanceField* pField = klass->GetInstanceField(i);
1044 char c = pField->GetType();
1045 if (c != 'D' && c != 'J') {
1046 while (j > i) {
1047 InstanceField* doubleField = klass->GetInstanceField(j--);
1048 char rc = doubleField->GetType();
1049 if (rc == 'D' || rc == 'J') {
1050 pField->Swap(doubleField);
1051 c = rc;
1052 break;
1053 }
1054 }
1055 } else {
1056 // This is a double-wide field, leave it be.
1057 }
1058
1059 pField->SetOffset(fieldOffset);
1060 fieldOffset += sizeof(uint32_t);
1061 if (c == 'J' || c == 'D')
1062 fieldOffset += sizeof(uint32_t);
1063 }
1064
1065#ifndef NDEBUG
1066 /* Make sure that all reference fields appear before
1067 * non-reference fields, and all double-wide fields are aligned.
1068 */
1069 j = 0; // seen non-ref
1070 for (i = 0; i < klass->NumInstanceFields(); i++) {
1071 InstanceField *pField = &klass->ifields[i];
1072 char c = pField->GetType();
1073
1074 if (c == 'D' || c == 'J') {
1075 assert((pField->offset_ & 0x07) == 0);
1076 }
1077
1078 if (c != '[' && c != 'L') {
1079 if (!j) {
1080 assert(i == klass->num_reference_ifields_);
1081 j = 1;
1082 }
1083 } else if (j) {
1084 assert(false);
1085 }
1086 }
1087 if (!j) {
1088 assert(klass->num_reference_ifields_ == klass->NumInstanceFields());
1089 }
1090#endif
1091
1092 klass->object_size_ = fieldOffset;
1093 return true;
1094}
1095
1096// Set the bitmap of reference offsets, refOffsets, from the ifields
1097// list.
1098void ClassLinker::CreateReferenceOffsets(Class* klass) {
1099 uint32_t reference_offsets = 0;
1100 if (klass->HasSuperClass()) {
1101 reference_offsets = klass->GetSuperClass()->GetReferenceOffsets();
1102 }
1103 // If our superclass overflowed, we don't stand a chance.
1104 if (reference_offsets != CLASS_WALK_SUPER) {
1105 // All of the fields that contain object references are guaranteed
1106 // to be at the beginning of the ifields list.
1107 for (size_t i = 0; i < klass->NumReferenceInstanceFields(); ++i) {
1108 // Note that, per the comment on struct InstField, f->byteOffset
1109 // is the offset from the beginning of obj, not the offset into
1110 // obj->instanceData.
1111 const InstanceField* field = klass->GetInstanceField(i);
1112 size_t byte_offset = field->GetOffset();
1113 CHECK_GE(byte_offset, CLASS_SMALLEST_OFFSET);
1114 CHECK_EQ(byte_offset & (CLASS_OFFSET_ALIGNMENT - 1), 0);
1115 if (CLASS_CAN_ENCODE_OFFSET(byte_offset)) {
1116 uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset);
1117 CHECK_NE(new_bit, 0);
1118 reference_offsets |= new_bit;
1119 } else {
1120 reference_offsets = CLASS_WALK_SUPER;
1121 break;
1122 }
1123 }
1124 klass->SetReferenceOffsets(reference_offsets);
1125 }
1126}
1127
Carl Shapiro5fafe2b2011-07-09 15:34:41 -07001128Class* ClassLinker::ResolveClass(const Class* referrer, uint32_t class_idx) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001129 DexFile* dex_file = referrer->GetDexFile();
1130 Class* resolved = dex_file->GetResolvedClass(class_idx);
1131 if (resolved != NULL) {
1132 return resolved;
1133 }
1134 const char* descriptor = dex_file->GetRaw()->dexStringByTypeIdx(class_idx);
1135 if (descriptor[0] != '\0' && descriptor[1] == '\0') {
Carl Shapiro565f5072011-07-10 13:39:43 -07001136 JType type = static_cast<JType>(descriptor[0]);
1137 resolved = FindPrimitiveClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001138 } else {
1139 resolved = FindClass(descriptor, referrer->GetClassLoader(), NULL);
1140 }
1141 if (resolved != NULL) {
1142 Class* check = resolved->IsArray() ? resolved->component_type_ : resolved;
1143 if (referrer->GetDexFile() != check->GetDexFile()) {
1144 if (check->GetClassLoader() != NULL) {
1145 LG << "Class resolved by unexpected DEX"; // TODO: IllegalAccessError
1146 return NULL;
1147 }
1148 }
Carl Shapiro5fafe2b2011-07-09 15:34:41 -07001149 dex_file->SetResolvedClass(resolved, class_idx);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001150 } else {
Carl Shapirob5573532011-07-12 18:22:59 -07001151 CHECK(Thread::Current()->IsExceptionPending());
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001152 }
1153 return resolved;
1154}
1155
1156Method* ResolveMethod(const Class* referrer, uint32_t method_idx,
1157 /*MethodType*/ int method_type) {
1158 CHECK(false);
1159 return NULL;
1160}
1161
Carl Shapiro5fafe2b2011-07-09 15:34:41 -07001162String* ClassLinker::ResolveString(const Class* referring, uint32_t string_idx) {
1163 const RawDexFile* raw = referring->GetDexFile()->GetRaw();
1164 const RawDexFile::StringId& string_id = raw->GetStringId(string_idx);
1165 const char* string_data = raw->GetStringData(string_id);
1166 String* new_string = Heap::AllocStringFromModifiedUtf8(string_data);
1167 // TODO: intern the new string
1168 referring->GetDexFile()->SetResolvedString(new_string, string_idx);
1169 return new_string;
1170}
1171
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001172} // namespace art