blob: 3ddfe59ea33e8282d8ef5e7dc44f0e63db57c95d [file] [log] [blame]
Carl Shapiro3ee755d2011-06-28 12:11:04 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "object.h"
4
Ian Rogersb033c752011-07-20 12:22:35 -07005#include <string.h>
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07006
Ian Rogersdf20fe02011-07-20 20:34:16 -07007#include <algorithm>
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07008#include <string>
9#include <utility>
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070010
Elliott Hughesd8ddfd52011-08-15 14:32:53 -070011#include "class_linker.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070012#include "class_loader.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070013#include "globals.h"
Brian Carlstroma40f9bc2011-07-26 21:26:07 -070014#include "heap.h"
Elliott Hughescf4c6c42011-09-01 15:16:42 -070015#include "intern_table.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070016#include "logging.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070017#include "dex_cache.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070018#include "dex_file.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070019#include "runtime.h"
Carl Shapiro3ee755d2011-06-28 12:11:04 -070020
21namespace art {
22
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070023bool Object::IsString() const {
24 // TODO use "klass_ == String::GetJavaLangString()" instead?
25 return GetClass() == GetClass()->GetDescriptor()->GetClass();
26}
27
28// TODO: get global references for these
29Class* Field::java_lang_reflect_Field_ = NULL;
30
31void Field::SetClass(Class* java_lang_reflect_Field) {
32 CHECK(java_lang_reflect_Field_ == NULL);
33 CHECK(java_lang_reflect_Field != NULL);
34 java_lang_reflect_Field_ = java_lang_reflect_Field;
35}
36
37void Field::ResetClass() {
38 CHECK(java_lang_reflect_Field_ != NULL);
39 java_lang_reflect_Field_ = NULL;
40}
41
42void Field::SetTypeIdx(uint32_t type_idx) {
43 SetField32(OFFSET_OF_OBJECT_MEMBER(Field, type_idx_), type_idx, false);
44}
45
46Class* Field::GetTypeDuringLinking() const {
47 // We are assured that the necessary primitive types are in the dex cache
48 // early during class linking
49 return GetDeclaringClass()->GetDexCache()->GetResolvedType(GetTypeIdx());
50}
51
52Class* Field::GetType() const {
53 DCHECK(Runtime::Current() != NULL)
54 << "Can't call GetType without an initialized runtime";
55 // Do full linkage (which sets dex cache value to speed next call)
56 return Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
57}
58
59uint32_t Field::Get32StaticFromCode(uint32_t field_idx, const Method* referrer) {
60 Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
61 if (field == NULL) {
62 UNIMPLEMENTED(FATAL) << "throw an error";
63 return 0;
Brian Carlstromb63ec392011-08-27 17:38:27 -070064 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070065 DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
66 return field->Get32(NULL);
67}
68void Field::Set32StaticFromCode(uint32_t field_idx, const Method* referrer, uint32_t new_value) {
69 Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
70 if (field == NULL) {
71 UNIMPLEMENTED(FATAL) << "throw an error";
72 return;
73 }
74 DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
75 field->Set32(NULL, new_value);
76}
77uint64_t Field::Get64StaticFromCode(uint32_t field_idx, const Method* referrer) {
78 Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
79 if (field == NULL) {
80 UNIMPLEMENTED(FATAL) << "throw an error";
81 return 0;
82 }
83 DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
84 return field->Get64(NULL);
85}
86void Field::Set64StaticFromCode(uint32_t field_idx, const Method* referrer, uint64_t new_value) {
87 Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
88 if (field == NULL) {
89 UNIMPLEMENTED(FATAL) << "throw an error";
90 return;
91 }
92 DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
93 field->Set64(NULL, new_value);
94}
95Object* Field::GetObjStaticFromCode(uint32_t field_idx, const Method* referrer) {
96 Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
97 if (field == NULL) {
98 UNIMPLEMENTED(FATAL) << "throw an error";
99 return 0;
100 }
101 DCHECK(!field->GetType()->IsPrimitive());
102 return field->GetObj(NULL);
103}
104void Field::SetObjStaticFromCode(uint32_t field_idx, const Method* referrer, Object* new_value) {
105 Field* field = Runtime::Current()->GetClassLinker()->ResolveField(field_idx, referrer);
106 if (field == NULL) {
107 UNIMPLEMENTED(FATAL) << "throw an error";
108 return;
109 }
110 DCHECK(!field->GetType()->IsPrimitive());
111 field->SetObj(NULL, new_value);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700112}
113
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700114uint32_t Field::Get32(const Object* object) const {
115 CHECK((object == NULL) == IsStatic());
116 if (IsStatic()) {
117 object = declaring_class_;
118 }
119 return object->GetField32(GetOffset(), IsVolatile());
Elliott Hughes68f4fa02011-08-21 10:46:59 -0700120}
121
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700122void Field::Set32(Object* object, uint32_t new_value) const {
123 CHECK((object == NULL) == IsStatic());
124 if (IsStatic()) {
125 object = declaring_class_;
126 }
127 object->SetField32(GetOffset(), new_value, IsVolatile());
128}
129
130uint64_t Field::Get64(const Object* object) const {
131 CHECK((object == NULL) == IsStatic());
132 if (IsStatic()) {
133 object = declaring_class_;
134 }
135 return object->GetField64(GetOffset(), IsVolatile());
136}
137
138void Field::Set64(Object* object, uint64_t new_value) const {
139 CHECK((object == NULL) == IsStatic());
140 if (IsStatic()) {
141 object = declaring_class_;
142 }
143 object->SetField64(GetOffset(), new_value, IsVolatile());
144}
145
146Object* Field::GetObj(const Object* object) const {
147 CHECK((object == NULL) == IsStatic());
148 if (IsStatic()) {
149 object = declaring_class_;
150 }
151 return object->GetFieldObject<Object*>(GetOffset(), IsVolatile());
152}
153
154void Field::SetObj(Object* object, const Object* new_value) const {
155 CHECK((object == NULL) == IsStatic());
156 if (IsStatic()) {
157 object = declaring_class_;
158 }
159 object->SetFieldObject(GetOffset(), new_value, IsVolatile());
160}
161
162bool Field::GetBoolean(const Object* object) const {
163 DCHECK(GetType()->IsPrimitiveBoolean());
164 return Get32(object);
165}
166
167void Field::SetBoolean(Object* object, bool z) const {
168 DCHECK(GetType()->IsPrimitiveBoolean());
169 Set32(object, z);
170}
171
172int8_t Field::GetByte(const Object* object) const {
173 DCHECK(GetType()->IsPrimitiveByte());
174 return Get32(object);
175}
176
177void Field::SetByte(Object* object, int8_t b) const {
178 DCHECK(GetType()->IsPrimitiveByte());
179 Set32(object, b);
180}
181
182uint16_t Field::GetChar(const Object* object) const {
183 DCHECK(GetType()->IsPrimitiveChar());
184 return Get32(object);
185}
186
187void Field::SetChar(Object* object, uint16_t c) const {
188 DCHECK(GetType()->IsPrimitiveChar());
189 Set32(object, c);
190}
191
192uint16_t Field::GetShort(const Object* object) const {
193 DCHECK(GetType()->IsPrimitiveShort());
194 return Get32(object);
195}
196
197void Field::SetShort(Object* object, uint16_t s) const {
198 DCHECK(GetType()->IsPrimitiveShort());
199 Set32(object, s);
200}
201
202int32_t Field::GetInt(const Object* object) const {
203 DCHECK(GetType()->IsPrimitiveInt());
204 return Get32(object);
205}
206
207void Field::SetInt(Object* object, int32_t i) const {
208 DCHECK(GetType()->IsPrimitiveInt());
209 Set32(object, i);
210}
211
212int64_t Field::GetLong(const Object* object) const {
213 DCHECK(GetType()->IsPrimitiveLong());
214 return Get64(object);
215}
216
217void Field::SetLong(Object* object, int64_t j) const {
218 DCHECK(GetType()->IsPrimitiveLong());
219 Set64(object, j);
220}
221
222float Field::GetFloat(const Object* object) const {
223 DCHECK(GetType()->IsPrimitiveFloat());
224 JValue float_bits;
225 float_bits.i = Get32(object);
226 return float_bits.f;
227}
228
229void Field::SetFloat(Object* object, float f) const {
230 DCHECK(GetType()->IsPrimitiveFloat());
231 JValue float_bits;
232 float_bits.f = f;
233 Set32(object, float_bits.i);
234}
235
236double Field::GetDouble(const Object* object) const {
237 DCHECK(GetType()->IsPrimitiveDouble());
238 JValue double_bits;
239 double_bits.j = Get64(object);
240 return double_bits.d;
241}
242
243void Field::SetDouble(Object* object, double d) const {
244 DCHECK(GetType()->IsPrimitiveDouble());
245 JValue double_bits;
246 double_bits.d = d;
247 Set64(object, double_bits.j);
248}
249
250Object* Field::GetObject(const Object* object) const {
251 CHECK(!GetType()->IsPrimitive());
252 return GetObj(object);
253}
254
255void Field::SetObject(Object* object, const Object* l) const {
256 CHECK(!GetType()->IsPrimitive());
257 SetObj(object, l);
258}
259
260// TODO: get global references for these
261Class* Method::java_lang_reflect_Method_ = NULL;
262
263void Method::SetClass(Class* java_lang_reflect_Method) {
264 CHECK(java_lang_reflect_Method_ == NULL);
265 CHECK(java_lang_reflect_Method != NULL);
266 java_lang_reflect_Method_ = java_lang_reflect_Method;
267}
268
269void Method::ResetClass() {
270 CHECK(java_lang_reflect_Method_ != NULL);
271 java_lang_reflect_Method_ = NULL;
272}
273
274ObjectArray<String>* Method::GetDexCacheStrings() const {
275 return GetFieldObject<ObjectArray<String>*>(
276 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_), false);
277}
278
279void Method::SetReturnTypeIdx(uint32_t new_return_type_idx) {
280 SetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_),
281 new_return_type_idx, false);
282}
283
284Class* Method::GetReturnType() const {
285 DCHECK(GetDeclaringClass()->IsLinked());
286 // Short-cut
287 Class* result = GetDexCacheResolvedTypes()->Get(GetReturnTypeIdx());
288 if (result == NULL) {
289 // Do full linkage and set cache value for next call
290 result = Runtime::Current()->GetClassLinker()->ResolveType(GetReturnTypeIdx(), this);
291 }
292 CHECK(result != NULL);
293 return result;
294}
295
296void Method::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) {
297 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_),
298 new_dex_cache_strings, false);
299}
300
301ObjectArray<Class>* Method::GetDexCacheResolvedTypes() const {
302 return GetFieldObject<ObjectArray<Class>*>(
303 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_), false);
304}
305
306void Method::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_classes) {
307 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_),
308 new_dex_cache_classes, false);
309}
310
311ObjectArray<Method>* Method::GetDexCacheResolvedMethods() const {
312 return GetFieldObject<ObjectArray<Method>*>(
313 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_), false);
314}
315
316void Method::SetDexCacheResolvedMethods(ObjectArray<Method>* new_dex_cache_methods) {
317 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_),
318 new_dex_cache_methods, false);
319}
320
321ObjectArray<Field>* Method::GetDexCacheResolvedFields() const {
322 return GetFieldObject<ObjectArray<Field>*>(
323 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_fields_), false);
324}
325
326void Method::SetDexCacheResolvedFields(ObjectArray<Field>* new_dex_cache_fields) {
327 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_fields_),
328 new_dex_cache_fields, false);
329}
330
331CodeAndDirectMethods* Method::GetDexCacheCodeAndDirectMethods() const {
332 return GetFieldPtr<CodeAndDirectMethods*>(
333 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_),
334 false);
335}
336
337void Method::SetDexCacheCodeAndDirectMethods(CodeAndDirectMethods* new_value) {
338 SetFieldPtr<CodeAndDirectMethods*>(
339 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_),
340 new_value, false);
341}
342
343ObjectArray<StaticStorageBase>* Method::GetDexCacheInitializedStaticStorage() const {
344 return GetFieldObject<ObjectArray<StaticStorageBase>*>(
345 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
346 false);
347}
348
349void Method::SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) {
350 SetFieldObject(
351 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
352 new_value, false);
353
354}
355
356size_t Method::NumArgRegisters(const StringPiece& shorty) {
357 CHECK_LE(1, shorty.length());
358 uint32_t num_registers = 0;
359 for (int i = 1; i < shorty.length(); ++i) {
360 char ch = shorty[i];
361 if (ch == 'D' || ch == 'J') {
362 num_registers += 2;
363 } else {
364 num_registers += 1;
Brian Carlstromb63ec392011-08-27 17:38:27 -0700365 }
366 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700367 return num_registers;
368}
369
370size_t Method::NumArgArrayBytes() const {
371 const StringPiece& shorty = GetShorty();
372 size_t num_bytes = 0;
373 for (int i = 1; i < shorty.length(); ++i) {
374 char ch = shorty[i];
375 if (ch == 'D' || ch == 'J') {
376 num_bytes += 8;
377 } else if (ch == 'L') {
378 // Argument is a reference or an array. The shorty descriptor
379 // does not distinguish between these types.
380 num_bytes += sizeof(Object*);
381 } else {
382 num_bytes += 4;
383 }
384 }
385 return num_bytes;
386}
387
388// The number of reference arguments to this method including implicit this
389// pointer
390size_t Method::NumReferenceArgs() const {
391 const StringPiece& shorty = GetShorty();
392 size_t result = IsStatic() ? 0 : 1; // The implicit this pointer.
393 for (int i = 1; i < shorty.length(); i++) {
394 if ((shorty[i] == 'L') || (shorty[i] == '[')) {
395 result++;
396 }
397 }
398 return result;
399}
400
401// The number of long or double arguments
402size_t Method::NumLongOrDoubleArgs() const {
403 const StringPiece& shorty = GetShorty();
404 size_t result = 0;
405 for (int i = 1; i < shorty.length(); i++) {
406 if ((shorty[i] == 'D') || (shorty[i] == 'J')) {
407 result++;
408 }
409 }
410 return result;
411}
412
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700413// Is the given method parameter a reference?
414bool Method::IsParamAReference(unsigned int param) const {
415 CHECK_LT(param, NumArgs());
416 if (IsStatic()) {
417 param++; // 0th argument must skip return value at start of the shorty
418 } else if (param == 0) {
419 return true; // this argument
420 }
421 return GetShorty()[param] == 'L';
422}
423
424// Is the given method parameter a long or double?
425bool Method::IsParamALongOrDouble(unsigned int param) const {
426 CHECK_LT(param, NumArgs());
427 if (IsStatic()) {
428 param++; // 0th argument must skip return value at start of the shorty
429 } else if (param == 0) {
430 return false; // this argument
431 }
432 return (GetShorty()[param] == 'J') || (GetShorty()[param] == 'D');
433}
434
435static size_t ShortyCharToSize(char x) {
436 switch (x) {
437 case 'V': return 0;
438 case '[': return kPointerSize;
439 case 'L': return kPointerSize;
440 case 'D': return 8;
441 case 'J': return 8;
442 default: return 4;
443 }
444}
445
446size_t Method::ParamSize(unsigned int param) const {
447 CHECK_LT(param, NumArgs());
448 if (IsStatic()) {
449 param++; // 0th argument must skip return value at start of the shorty
450 } else if (param == 0) {
451 return kPointerSize; // this argument
452 }
453 return ShortyCharToSize(GetShorty()[param]);
454}
455
456size_t Method::ReturnSize() const {
457 return ShortyCharToSize(GetShorty()[0]);
458}
459
460bool Method::HasSameNameAndDescriptor(const Method* that) const {
461 return (this->GetName()->Equals(that->GetName()) &&
462 this->GetSignature()->Equals(that->GetSignature()));
463}
464
465void Method::SetCode(const byte* compiled_code,
466 size_t byte_count,
467 InstructionSet set) {
468 // Copy the code into an executable region.
469 code_instruction_set_ = set;
470 code_area_.reset(MemMap::Map(byte_count,
471 PROT_READ | PROT_WRITE | PROT_EXEC));
472 CHECK(code_area_.get());
473 byte* code = code_area_->GetAddress();
474 memcpy(code, compiled_code, byte_count);
475 __builtin___clear_cache(code, code + byte_count);
476
477 uintptr_t address = reinterpret_cast<uintptr_t>(code);
478 if (code_instruction_set_ == kThumb2) {
479 // Set the low-order bit so a BLX will switch to Thumb mode
480 address |= 0x1;
481 }
482 SetFieldPtr<uintptr_t>(OFFSET_OF_OBJECT_MEMBER(Method, code_), address, false);
483}
484
485void Class::SetStatus(Status new_status) {
486 CHECK(new_status > GetStatus() || new_status == kStatusError ||
487 Runtime::Current() == NULL); // no runtime implies we're not initialized
488 CHECK(sizeof(Status) == sizeof(uint32_t));
489 return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_),
490 new_status, false);
491}
492
493DexCache* Class::GetDexCache() const {
494 return GetFieldObject<DexCache*>(
495 OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
496}
497
498void Class::SetDexCache(DexCache* new_dex_cache) {
499 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_),
500 new_dex_cache, false);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700501}
502
Brian Carlstrom1f870082011-08-23 16:02:11 -0700503Object* Class::AllocObjectFromCode(uint32_t type_idx, Method* method) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700504 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700505 if (klass == NULL) {
506 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
507 if (klass == NULL) {
508 UNIMPLEMENTED(FATAL) << "throw an error";
509 return NULL;
510 }
511 }
Brian Carlstrom1f870082011-08-23 16:02:11 -0700512 return klass->AllocObject();
513}
514
515Object* Class::AllocObject() {
516 DCHECK(!IsAbstract());
517 return Heap::AllocObject(this, this->object_size_);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700518}
519
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700520void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
521 if (new_reference_offsets != CLASS_WALK_SUPER) {
522 // Sanity check that the number of bits set in the reference offset bitmap
523 // agrees with the number of references
524 Class* cur = this;
525 size_t cnt = 0;
526 while (cur) {
527 cnt += cur->NumReferenceInstanceFieldsDuringLinking();
528 cur = cur->GetSuperClass();
529 }
530 CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), cnt);
531 }
532 SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
533 new_reference_offsets, false);
534}
535
536void Class::SetReferenceStaticOffsets(uint32_t new_reference_offsets) {
537 if (new_reference_offsets != CLASS_WALK_SUPER) {
538 // Sanity check that the number of bits set in the reference offset bitmap
539 // agrees with the number of references
540 CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets),
541 NumReferenceStaticFieldsDuringLinking());
542 }
543 SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_),
544 new_reference_offsets, false);
545}
546
547size_t Class::PrimitiveSize() const {
548 switch (GetPrimitiveType()) {
549 case kPrimBoolean:
550 case kPrimByte:
551 case kPrimChar:
552 case kPrimShort:
553 case kPrimInt:
554 case kPrimFloat:
555 return sizeof(int32_t);
556 case kPrimLong:
557 case kPrimDouble:
558 return sizeof(int64_t);
559 default:
560 LOG(FATAL) << "Primitive type size calculation on invalid type " << this;
561 return 0;
562 }
563}
564
565size_t Class::GetTypeSize(const String* descriptor) {
566 switch (descriptor->CharAt(0)) {
567 case 'B': return 1; // byte
568 case 'C': return 2; // char
569 case 'D': return 8; // double
570 case 'F': return 4; // float
571 case 'I': return 4; // int
572 case 'J': return 8; // long
573 case 'S': return 2; // short
574 case 'Z': return 1; // boolean
575 case 'L': return sizeof(Object*);
576 case '[': return sizeof(Array*);
577 default:
578 LOG(ERROR) << "Unknown type " << descriptor;
579 return 0;
580 }
Elliott Hughesbf86d042011-08-31 17:53:14 -0700581}
582
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700583bool Class::Implements(const Class* klass) const {
584 DCHECK(klass != NULL);
585 DCHECK(klass->IsInterface());
586 // All interfaces implemented directly and by our superclass, and
587 // recursively all super-interfaces of those interfaces, are listed
588 // in iftable_, so we can just do a linear scan through that.
589 for (size_t i = 0; i < iftable_count_; i++) {
Brian Carlstrom30b94452011-08-25 21:35:26 -0700590 if (iftable_[i].GetInterface() == klass) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700591 return true;
592 }
593 }
594 return false;
595}
596
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700597bool Class::CanPutArrayElementFromCode(const Class* elementClass, const Class* arrayClass) {
598 UNIMPLEMENTED(FATAL);
599 return false;
600}
601
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700602// Determine whether "this" is assignable from "klazz", where both of these
603// are array classes.
604//
605// Consider an array class, e.g. Y[][], where Y is a subclass of X.
606// Y[][] = Y[][] --> true (identity)
607// X[][] = Y[][] --> true (element superclass)
608// Y = Y[][] --> false
609// Y[] = Y[][] --> false
610// Object = Y[][] --> true (everything is an object)
611// Object[] = Y[][] --> true
612// Object[][] = Y[][] --> true
613// Object[][][] = Y[][] --> false (too many []s)
614// Serializable = Y[][] --> true (all arrays are Serializable)
615// Serializable[] = Y[][] --> true
616// Serializable[][] = Y[][] --> false (unless Y is Serializable)
617//
618// Don't forget about primitive types.
619// int[] instanceof Object[] --> false
620//
621bool Class::IsArrayAssignableFromArray(const Class* klass) const {
Brian Carlstromb63ec392011-08-27 17:38:27 -0700622 DCHECK(IsArrayClass());
623 DCHECK(klass->IsArrayClass());
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700624 DCHECK_GT(GetArrayRank(), 0);
625 DCHECK_GT(klass->GetArrayRank(), 0);
626 DCHECK(GetComponentType() != NULL);
627 DCHECK(klass->GetComponentType() != NULL);
628 if (GetArrayRank() > klass->GetArrayRank()) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700629 // Too many []s.
630 return false;
631 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700632 if (GetArrayRank() == klass->GetArrayRank()) {
633 return GetComponentType()->IsAssignableFrom(klass->GetComponentType());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700634 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700635 DCHECK_LT(GetArrayRank(), klass->GetArrayRank());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700636 // The thing we might be assignable from has more dimensions. We
637 // must be an Object or array of Object, or a standard array
638 // interface or array of standard array interfaces (the standard
639 // interfaces being java/lang/Cloneable and java/io/Serializable).
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700640 if (GetComponentType()->IsInterface()) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700641 // See if we implement our component type. We know the
642 // base element is an interface; if the array class implements
643 // it, we know it's a standard array interface.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700644 return Implements(GetComponentType());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700645 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700646 // See if this is an array of Object, Object[], etc.
647 return GetComponentType()->IsObjectClass();
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700648}
649
650bool Class::IsAssignableFromArray(const Class* klass) const {
651 DCHECK(!IsInterface()); // handled first in IsAssignableFrom
Brian Carlstromb63ec392011-08-27 17:38:27 -0700652 DCHECK(klass->IsArrayClass());
653 if (!IsArrayClass()) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700654 // If "this" is not also an array, it must be Object.
655 // klass's super should be java_lang_Object, since it is an array.
656 Class* java_lang_Object = klass->GetSuperClass();
657 DCHECK(java_lang_Object != NULL);
658 DCHECK(java_lang_Object->GetSuperClass() == NULL);
659 return this == java_lang_Object;
660 }
661 return IsArrayAssignableFromArray(klass);
662}
663
664bool Class::IsSubClass(const Class* klass) const {
665 DCHECK(!IsInterface());
Brian Carlstromb63ec392011-08-27 17:38:27 -0700666 DCHECK(!klass->IsArrayClass());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700667 const Class* current = this;
668 do {
669 if (current == klass) {
670 return true;
671 }
672 current = current->GetSuperClass();
673 } while (current != NULL);
674 return false;
675}
676
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700677bool Class::IsInSamePackage(const String* descriptor_string_1,
678 const String* descriptor_string_2) {
679 const std::string descriptor1(descriptor_string_1->ToModifiedUtf8());
680 const std::string descriptor2(descriptor_string_2->ToModifiedUtf8());
681
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700682 size_t i = 0;
683 while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
684 ++i;
685 }
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700686 if (descriptor1.find('/', i) != StringPiece::npos ||
687 descriptor2.find('/', i) != StringPiece::npos) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700688 return false;
689 } else {
690 return true;
691 }
692}
693
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700694#if 0
Ian Rogersb033c752011-07-20 12:22:35 -0700695bool Class::IsInSamePackage(const StringPiece& descriptor1,
696 const StringPiece& descriptor2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700697 size_t size = std::min(descriptor1.size(), descriptor2.size());
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700698 std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos;
Ian Rogersb033c752011-07-20 12:22:35 -0700699 pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size,
700 descriptor2.begin());
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700701 return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos);
702}
703#endif
704
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700705bool Class::IsInSamePackage(const Class* that) const {
706 const Class* klass1 = this;
707 const Class* klass2 = that;
708 if (klass1 == klass2) {
709 return true;
710 }
711 // Class loaders must match.
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700712 if (klass1->GetClassLoader() != klass2->GetClassLoader()) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700713 return false;
714 }
715 // Arrays are in the same package when their element classes are.
Brian Carlstromb63ec392011-08-27 17:38:27 -0700716 if (klass1->IsArrayClass()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700717 klass1 = klass1->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700718 }
Brian Carlstromb63ec392011-08-27 17:38:27 -0700719 if (klass2->IsArrayClass()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700720 klass2 = klass2->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700721 }
722 // Compare the package part of the descriptor string.
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700723 return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700724}
725
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700726const ClassLoader* Class::GetClassLoader() const {
727 return GetFieldObject<const ClassLoader*>(
728 OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
Brian Carlstromb9edb842011-08-28 16:31:06 -0700729}
730
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700731void Class::SetClassLoader(const ClassLoader* new_cl) {
732 ClassLoader* new_class_loader = const_cast<ClassLoader*>(new_cl);
733 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_),
734 new_class_loader, false);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700735}
736
Brian Carlstrom30b94452011-08-25 21:35:26 -0700737Method* Class::FindVirtualMethodForInterface(Method* method) {
738 Class* declaring_class = method->GetDeclaringClass();
739 DCHECK(declaring_class->IsInterface());
740 // TODO cache to improve lookup speed
741 for (size_t i = 0; i < iftable_count_; i++) {
742 InterfaceEntry& interface_entry = iftable_[i];
743 if (interface_entry.GetInterface() == declaring_class) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700744 return GetVTable()->Get(
745 interface_entry.GetMethodIndexArray()[method->GetMethodIndex()]);
Brian Carlstrom30b94452011-08-25 21:35:26 -0700746 }
747 }
748 UNIMPLEMENTED(FATAL) << "Need to throw an error of some kind";
749 return NULL;
750}
751
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700752Method* Class::FindDeclaredDirectMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700753 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700754 for (size_t i = 0; i < NumDirectMethods(); ++i) {
Ian Rogersb033c752011-07-20 12:22:35 -0700755 Method* method = GetDirectMethod(i);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700756 if (method->GetName()->Equals(name) &&
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700757 method->GetSignature()->Equals(signature)) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700758 return method;
Ian Rogersb033c752011-07-20 12:22:35 -0700759 }
760 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700761 return NULL;
Ian Rogersb033c752011-07-20 12:22:35 -0700762}
763
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700764Method* Class::FindDirectMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700765 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700766 for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700767 Method* method = klass->FindDeclaredDirectMethod(name, signature);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700768 if (method != NULL) {
769 return method;
770 }
771 }
772 return NULL;
773}
774
775Method* Class::FindDeclaredVirtualMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700776 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700777 for (size_t i = 0; i < NumVirtualMethods(); ++i) {
Ian Rogersb033c752011-07-20 12:22:35 -0700778 Method* method = GetVirtualMethod(i);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700779 if (method->GetName()->Equals(name) &&
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700780 method->GetSignature()->Equals(signature)) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700781 return method;
Ian Rogersb033c752011-07-20 12:22:35 -0700782 }
783 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700784 return NULL;
Ian Rogersb033c752011-07-20 12:22:35 -0700785}
786
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700787Method* Class::FindVirtualMethod(const StringPiece& name,
788 const StringPiece& descriptor) {
789 for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
790 Method* method = klass->FindDeclaredVirtualMethod(name, descriptor);
791 if (method != NULL) {
792 return method;
793 }
794 }
795 return NULL;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700796}
797
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700798Field* Class::FindDeclaredInstanceField(const StringPiece& name, Class* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700799 // Is the field in this class?
800 // Interfaces are not relevant because they can't contain instance fields.
801 for (size_t i = 0; i < NumInstanceFields(); ++i) {
802 Field* f = GetInstanceField(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700803 if (f->GetName()->Equals(name) && type == f->GetType()) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700804 return f;
805 }
806 }
807 return NULL;
808}
809
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700810Field* Class::FindInstanceField(const StringPiece& name, Class* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700811 // Is the field in this class, or any of its superclasses?
812 // Interfaces are not relevant because they can't contain instance fields.
813 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700814 Field* f = c->FindDeclaredInstanceField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -0700815 if (f != NULL) {
816 return f;
817 }
818 }
819 return NULL;
820}
821
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700822Field* Class::FindDeclaredStaticField(const StringPiece& name, Class* type) {
823 DCHECK(type != NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -0700824 for (size_t i = 0; i < NumStaticFields(); ++i) {
825 Field* f = GetStaticField(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700826 if (f->GetName()->Equals(name) && f->GetType() == type) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700827 return f;
828 }
829 }
830 return NULL;
831}
832
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700833Field* Class::FindStaticField(const StringPiece& name, Class* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700834 // Is the field in this class (or its interfaces), or any of its
835 // superclasses (or their interfaces)?
836 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
837 // Is the field in this class?
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700838 Field* f = c->FindDeclaredStaticField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -0700839 if (f != NULL) {
840 return f;
841 }
842
843 // Is this field in any of this class' interfaces?
844 for (size_t i = 0; i < c->NumInterfaces(); ++i) {
845 Class* interface = c->GetInterface(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700846 f = interface->FindDeclaredStaticField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -0700847 if (f != NULL) {
848 return f;
849 }
850 }
851 }
852 return NULL;
853}
854
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700855Array* Array::Alloc(Class* array_class, int32_t component_count, size_t component_size) {
856 DCHECK_GE(component_count, 0);
857 DCHECK(array_class->IsArrayClass());
858 size_t size = SizeOf(component_count, component_size);
859 Array* array = down_cast<Array*>(Heap::AllocObject(array_class, size));
860 if (array != NULL) {
861 DCHECK(array->IsArrayInstance());
862 array->SetLength(component_count);
863 }
864 return array;
865}
866
867Array* Array::Alloc(Class* array_class, int32_t component_count) {
868 return Alloc(array_class, component_count, array_class->GetComponentSize());
869}
870
871Array* Array::AllocFromCode(uint32_t type_idx, Method* method, int32_t component_count) {
872 // TODO: throw on negative component_count
873 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
874 if (klass == NULL) {
875 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
876 if (klass == NULL || !klass->IsArrayClass()) {
877 UNIMPLEMENTED(FATAL) << "throw an error";
878 return NULL;
879 }
880 }
881 return Array::Alloc(klass, component_count);
882}
883
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700884template<typename T>
885PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) {
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700886 DCHECK(array_class_ != NULL);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700887 Array* raw_array = Array::Alloc(array_class_, length, sizeof(T));
888 return down_cast<PrimitiveArray<T>*>(raw_array);
889}
890
891template <typename T> Class* PrimitiveArray<T>::array_class_ = NULL;
892
893// Explicitly instantiate all the primitive array types.
894template class PrimitiveArray<uint8_t>; // BooleanArray
895template class PrimitiveArray<int8_t>; // ByteArray
896template class PrimitiveArray<uint16_t>; // CharArray
897template class PrimitiveArray<double>; // DoubleArray
898template class PrimitiveArray<float>; // FloatArray
899template class PrimitiveArray<int32_t>; // IntArray
900template class PrimitiveArray<int64_t>; // LongArray
901template class PrimitiveArray<int16_t>; // ShortArray
902
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700903// TODO: get global references for these
904Class* String::java_lang_String_ = NULL;
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700905
Brian Carlstroma663ea52011-08-19 23:33:41 -0700906void String::SetClass(Class* java_lang_String) {
907 CHECK(java_lang_String_ == NULL);
908 CHECK(java_lang_String != NULL);
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700909 java_lang_String_ = java_lang_String;
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700910}
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700911
Brian Carlstroma663ea52011-08-19 23:33:41 -0700912void String::ResetClass() {
913 CHECK(java_lang_String_ != NULL);
914 java_lang_String_ = NULL;
915}
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700916
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700917const String* String::Intern() const {
918 return Runtime::Current()->GetInternTable()->InternWeak(this);
919}
920
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700921int32_t String::GetHashCode() const {
922 int32_t result = GetField32(
923 OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false);
924 DCHECK(result != 0 ||
925 ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0);
926 return result;
927}
928
929int32_t String::GetLength() const {
930 int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), false);
931 DCHECK(result >= 0 && result <= GetCharArray()->GetLength());
932 return result;
933}
934
935uint16_t String::CharAt(int32_t index) const {
936 // TODO: do we need this? Equals is the only caller, and could
937 // bounds check itself.
938 if (index < 0 || index >= count_) {
939 Thread* self = Thread::Current();
940 self->ThrowNewException("Ljava/lang/StringIndexOutOfBoundsException;",
941 "length=%i; index=%i", count_, index);
942 return 0;
943 }
944 return GetCharArray()->Get(index + GetOffset());
945}
946
947String* String::AllocFromUtf16(int32_t utf16_length,
948 const uint16_t* utf16_data_in,
949 int32_t hash_code) {
950 String* string = Alloc(GetJavaLangString(), utf16_length);
951 // TODO: use 16-bit wide memset variant
952 CharArray* array = const_cast<CharArray*>(string->GetCharArray());
953 for (int i = 0; i < utf16_length; i++) {
954 array->Set(i, utf16_data_in[i]);
955 }
956 if (hash_code != 0) {
957 string->SetHashCode(hash_code);
958 } else {
959 string->ComputeHashCode();
960 }
961 return string;
962}
963
964String* String::AllocFromModifiedUtf8(const char* utf) {
965 size_t char_count = CountModifiedUtf8Chars(utf);
966 return AllocFromModifiedUtf8(char_count, utf);
967}
968
969String* String::AllocFromModifiedUtf8(int32_t utf16_length,
970 const char* utf8_data_in) {
971 String* string = Alloc(GetJavaLangString(), utf16_length);
972 uint16_t* utf16_data_out =
973 const_cast<uint16_t*>(string->GetCharArray()->GetData());
974 ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in);
975 string->ComputeHashCode();
976 return string;
977}
978
979String* String::Alloc(Class* java_lang_String, int32_t utf16_length) {
980 return Alloc(java_lang_String, CharArray::Alloc(utf16_length));
981}
982
983String* String::Alloc(Class* java_lang_String, CharArray* array) {
984 String* string = down_cast<String*>(java_lang_String->AllocObject());
985 string->SetArray(array);
986 string->SetCount(array->GetLength());
987 return string;
988}
989
990bool String::Equals(const String* that) const {
991 if (this == that) {
992 // Quick reference equality test
993 return true;
994 } else if (that == NULL) {
995 // Null isn't an instanceof anything
996 return false;
997 } else if (this->GetLength() != that->GetLength()) {
998 // Quick length inequality test
999 return false;
1000 } else {
1001 // NB don't short circuit on hash code as we're presumably here as the
1002 // hash code was already equal
1003 for (int32_t i = 0; i < that->GetLength(); ++i) {
1004 if (this->CharAt(i) != that->CharAt(i)) {
1005 return false;
1006 }
1007 }
1008 return true;
1009 }
1010}
1011
1012bool String::Equals(const uint16_t* that_chars, int32_t that_offset,
1013 int32_t that_length) const {
1014 if (this->GetLength() != that_length) {
1015 return false;
1016 } else {
1017 for (int32_t i = 0; i < that_length; ++i) {
1018 if (this->CharAt(i) != that_chars[that_offset + i]) {
1019 return false;
1020 }
1021 }
1022 return true;
1023 }
1024}
1025
1026bool String::Equals(const char* modified_utf8) const {
1027 for (int32_t i = 0; i < GetLength(); ++i) {
1028 uint16_t ch = GetUtf16FromUtf8(&modified_utf8);
1029 if (ch == '\0' || ch != CharAt(i)) {
1030 return false;
1031 }
1032 }
1033 return *modified_utf8 == '\0';
1034}
1035
1036bool String::Equals(const StringPiece& modified_utf8) const {
1037 // TODO: do not assume C-string representation.
1038 return Equals(modified_utf8.data());
1039}
1040
1041// Create a modified UTF-8 encoded std::string from a java/lang/String object.
1042std::string String::ToModifiedUtf8() const {
1043 const uint16_t* chars = GetCharArray()->GetData() + GetOffset();
1044 size_t byte_count(CountUtf8Bytes(chars, GetLength()));
1045 std::string result(byte_count, char(0));
1046 ConvertUtf16ToModifiedUtf8(&result[0], chars, GetLength());
1047 return result;
1048}
1049
Shih-wei Liao55df06b2011-08-26 14:39:27 -07001050Class* StackTraceElement::java_lang_StackTraceElement_ = NULL;
1051
1052void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) {
1053 CHECK(java_lang_StackTraceElement_ == NULL);
1054 CHECK(java_lang_StackTraceElement != NULL);
1055 java_lang_StackTraceElement_ = java_lang_StackTraceElement;
1056}
1057
1058void StackTraceElement::ResetClass() {
1059 CHECK(java_lang_StackTraceElement_ != NULL);
1060 java_lang_StackTraceElement_ = NULL;
1061}
1062
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001063StackTraceElement* StackTraceElement::Alloc(const String* declaring_class,
1064 const String* method_name,
1065 const String* file_name,
1066 int32_t line_number) {
1067 StackTraceElement* trace =
1068 down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject());
1069 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
1070 const_cast<String*>(declaring_class), false);
1071 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
1072 const_cast<String*>(method_name), false);
1073 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
1074 const_cast<String*>(file_name), false);
1075 trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_),
1076 line_number, false);
1077 return trace;
1078}
1079
Elliott Hughes1f359b02011-07-17 14:27:17 -07001080static const char* kClassStatusNames[] = {
1081 "Error",
1082 "NotReady",
1083 "Idx",
1084 "Loaded",
1085 "Resolved",
1086 "Verifying",
1087 "Verified",
1088 "Initializing",
1089 "Initialized"
1090};
1091std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) {
1092 if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
Brian Carlstromae3ac012011-07-27 01:30:28 -07001093 os << kClassStatusNames[rhs + 1];
Elliott Hughes1f359b02011-07-17 14:27:17 -07001094 } else {
Ian Rogersb033c752011-07-20 12:22:35 -07001095 os << "Class::Status[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -07001096 }
1097 return os;
1098}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001099
Carl Shapiro3ee755d2011-06-28 12:11:04 -07001100} // namespace art