blob: 5d99cb6a744a9237c3ed8d34a21abbadbc55e874 [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
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700465void Method::SetCode(ByteArray* code_array,
466 InstructionSet instruction_set) {
467 CHECK(!HasCode() || IsNative());
468 SetFieldPtr<ByteArray*>(OFFSET_OF_OBJECT_MEMBER(Method, code_array_), code_array, false);
469 int8_t* code = code_array->GetData();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700470 uintptr_t address = reinterpret_cast<uintptr_t>(code);
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700471 if (instruction_set == kThumb2) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700472 // Set the low-order bit so a BLX will switch to Thumb mode
473 address |= 0x1;
474 }
475 SetFieldPtr<uintptr_t>(OFFSET_OF_OBJECT_MEMBER(Method, code_), address, false);
476}
477
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700478void Method::SetInvokeStub(const ByteArray* invoke_stub_array) {
479 const InvokeStub* invoke_stub = reinterpret_cast<InvokeStub*>(invoke_stub_array->GetData());
480 SetFieldPtr<const ByteArray*>(
481 OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_array_), invoke_stub_array, false);
482 SetFieldPtr<const InvokeStub*>(
483 OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), invoke_stub, false);
484}
485
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700486void Class::SetStatus(Status new_status) {
487 CHECK(new_status > GetStatus() || new_status == kStatusError ||
488 Runtime::Current() == NULL); // no runtime implies we're not initialized
489 CHECK(sizeof(Status) == sizeof(uint32_t));
490 return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_),
491 new_status, false);
492}
493
494DexCache* Class::GetDexCache() const {
495 return GetFieldObject<DexCache*>(
496 OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
497}
498
499void Class::SetDexCache(DexCache* new_dex_cache) {
500 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_),
501 new_dex_cache, false);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700502}
503
Brian Carlstrom1f870082011-08-23 16:02:11 -0700504Object* Class::AllocObjectFromCode(uint32_t type_idx, Method* method) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700505 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700506 if (klass == NULL) {
507 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
508 if (klass == NULL) {
509 UNIMPLEMENTED(FATAL) << "throw an error";
510 return NULL;
511 }
512 }
Brian Carlstrom1f870082011-08-23 16:02:11 -0700513 return klass->AllocObject();
514}
515
516Object* Class::AllocObject() {
517 DCHECK(!IsAbstract());
518 return Heap::AllocObject(this, this->object_size_);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700519}
520
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700521void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
522 if (new_reference_offsets != CLASS_WALK_SUPER) {
523 // Sanity check that the number of bits set in the reference offset bitmap
524 // agrees with the number of references
525 Class* cur = this;
526 size_t cnt = 0;
527 while (cur) {
528 cnt += cur->NumReferenceInstanceFieldsDuringLinking();
529 cur = cur->GetSuperClass();
530 }
531 CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), cnt);
532 }
533 SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
534 new_reference_offsets, false);
535}
536
537void Class::SetReferenceStaticOffsets(uint32_t new_reference_offsets) {
538 if (new_reference_offsets != CLASS_WALK_SUPER) {
539 // Sanity check that the number of bits set in the reference offset bitmap
540 // agrees with the number of references
541 CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets),
542 NumReferenceStaticFieldsDuringLinking());
543 }
544 SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_),
545 new_reference_offsets, false);
546}
547
548size_t Class::PrimitiveSize() const {
549 switch (GetPrimitiveType()) {
550 case kPrimBoolean:
551 case kPrimByte:
552 case kPrimChar:
553 case kPrimShort:
554 case kPrimInt:
555 case kPrimFloat:
556 return sizeof(int32_t);
557 case kPrimLong:
558 case kPrimDouble:
559 return sizeof(int64_t);
560 default:
561 LOG(FATAL) << "Primitive type size calculation on invalid type " << this;
562 return 0;
563 }
564}
565
566size_t Class::GetTypeSize(const String* descriptor) {
567 switch (descriptor->CharAt(0)) {
568 case 'B': return 1; // byte
569 case 'C': return 2; // char
570 case 'D': return 8; // double
571 case 'F': return 4; // float
572 case 'I': return 4; // int
573 case 'J': return 8; // long
574 case 'S': return 2; // short
575 case 'Z': return 1; // boolean
576 case 'L': return sizeof(Object*);
577 case '[': return sizeof(Array*);
578 default:
579 LOG(ERROR) << "Unknown type " << descriptor;
580 return 0;
581 }
Elliott Hughesbf86d042011-08-31 17:53:14 -0700582}
583
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700584bool Class::Implements(const Class* klass) const {
585 DCHECK(klass != NULL);
586 DCHECK(klass->IsInterface());
587 // All interfaces implemented directly and by our superclass, and
588 // recursively all super-interfaces of those interfaces, are listed
589 // in iftable_, so we can just do a linear scan through that.
590 for (size_t i = 0; i < iftable_count_; i++) {
Brian Carlstrom30b94452011-08-25 21:35:26 -0700591 if (iftable_[i].GetInterface() == klass) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700592 return true;
593 }
594 }
595 return false;
596}
597
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700598bool Class::CanPutArrayElement(const Class* object_class, const Class* array_class) {
599 if (object_class->IsArrayClass()) {
600 return array_class->IsArrayAssignableFromArray(object_class);
601 } else {
602 return array_class->GetComponentType()->IsAssignableFrom(object_class);
603 }
604}
605
606void Class::CanPutArrayElementFromCode(const Class* object_class, const Class* array_class) {
607 if (!CanPutArrayElement(object_class, array_class)) {
608 LOG(ERROR) << "Can't put a " << PrettyDescriptor(object_class->GetDescriptor())
609 << " into a " << PrettyDescriptor(array_class->GetDescriptor());
610 UNIMPLEMENTED(FATAL) << "need to throw ArrayStoreException and unwind stack";
611 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700612}
613
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700614// Determine whether "this" is assignable from "klazz", where both of these
615// are array classes.
616//
617// Consider an array class, e.g. Y[][], where Y is a subclass of X.
618// Y[][] = Y[][] --> true (identity)
619// X[][] = Y[][] --> true (element superclass)
620// Y = Y[][] --> false
621// Y[] = Y[][] --> false
622// Object = Y[][] --> true (everything is an object)
623// Object[] = Y[][] --> true
624// Object[][] = Y[][] --> true
625// Object[][][] = Y[][] --> false (too many []s)
626// Serializable = Y[][] --> true (all arrays are Serializable)
627// Serializable[] = Y[][] --> true
628// Serializable[][] = Y[][] --> false (unless Y is Serializable)
629//
630// Don't forget about primitive types.
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700631// Object[] = int[] --> false
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700632//
633bool Class::IsArrayAssignableFromArray(const Class* klass) const {
Brian Carlstromb63ec392011-08-27 17:38:27 -0700634 DCHECK(IsArrayClass());
635 DCHECK(klass->IsArrayClass());
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700636 DCHECK_GT(GetArrayRank(), 0);
637 DCHECK_GT(klass->GetArrayRank(), 0);
638 DCHECK(GetComponentType() != NULL);
639 DCHECK(klass->GetComponentType() != NULL);
640 if (GetArrayRank() > klass->GetArrayRank()) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700641 // Too many []s.
642 return false;
643 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700644 if (GetArrayRank() == klass->GetArrayRank()) {
645 return GetComponentType()->IsAssignableFrom(klass->GetComponentType());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700646 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700647 DCHECK_LT(GetArrayRank(), klass->GetArrayRank());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700648 // The thing we might be assignable from has more dimensions. We
649 // must be an Object or array of Object, or a standard array
650 // interface or array of standard array interfaces (the standard
651 // interfaces being java/lang/Cloneable and java/io/Serializable).
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700652 if (GetComponentType()->IsInterface()) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700653 // See if we implement our component type. We know the
654 // base element is an interface; if the array class implements
655 // it, we know it's a standard array interface.
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700656 return Implements(GetComponentType());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700657 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700658 // See if this is an array of Object, Object[], etc.
659 return GetComponentType()->IsObjectClass();
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700660}
661
662bool Class::IsAssignableFromArray(const Class* klass) const {
663 DCHECK(!IsInterface()); // handled first in IsAssignableFrom
Brian Carlstromb63ec392011-08-27 17:38:27 -0700664 DCHECK(klass->IsArrayClass());
665 if (!IsArrayClass()) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700666 // If "this" is not also an array, it must be Object.
667 // klass's super should be java_lang_Object, since it is an array.
668 Class* java_lang_Object = klass->GetSuperClass();
669 DCHECK(java_lang_Object != NULL);
670 DCHECK(java_lang_Object->GetSuperClass() == NULL);
671 return this == java_lang_Object;
672 }
673 return IsArrayAssignableFromArray(klass);
674}
675
676bool Class::IsSubClass(const Class* klass) const {
677 DCHECK(!IsInterface());
Brian Carlstromb63ec392011-08-27 17:38:27 -0700678 DCHECK(!klass->IsArrayClass());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700679 const Class* current = this;
680 do {
681 if (current == klass) {
682 return true;
683 }
684 current = current->GetSuperClass();
685 } while (current != NULL);
686 return false;
687}
688
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700689bool Class::IsInSamePackage(const String* descriptor_string_1,
690 const String* descriptor_string_2) {
691 const std::string descriptor1(descriptor_string_1->ToModifiedUtf8());
692 const std::string descriptor2(descriptor_string_2->ToModifiedUtf8());
693
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700694 size_t i = 0;
695 while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
696 ++i;
697 }
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700698 if (descriptor1.find('/', i) != StringPiece::npos ||
699 descriptor2.find('/', i) != StringPiece::npos) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700700 return false;
701 } else {
702 return true;
703 }
704}
705
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700706#if 0
Ian Rogersb033c752011-07-20 12:22:35 -0700707bool Class::IsInSamePackage(const StringPiece& descriptor1,
708 const StringPiece& descriptor2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700709 size_t size = std::min(descriptor1.size(), descriptor2.size());
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700710 std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos;
Ian Rogersb033c752011-07-20 12:22:35 -0700711 pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size,
712 descriptor2.begin());
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700713 return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos);
714}
715#endif
716
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700717bool Class::IsInSamePackage(const Class* that) const {
718 const Class* klass1 = this;
719 const Class* klass2 = that;
720 if (klass1 == klass2) {
721 return true;
722 }
723 // Class loaders must match.
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700724 if (klass1->GetClassLoader() != klass2->GetClassLoader()) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700725 return false;
726 }
727 // Arrays are in the same package when their element classes are.
Brian Carlstromb63ec392011-08-27 17:38:27 -0700728 if (klass1->IsArrayClass()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700729 klass1 = klass1->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700730 }
Brian Carlstromb63ec392011-08-27 17:38:27 -0700731 if (klass2->IsArrayClass()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700732 klass2 = klass2->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700733 }
734 // Compare the package part of the descriptor string.
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700735 return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700736}
737
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700738const ClassLoader* Class::GetClassLoader() const {
739 return GetFieldObject<const ClassLoader*>(
740 OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
Brian Carlstromb9edb842011-08-28 16:31:06 -0700741}
742
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700743void Class::SetClassLoader(const ClassLoader* new_cl) {
744 ClassLoader* new_class_loader = const_cast<ClassLoader*>(new_cl);
745 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_),
746 new_class_loader, false);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700747}
748
Brian Carlstrom30b94452011-08-25 21:35:26 -0700749Method* Class::FindVirtualMethodForInterface(Method* method) {
750 Class* declaring_class = method->GetDeclaringClass();
751 DCHECK(declaring_class->IsInterface());
752 // TODO cache to improve lookup speed
753 for (size_t i = 0; i < iftable_count_; i++) {
754 InterfaceEntry& interface_entry = iftable_[i];
755 if (interface_entry.GetInterface() == declaring_class) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700756 return GetVTable()->Get(
757 interface_entry.GetMethodIndexArray()[method->GetMethodIndex()]);
Brian Carlstrom30b94452011-08-25 21:35:26 -0700758 }
759 }
760 UNIMPLEMENTED(FATAL) << "Need to throw an error of some kind";
761 return NULL;
762}
763
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700764Method* Class::FindDeclaredDirectMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700765 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700766 for (size_t i = 0; i < NumDirectMethods(); ++i) {
Ian Rogersb033c752011-07-20 12:22:35 -0700767 Method* method = GetDirectMethod(i);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700768 if (method->GetName()->Equals(name) &&
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700769 method->GetSignature()->Equals(signature)) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700770 return method;
Ian Rogersb033c752011-07-20 12:22:35 -0700771 }
772 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700773 return NULL;
Ian Rogersb033c752011-07-20 12:22:35 -0700774}
775
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700776Method* Class::FindDirectMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700777 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700778 for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700779 Method* method = klass->FindDeclaredDirectMethod(name, signature);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700780 if (method != NULL) {
781 return method;
782 }
783 }
784 return NULL;
785}
786
787Method* Class::FindDeclaredVirtualMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700788 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700789 for (size_t i = 0; i < NumVirtualMethods(); ++i) {
Ian Rogersb033c752011-07-20 12:22:35 -0700790 Method* method = GetVirtualMethod(i);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700791 if (method->GetName()->Equals(name) &&
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700792 method->GetSignature()->Equals(signature)) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700793 return method;
Ian Rogersb033c752011-07-20 12:22:35 -0700794 }
795 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700796 return NULL;
Ian Rogersb033c752011-07-20 12:22:35 -0700797}
798
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700799Method* Class::FindVirtualMethod(const StringPiece& name,
800 const StringPiece& descriptor) {
801 for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
802 Method* method = klass->FindDeclaredVirtualMethod(name, descriptor);
803 if (method != NULL) {
804 return method;
805 }
806 }
807 return NULL;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700808}
809
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700810Field* Class::FindDeclaredInstanceField(const StringPiece& name, Class* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700811 // Is the field in this class?
812 // Interfaces are not relevant because they can't contain instance fields.
813 for (size_t i = 0; i < NumInstanceFields(); ++i) {
814 Field* f = GetInstanceField(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700815 if (f->GetName()->Equals(name) && type == f->GetType()) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700816 return f;
817 }
818 }
819 return NULL;
820}
821
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700822Field* Class::FindInstanceField(const StringPiece& name, Class* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700823 // Is the field in this class, or any of its superclasses?
824 // Interfaces are not relevant because they can't contain instance fields.
825 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700826 Field* f = c->FindDeclaredInstanceField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -0700827 if (f != NULL) {
828 return f;
829 }
830 }
831 return NULL;
832}
833
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700834Field* Class::FindDeclaredStaticField(const StringPiece& name, Class* type) {
835 DCHECK(type != NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -0700836 for (size_t i = 0; i < NumStaticFields(); ++i) {
837 Field* f = GetStaticField(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700838 if (f->GetName()->Equals(name) && f->GetType() == type) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700839 return f;
840 }
841 }
842 return NULL;
843}
844
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700845Field* Class::FindStaticField(const StringPiece& name, Class* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -0700846 // Is the field in this class (or its interfaces), or any of its
847 // superclasses (or their interfaces)?
848 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
849 // Is the field in this class?
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700850 Field* f = c->FindDeclaredStaticField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -0700851 if (f != NULL) {
852 return f;
853 }
854
855 // Is this field in any of this class' interfaces?
856 for (size_t i = 0; i < c->NumInterfaces(); ++i) {
857 Class* interface = c->GetInterface(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700858 f = interface->FindDeclaredStaticField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -0700859 if (f != NULL) {
860 return f;
861 }
862 }
863 }
864 return NULL;
865}
866
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700867Array* Array::Alloc(Class* array_class, int32_t component_count, size_t component_size) {
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700868 DCHECK(array_class != NULL);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700869 DCHECK_GE(component_count, 0);
870 DCHECK(array_class->IsArrayClass());
871 size_t size = SizeOf(component_count, component_size);
872 Array* array = down_cast<Array*>(Heap::AllocObject(array_class, size));
873 if (array != NULL) {
874 DCHECK(array->IsArrayInstance());
875 array->SetLength(component_count);
876 }
877 return array;
878}
879
880Array* Array::Alloc(Class* array_class, int32_t component_count) {
881 return Alloc(array_class, component_count, array_class->GetComponentSize());
882}
883
884Array* Array::AllocFromCode(uint32_t type_idx, Method* method, int32_t component_count) {
885 // TODO: throw on negative component_count
886 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
887 if (klass == NULL) {
888 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
889 if (klass == NULL || !klass->IsArrayClass()) {
890 UNIMPLEMENTED(FATAL) << "throw an error";
891 return NULL;
892 }
893 }
894 return Array::Alloc(klass, component_count);
895}
896
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700897template<typename T>
898PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) {
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700899 DCHECK(array_class_ != NULL);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700900 Array* raw_array = Array::Alloc(array_class_, length, sizeof(T));
901 return down_cast<PrimitiveArray<T>*>(raw_array);
902}
903
904template <typename T> Class* PrimitiveArray<T>::array_class_ = NULL;
905
906// Explicitly instantiate all the primitive array types.
907template class PrimitiveArray<uint8_t>; // BooleanArray
908template class PrimitiveArray<int8_t>; // ByteArray
909template class PrimitiveArray<uint16_t>; // CharArray
910template class PrimitiveArray<double>; // DoubleArray
911template class PrimitiveArray<float>; // FloatArray
912template class PrimitiveArray<int32_t>; // IntArray
913template class PrimitiveArray<int64_t>; // LongArray
914template class PrimitiveArray<int16_t>; // ShortArray
915
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700916// TODO: get global references for these
917Class* String::java_lang_String_ = NULL;
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700918
Brian Carlstroma663ea52011-08-19 23:33:41 -0700919void String::SetClass(Class* java_lang_String) {
920 CHECK(java_lang_String_ == NULL);
921 CHECK(java_lang_String != NULL);
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700922 java_lang_String_ = java_lang_String;
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700923}
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700924
Brian Carlstroma663ea52011-08-19 23:33:41 -0700925void String::ResetClass() {
926 CHECK(java_lang_String_ != NULL);
927 java_lang_String_ = NULL;
928}
Jesse Wilsonf7e85a52011-08-01 18:45:58 -0700929
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700930const String* String::Intern() const {
931 return Runtime::Current()->GetInternTable()->InternWeak(this);
932}
933
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700934int32_t String::GetHashCode() const {
935 int32_t result = GetField32(
936 OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false);
937 DCHECK(result != 0 ||
938 ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0);
939 return result;
940}
941
942int32_t String::GetLength() const {
943 int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), false);
944 DCHECK(result >= 0 && result <= GetCharArray()->GetLength());
945 return result;
946}
947
948uint16_t String::CharAt(int32_t index) const {
949 // TODO: do we need this? Equals is the only caller, and could
950 // bounds check itself.
951 if (index < 0 || index >= count_) {
952 Thread* self = Thread::Current();
953 self->ThrowNewException("Ljava/lang/StringIndexOutOfBoundsException;",
954 "length=%i; index=%i", count_, index);
955 return 0;
956 }
957 return GetCharArray()->Get(index + GetOffset());
958}
959
960String* String::AllocFromUtf16(int32_t utf16_length,
961 const uint16_t* utf16_data_in,
962 int32_t hash_code) {
963 String* string = Alloc(GetJavaLangString(), utf16_length);
964 // TODO: use 16-bit wide memset variant
965 CharArray* array = const_cast<CharArray*>(string->GetCharArray());
966 for (int i = 0; i < utf16_length; i++) {
967 array->Set(i, utf16_data_in[i]);
968 }
969 if (hash_code != 0) {
970 string->SetHashCode(hash_code);
971 } else {
972 string->ComputeHashCode();
973 }
974 return string;
975}
976
977String* String::AllocFromModifiedUtf8(const char* utf) {
978 size_t char_count = CountModifiedUtf8Chars(utf);
979 return AllocFromModifiedUtf8(char_count, utf);
980}
981
982String* String::AllocFromModifiedUtf8(int32_t utf16_length,
983 const char* utf8_data_in) {
984 String* string = Alloc(GetJavaLangString(), utf16_length);
985 uint16_t* utf16_data_out =
986 const_cast<uint16_t*>(string->GetCharArray()->GetData());
987 ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in);
988 string->ComputeHashCode();
989 return string;
990}
991
992String* String::Alloc(Class* java_lang_String, int32_t utf16_length) {
993 return Alloc(java_lang_String, CharArray::Alloc(utf16_length));
994}
995
996String* String::Alloc(Class* java_lang_String, CharArray* array) {
997 String* string = down_cast<String*>(java_lang_String->AllocObject());
998 string->SetArray(array);
999 string->SetCount(array->GetLength());
1000 return string;
1001}
1002
1003bool String::Equals(const String* that) const {
1004 if (this == that) {
1005 // Quick reference equality test
1006 return true;
1007 } else if (that == NULL) {
1008 // Null isn't an instanceof anything
1009 return false;
1010 } else if (this->GetLength() != that->GetLength()) {
1011 // Quick length inequality test
1012 return false;
1013 } else {
1014 // NB don't short circuit on hash code as we're presumably here as the
1015 // hash code was already equal
1016 for (int32_t i = 0; i < that->GetLength(); ++i) {
1017 if (this->CharAt(i) != that->CharAt(i)) {
1018 return false;
1019 }
1020 }
1021 return true;
1022 }
1023}
1024
1025bool String::Equals(const uint16_t* that_chars, int32_t that_offset,
1026 int32_t that_length) const {
1027 if (this->GetLength() != that_length) {
1028 return false;
1029 } else {
1030 for (int32_t i = 0; i < that_length; ++i) {
1031 if (this->CharAt(i) != that_chars[that_offset + i]) {
1032 return false;
1033 }
1034 }
1035 return true;
1036 }
1037}
1038
1039bool String::Equals(const char* modified_utf8) const {
1040 for (int32_t i = 0; i < GetLength(); ++i) {
1041 uint16_t ch = GetUtf16FromUtf8(&modified_utf8);
1042 if (ch == '\0' || ch != CharAt(i)) {
1043 return false;
1044 }
1045 }
1046 return *modified_utf8 == '\0';
1047}
1048
1049bool String::Equals(const StringPiece& modified_utf8) const {
1050 // TODO: do not assume C-string representation.
1051 return Equals(modified_utf8.data());
1052}
1053
1054// Create a modified UTF-8 encoded std::string from a java/lang/String object.
1055std::string String::ToModifiedUtf8() const {
1056 const uint16_t* chars = GetCharArray()->GetData() + GetOffset();
1057 size_t byte_count(CountUtf8Bytes(chars, GetLength()));
1058 std::string result(byte_count, char(0));
1059 ConvertUtf16ToModifiedUtf8(&result[0], chars, GetLength());
1060 return result;
1061}
1062
Shih-wei Liao55df06b2011-08-26 14:39:27 -07001063Class* StackTraceElement::java_lang_StackTraceElement_ = NULL;
1064
1065void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) {
1066 CHECK(java_lang_StackTraceElement_ == NULL);
1067 CHECK(java_lang_StackTraceElement != NULL);
1068 java_lang_StackTraceElement_ = java_lang_StackTraceElement;
1069}
1070
1071void StackTraceElement::ResetClass() {
1072 CHECK(java_lang_StackTraceElement_ != NULL);
1073 java_lang_StackTraceElement_ = NULL;
1074}
1075
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001076StackTraceElement* StackTraceElement::Alloc(const String* declaring_class,
1077 const String* method_name,
1078 const String* file_name,
1079 int32_t line_number) {
1080 StackTraceElement* trace =
1081 down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject());
1082 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
1083 const_cast<String*>(declaring_class), false);
1084 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
1085 const_cast<String*>(method_name), false);
1086 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
1087 const_cast<String*>(file_name), false);
1088 trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_),
1089 line_number, false);
1090 return trace;
1091}
1092
Elliott Hughes1f359b02011-07-17 14:27:17 -07001093static const char* kClassStatusNames[] = {
1094 "Error",
1095 "NotReady",
1096 "Idx",
1097 "Loaded",
1098 "Resolved",
1099 "Verifying",
1100 "Verified",
1101 "Initializing",
1102 "Initialized"
1103};
1104std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) {
1105 if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
Brian Carlstromae3ac012011-07-27 01:30:28 -07001106 os << kClassStatusNames[rhs + 1];
Elliott Hughes1f359b02011-07-17 14:27:17 -07001107 } else {
Ian Rogersb033c752011-07-20 12:22:35 -07001108 os << "Class::Status[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -07001109 }
1110 return os;
1111}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001112
Carl Shapiro3ee755d2011-06-28 12:11:04 -07001113} // namespace art