blob: 91c4b3d7935b6aea9099e6f5163bfde8fd63019f [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"
Elliott Hughes54e7df12011-09-16 11:47:04 -070013#include "dex_cache.h"
14#include "dex_file.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070015#include "globals.h"
Brian Carlstroma40f9bc2011-07-26 21:26:07 -070016#include "heap.h"
Elliott Hughescf4c6c42011-09-01 15:16:42 -070017#include "intern_table.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070018#include "logging.h"
Elliott Hughes54e7df12011-09-16 11:47:04 -070019#include "monitor.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070020#include "runtime.h"
Carl Shapiro3ee755d2011-06-28 12:11:04 -070021
22namespace art {
23
Elliott Hughes081be7f2011-09-18 16:50:26 -070024Object* Object::Clone() {
25 Class* c = GetClass();
26 DCHECK(!c->IsClassClass());
27
28 // Object::SizeOf gets the right size even if we're an array.
29 // Using c->AllocObject() here would be wrong.
30 size_t num_bytes = SizeOf();
31 Object* copy = Heap::AllocObject(c, num_bytes);
32 if (copy == NULL) {
33 return NULL;
34 }
35
36 // Copy instance data. We assume memcpy copies by words.
37 // TODO: expose and use move32.
38 byte* src_bytes = reinterpret_cast<byte*>(this);
39 byte* dst_bytes = reinterpret_cast<byte*>(copy);
40 size_t offset = sizeof(Object);
41 memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset);
42
43 // TODO: Mark the clone as finalizable if appropriate.
44// if (IS_CLASS_FLAG_SET(clazz, CLASS_ISFINALIZABLE)) {
45// dvmSetFinalizable(copy);
46// }
47
48 return copy;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070049}
50
Elliott Hughes5f791332011-09-15 17:45:30 -070051uint32_t Object::GetLockOwner() {
52 return Monitor::GetLockOwner(monitor_);
53}
54
Elliott Hughes081be7f2011-09-18 16:50:26 -070055bool Object::IsString() const {
56 // TODO use "klass_ == String::GetJavaLangString()" instead?
57 return GetClass() == GetClass()->GetDescriptor()->GetClass();
58}
59
Elliott Hughes5f791332011-09-15 17:45:30 -070060void Object::MonitorEnter(Thread* thread) {
61 Monitor::MonitorEnter(thread, this);
62}
63
64void Object::MonitorExit(Thread* thread) {
65 Monitor::MonitorExit(thread, this);
66}
67
68void Object::Notify() {
69 Monitor::Notify(Thread::Current(), this);
70}
71
72void Object::NotifyAll() {
73 Monitor::NotifyAll(Thread::Current(), this);
74}
75
76void Object::Wait(int64_t ms, int32_t ns) {
77 Monitor::Wait(Thread::Current(), this, ms, ns, true);
78}
79
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070080// TODO: get global references for these
81Class* Field::java_lang_reflect_Field_ = NULL;
82
83void Field::SetClass(Class* java_lang_reflect_Field) {
84 CHECK(java_lang_reflect_Field_ == NULL);
85 CHECK(java_lang_reflect_Field != NULL);
86 java_lang_reflect_Field_ = java_lang_reflect_Field;
87}
88
89void Field::ResetClass() {
90 CHECK(java_lang_reflect_Field_ != NULL);
91 java_lang_reflect_Field_ = NULL;
92}
93
94void Field::SetTypeIdx(uint32_t type_idx) {
95 SetField32(OFFSET_OF_OBJECT_MEMBER(Field, type_idx_), type_idx, false);
96}
97
98Class* Field::GetTypeDuringLinking() const {
99 // We are assured that the necessary primitive types are in the dex cache
100 // early during class linking
101 return GetDeclaringClass()->GetDexCache()->GetResolvedType(GetTypeIdx());
102}
103
104Class* Field::GetType() const {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700105 // Do full linkage (which sets dex cache value to speed next call)
106 return Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
107}
108
buzbee34cd9e52011-09-08 14:31:52 -0700109Field* Field::FindFieldFromCode(uint32_t field_idx, const Method* referrer) {
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700110 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
111 Field* f = class_linker->ResolveField(field_idx, referrer);
112 if (f != NULL) {
113 Class* c = f->GetDeclaringClass();
114 // If the class is already initializing, we must be inside <clinit>, or
115 // we'd still be waiting for the lock.
116 if (c->GetStatus() == Class::kStatusInitializing || class_linker->EnsureInitialized(c)) {
117 return f;
118 }
Brian Carlstromb63ec392011-08-27 17:38:27 -0700119 }
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700120 UNIMPLEMENTED(FATAL) << "throw an error and unwind";
121 return NULL;
122}
123
124uint32_t Field::Get32StaticFromCode(uint32_t field_idx, const Method* referrer) {
125 Field* field = FindFieldFromCode(field_idx, referrer);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700126 DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
127 return field->Get32(NULL);
128}
129void Field::Set32StaticFromCode(uint32_t field_idx, const Method* referrer, uint32_t new_value) {
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700130 Field* field = FindFieldFromCode(field_idx, referrer);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700131 DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
132 field->Set32(NULL, new_value);
133}
134uint64_t Field::Get64StaticFromCode(uint32_t field_idx, const Method* referrer) {
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700135 Field* field = FindFieldFromCode(field_idx, referrer);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700136 DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
137 return field->Get64(NULL);
138}
139void Field::Set64StaticFromCode(uint32_t field_idx, const Method* referrer, uint64_t new_value) {
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700140 Field* field = FindFieldFromCode(field_idx, referrer);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700141 DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
142 field->Set64(NULL, new_value);
143}
144Object* Field::GetObjStaticFromCode(uint32_t field_idx, const Method* referrer) {
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700145 Field* field = FindFieldFromCode(field_idx, referrer);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700146 DCHECK(!field->GetType()->IsPrimitive());
147 return field->GetObj(NULL);
148}
149void Field::SetObjStaticFromCode(uint32_t field_idx, const Method* referrer, Object* new_value) {
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700150 Field* field = FindFieldFromCode(field_idx, referrer);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700151 DCHECK(!field->GetType()->IsPrimitive());
152 field->SetObj(NULL, new_value);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700153}
154
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700155uint32_t Field::Get32(const Object* object) const {
156 CHECK((object == NULL) == IsStatic());
157 if (IsStatic()) {
158 object = declaring_class_;
159 }
160 return object->GetField32(GetOffset(), IsVolatile());
Elliott Hughes68f4fa02011-08-21 10:46:59 -0700161}
162
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700163void Field::Set32(Object* object, uint32_t new_value) const {
164 CHECK((object == NULL) == IsStatic());
165 if (IsStatic()) {
166 object = declaring_class_;
167 }
168 object->SetField32(GetOffset(), new_value, IsVolatile());
169}
170
171uint64_t Field::Get64(const Object* object) const {
172 CHECK((object == NULL) == IsStatic());
173 if (IsStatic()) {
174 object = declaring_class_;
175 }
176 return object->GetField64(GetOffset(), IsVolatile());
177}
178
179void Field::Set64(Object* object, uint64_t new_value) const {
180 CHECK((object == NULL) == IsStatic());
181 if (IsStatic()) {
182 object = declaring_class_;
183 }
184 object->SetField64(GetOffset(), new_value, IsVolatile());
185}
186
187Object* Field::GetObj(const Object* object) const {
188 CHECK((object == NULL) == IsStatic());
189 if (IsStatic()) {
190 object = declaring_class_;
191 }
192 return object->GetFieldObject<Object*>(GetOffset(), IsVolatile());
193}
194
195void Field::SetObj(Object* object, const Object* new_value) const {
196 CHECK((object == NULL) == IsStatic());
197 if (IsStatic()) {
198 object = declaring_class_;
199 }
200 object->SetFieldObject(GetOffset(), new_value, IsVolatile());
201}
202
203bool Field::GetBoolean(const Object* object) const {
204 DCHECK(GetType()->IsPrimitiveBoolean());
205 return Get32(object);
206}
207
208void Field::SetBoolean(Object* object, bool z) const {
209 DCHECK(GetType()->IsPrimitiveBoolean());
210 Set32(object, z);
211}
212
213int8_t Field::GetByte(const Object* object) const {
214 DCHECK(GetType()->IsPrimitiveByte());
215 return Get32(object);
216}
217
218void Field::SetByte(Object* object, int8_t b) const {
219 DCHECK(GetType()->IsPrimitiveByte());
220 Set32(object, b);
221}
222
223uint16_t Field::GetChar(const Object* object) const {
224 DCHECK(GetType()->IsPrimitiveChar());
225 return Get32(object);
226}
227
228void Field::SetChar(Object* object, uint16_t c) const {
229 DCHECK(GetType()->IsPrimitiveChar());
230 Set32(object, c);
231}
232
233uint16_t Field::GetShort(const Object* object) const {
234 DCHECK(GetType()->IsPrimitiveShort());
235 return Get32(object);
236}
237
238void Field::SetShort(Object* object, uint16_t s) const {
239 DCHECK(GetType()->IsPrimitiveShort());
240 Set32(object, s);
241}
242
243int32_t Field::GetInt(const Object* object) const {
244 DCHECK(GetType()->IsPrimitiveInt());
245 return Get32(object);
246}
247
248void Field::SetInt(Object* object, int32_t i) const {
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700249 DCHECK(GetType()->IsPrimitiveInt()) << PrettyField(this);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700250 Set32(object, i);
251}
252
253int64_t Field::GetLong(const Object* object) const {
254 DCHECK(GetType()->IsPrimitiveLong());
255 return Get64(object);
256}
257
258void Field::SetLong(Object* object, int64_t j) const {
259 DCHECK(GetType()->IsPrimitiveLong());
260 Set64(object, j);
261}
262
263float Field::GetFloat(const Object* object) const {
264 DCHECK(GetType()->IsPrimitiveFloat());
265 JValue float_bits;
266 float_bits.i = Get32(object);
267 return float_bits.f;
268}
269
270void Field::SetFloat(Object* object, float f) const {
271 DCHECK(GetType()->IsPrimitiveFloat());
272 JValue float_bits;
273 float_bits.f = f;
274 Set32(object, float_bits.i);
275}
276
277double Field::GetDouble(const Object* object) const {
278 DCHECK(GetType()->IsPrimitiveDouble());
279 JValue double_bits;
280 double_bits.j = Get64(object);
281 return double_bits.d;
282}
283
284void Field::SetDouble(Object* object, double d) const {
285 DCHECK(GetType()->IsPrimitiveDouble());
286 JValue double_bits;
287 double_bits.d = d;
288 Set64(object, double_bits.j);
289}
290
291Object* Field::GetObject(const Object* object) const {
292 CHECK(!GetType()->IsPrimitive());
293 return GetObj(object);
294}
295
296void Field::SetObject(Object* object, const Object* l) const {
297 CHECK(!GetType()->IsPrimitive());
298 SetObj(object, l);
299}
300
301// TODO: get global references for these
302Class* Method::java_lang_reflect_Method_ = NULL;
303
304void Method::SetClass(Class* java_lang_reflect_Method) {
305 CHECK(java_lang_reflect_Method_ == NULL);
306 CHECK(java_lang_reflect_Method != NULL);
307 java_lang_reflect_Method_ = java_lang_reflect_Method;
308}
309
310void Method::ResetClass() {
311 CHECK(java_lang_reflect_Method_ != NULL);
312 java_lang_reflect_Method_ = NULL;
313}
314
315ObjectArray<String>* Method::GetDexCacheStrings() const {
316 return GetFieldObject<ObjectArray<String>*>(
317 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_), false);
318}
319
320void Method::SetReturnTypeIdx(uint32_t new_return_type_idx) {
321 SetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_),
322 new_return_type_idx, false);
323}
324
325Class* Method::GetReturnType() const {
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700326 DCHECK(GetDeclaringClass()->IsResolved());
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700327 // Short-cut
328 Class* result = GetDexCacheResolvedTypes()->Get(GetReturnTypeIdx());
329 if (result == NULL) {
330 // Do full linkage and set cache value for next call
331 result = Runtime::Current()->GetClassLinker()->ResolveType(GetReturnTypeIdx(), this);
332 }
333 CHECK(result != NULL);
334 return result;
335}
336
337void Method::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) {
338 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_),
339 new_dex_cache_strings, false);
340}
341
342ObjectArray<Class>* Method::GetDexCacheResolvedTypes() const {
343 return GetFieldObject<ObjectArray<Class>*>(
344 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_), false);
345}
346
347void Method::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_classes) {
348 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_),
349 new_dex_cache_classes, false);
350}
351
352ObjectArray<Method>* Method::GetDexCacheResolvedMethods() const {
353 return GetFieldObject<ObjectArray<Method>*>(
354 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_), false);
355}
356
357void Method::SetDexCacheResolvedMethods(ObjectArray<Method>* new_dex_cache_methods) {
358 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_),
359 new_dex_cache_methods, false);
360}
361
362ObjectArray<Field>* Method::GetDexCacheResolvedFields() const {
363 return GetFieldObject<ObjectArray<Field>*>(
364 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_fields_), false);
365}
366
367void Method::SetDexCacheResolvedFields(ObjectArray<Field>* new_dex_cache_fields) {
368 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_fields_),
369 new_dex_cache_fields, false);
370}
371
372CodeAndDirectMethods* Method::GetDexCacheCodeAndDirectMethods() const {
373 return GetFieldPtr<CodeAndDirectMethods*>(
374 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_),
375 false);
376}
377
378void Method::SetDexCacheCodeAndDirectMethods(CodeAndDirectMethods* new_value) {
379 SetFieldPtr<CodeAndDirectMethods*>(
380 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_),
381 new_value, false);
382}
383
384ObjectArray<StaticStorageBase>* Method::GetDexCacheInitializedStaticStorage() const {
385 return GetFieldObject<ObjectArray<StaticStorageBase>*>(
386 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
387 false);
388}
389
390void Method::SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) {
391 SetFieldObject(
392 OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
393 new_value, false);
394
395}
396
397size_t Method::NumArgRegisters(const StringPiece& shorty) {
398 CHECK_LE(1, shorty.length());
399 uint32_t num_registers = 0;
400 for (int i = 1; i < shorty.length(); ++i) {
401 char ch = shorty[i];
402 if (ch == 'D' || ch == 'J') {
403 num_registers += 2;
404 } else {
405 num_registers += 1;
Brian Carlstromb63ec392011-08-27 17:38:27 -0700406 }
407 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700408 return num_registers;
409}
410
411size_t Method::NumArgArrayBytes() const {
Brian Carlstromc74255f2011-09-11 22:47:39 -0700412 const String* shorty = GetShorty();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700413 size_t num_bytes = 0;
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700414 for (int i = 1; i < shorty->GetLength(); ++i) {
415 char ch = shorty->CharAt(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700416 if (ch == 'D' || ch == 'J') {
417 num_bytes += 8;
418 } else if (ch == 'L') {
419 // Argument is a reference or an array. The shorty descriptor
420 // does not distinguish between these types.
421 num_bytes += sizeof(Object*);
422 } else {
423 num_bytes += 4;
424 }
425 }
426 return num_bytes;
427}
428
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700429size_t Method::NumArgs() const {
430 // "1 +" because the first in Args is the receiver.
431 // "- 1" because we don't count the return type.
432 return (IsStatic() ? 0 : 1) + GetShorty()->GetLength() - 1;
433}
434
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700435// The number of reference arguments to this method including implicit this
436// pointer
437size_t Method::NumReferenceArgs() const {
Brian Carlstromc74255f2011-09-11 22:47:39 -0700438 const String* shorty = GetShorty();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700439 size_t result = IsStatic() ? 0 : 1; // The implicit this pointer.
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700440 for (int i = 1; i < shorty->GetLength(); i++) {
441 char ch = shorty->CharAt(i);
442 if ((ch == 'L') || (ch == '[')) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700443 result++;
444 }
445 }
446 return result;
447}
448
449// The number of long or double arguments
450size_t Method::NumLongOrDoubleArgs() const {
Brian Carlstromc74255f2011-09-11 22:47:39 -0700451 const String* shorty = GetShorty();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700452 size_t result = 0;
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700453 for (int i = 1; i < shorty->GetLength(); i++) {
454 char ch = shorty->CharAt(i);
455 if ((ch == 'D') || (ch == 'J')) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700456 result++;
457 }
458 }
459 return result;
460}
461
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700462// Is the given method parameter a reference?
463bool Method::IsParamAReference(unsigned int param) const {
464 CHECK_LT(param, NumArgs());
465 if (IsStatic()) {
466 param++; // 0th argument must skip return value at start of the shorty
467 } else if (param == 0) {
468 return true; // this argument
469 }
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700470 return GetShorty()->CharAt(param) == 'L';
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700471}
472
473// Is the given method parameter a long or double?
474bool Method::IsParamALongOrDouble(unsigned int param) const {
475 CHECK_LT(param, NumArgs());
476 if (IsStatic()) {
477 param++; // 0th argument must skip return value at start of the shorty
478 } else if (param == 0) {
479 return false; // this argument
480 }
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700481 char ch = GetShorty()->CharAt(param);
482 return (ch == 'J' || ch == 'D');
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700483}
484
485static size_t ShortyCharToSize(char x) {
486 switch (x) {
487 case 'V': return 0;
488 case '[': return kPointerSize;
489 case 'L': return kPointerSize;
490 case 'D': return 8;
491 case 'J': return 8;
492 default: return 4;
493 }
494}
495
496size_t Method::ParamSize(unsigned int param) const {
497 CHECK_LT(param, NumArgs());
498 if (IsStatic()) {
499 param++; // 0th argument must skip return value at start of the shorty
500 } else if (param == 0) {
501 return kPointerSize; // this argument
502 }
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700503 return ShortyCharToSize(GetShorty()->CharAt(param));
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700504}
505
506size_t Method::ReturnSize() const {
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700507 return ShortyCharToSize(GetShorty()->CharAt(0));
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700508}
509
510bool Method::HasSameNameAndDescriptor(const Method* that) const {
511 return (this->GetName()->Equals(that->GetName()) &&
512 this->GetSignature()->Equals(that->GetSignature()));
513}
514
Ian Rogersbdb03912011-09-14 00:55:44 -0700515uint32_t Method::ToDexPC(const uintptr_t pc) const {
516 IntArray* mapping_table = GetMappingTable();
517 if (mapping_table == NULL) {
Ian Rogers67375ac2011-09-14 00:55:44 -0700518 DCHECK(IsNative());
519 return DexFile::kDexNoIndex; // Special no mapping case
Ian Rogersbdb03912011-09-14 00:55:44 -0700520 }
521 size_t mapping_table_length = mapping_table->GetLength();
522 uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(GetCode());
523 CHECK_LT(sought_offset, static_cast<uint32_t>(GetCodeArray()->GetLength()));
524 uint32_t best_offset = 0;
525 uint32_t best_dex_offset = 0;
526 for (size_t i = 0; i < mapping_table_length; i += 2) {
527 uint32_t map_offset = mapping_table->Get(i);
528 uint32_t map_dex_offset = mapping_table->Get(i + 1);
529 if (map_offset == sought_offset) {
530 best_offset = map_offset;
531 best_dex_offset = map_dex_offset;
532 break;
533 }
534 if (map_offset < sought_offset && map_offset > best_offset) {
535 best_offset = map_offset;
536 best_dex_offset = map_dex_offset;
537 }
538 }
539 return best_dex_offset;
540}
541
542uintptr_t Method::ToNativePC(const uint32_t dex_pc) const {
543 IntArray* mapping_table = GetMappingTable();
544 if (mapping_table == NULL) {
545 DCHECK(dex_pc == 0);
546 return 0; // Special no mapping/pc == 0 case
547 }
548 size_t mapping_table_length = mapping_table->GetLength();
549 for (size_t i = 0; i < mapping_table_length; i += 2) {
550 uint32_t map_offset = mapping_table->Get(i);
551 uint32_t map_dex_offset = mapping_table->Get(i + 1);
552 if (map_dex_offset == dex_pc) {
553 DCHECK_LT(map_offset, static_cast<uint32_t>(GetCodeArray()->GetLength()));
554 return reinterpret_cast<uintptr_t>(GetCode()) + map_offset;
555 }
556 }
557 LOG(FATAL) << "Looking up Dex PC not contained in method";
558 return 0;
559}
560
561uint32_t Method::FindCatchBlock(Class* exception_type, uint32_t dex_pc) const {
562 DexCache* dex_cache = GetDeclaringClass()->GetDexCache();
563 const ClassLoader* class_loader = GetDeclaringClass()->GetClassLoader();
564 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
565 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
566 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(GetCodeItemOffset());
567 // Iterate over the catch handlers associated with dex_pc
568 for (DexFile::CatchHandlerIterator iter = dex_file.dexFindCatchHandler(*code_item, dex_pc);
569 !iter.HasNext(); iter.Next()) {
570 uint32_t iter_type_idx = iter.Get().type_idx_;
571 // Catch all case
572 if(iter_type_idx == DexFile::kDexNoIndex) {
573 return iter.Get().address_;
574 }
575 // Does this catch exception type apply?
576 Class* iter_exception_type =
577 class_linker->ResolveType(dex_file, iter_type_idx, dex_cache, class_loader);
578 if (iter_exception_type->IsAssignableFrom(exception_type)) {
579 return iter.Get().address_;
580 }
581 }
582 // Handler not found
583 return DexFile::kDexNoIndex;
584}
585
buzbee4ef76522011-09-08 10:00:32 -0700586void Method::SetCode(ByteArray* code_array, InstructionSet instruction_set,
Ian Rogersbdb03912011-09-14 00:55:44 -0700587 IntArray* mapping_table) {
Elliott Hughes1240dad2011-09-09 16:24:50 -0700588 CHECK(GetCode() == NULL || IsNative());
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700589 SetFieldPtr<ByteArray*>(OFFSET_OF_OBJECT_MEMBER(Method, code_array_), code_array, false);
Ian Rogersbdb03912011-09-14 00:55:44 -0700590 SetFieldPtr<IntArray*>(OFFSET_OF_OBJECT_MEMBER(Method, mapping_table_),
buzbee4ef76522011-09-08 10:00:32 -0700591 mapping_table, false);
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700592 int8_t* code = code_array->GetData();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700593 uintptr_t address = reinterpret_cast<uintptr_t>(code);
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700594 if (instruction_set == kThumb2) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700595 // Set the low-order bit so a BLX will switch to Thumb mode
596 address |= 0x1;
597 }
Elliott Hughes5ea047b2011-09-13 14:38:18 -0700598 SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, code_), reinterpret_cast<const void*>(address), false);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700599}
600
Ian Rogersbdb03912011-09-14 00:55:44 -0700601bool Method::IsWithinCode(uintptr_t pc) const {
602 if (GetCode() == NULL) {
603 return false;
604 }
605 if (pc == 0) {
606 // assume that this is some initial value that will always lie in code
607 return true;
608 } else {
Ian Rogers93dd9662011-09-17 23:21:22 -0700609#if defined(__arm__)
610 pc &= ~0x1; // clear any possible thumb instruction mode bit
611#endif
Ian Rogersbdb03912011-09-14 00:55:44 -0700612 uint32_t rel_offset = pc - reinterpret_cast<uintptr_t>(GetCodeArray()->GetData());
Ian Rogers93dd9662011-09-17 23:21:22 -0700613 // Strictly the following test should be a less-than, however, if the last
614 // instruction is a call to an exception throw we may see return addresses
615 // that are 1 beyond the end of code.
616 return rel_offset <= static_cast<uint32_t>(GetCodeArray()->GetLength());
Ian Rogersbdb03912011-09-14 00:55:44 -0700617 }
618}
619
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700620void Method::SetInvokeStub(const ByteArray* invoke_stub_array) {
621 const InvokeStub* invoke_stub = reinterpret_cast<InvokeStub*>(invoke_stub_array->GetData());
622 SetFieldPtr<const ByteArray*>(
623 OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_array_), invoke_stub_array, false);
624 SetFieldPtr<const InvokeStub*>(
625 OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), invoke_stub, false);
626}
627
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700628void Method::Invoke(Thread* self, Object* receiver, byte* args, JValue* result) const {
629 // Push a transition back into managed code onto the linked list in thread.
630 CHECK_EQ(Thread::kRunnable, self->GetState());
631 NativeToManagedRecord record;
632 self->PushNativeToManagedRecord(&record);
633
634 // Call the invoke stub associated with the method.
635 // Pass everything as arguments.
636 const Method::InvokeStub* stub = GetInvokeStub();
Elliott Hughes1240dad2011-09-09 16:24:50 -0700637
638 bool have_executable_code = (GetCode() != NULL);
639#if !defined(__arm__)
Brian Carlstrom4b620ff2011-09-11 01:11:01 -0700640 // Currently we can only compile non-native methods for ARM.
641 have_executable_code = IsNative();
Elliott Hughes1240dad2011-09-09 16:24:50 -0700642#endif
643
644 if (have_executable_code && stub != NULL) {
645 LOG(INFO) << "invoking " << PrettyMethod(this) << " code=" << (void*) GetCode() << " stub=" << (void*) stub;
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700646 (*stub)(this, receiver, self, args, result);
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700647 LOG(INFO) << "returned " << PrettyMethod(this) << " code=" << (void*) GetCode() << " stub=" << (void*) stub;
Elliott Hughesf5ecf062011-09-06 17:37:59 -0700648 } else {
649 LOG(WARNING) << "Not invoking method with no associated code: " << PrettyMethod(this);
650 if (result != NULL) {
651 result->j = 0;
652 }
653 }
654
655 // Pop transition.
656 self->PopNativeToManagedRecord(record);
657}
658
Brian Carlstrom16192862011-09-12 17:50:06 -0700659bool Method::IsRegistered() {
660 void* native_method = GetFieldPtr<void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_), false);
661 void* jni_stub = Runtime::Current()->GetJniStubArray()->GetData();
662 return native_method != jni_stub;
663}
664
665void Method::RegisterNative(const void* native_method) {
666 CHECK(IsNative());
667 CHECK(native_method != NULL);
668 SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
669 native_method, false);
670}
671
672void Method::UnregisterNative() {
673 CHECK(IsNative());
674 // restore stub to lookup native pointer via dlsym
675 RegisterNative(Runtime::Current()->GetJniStubArray()->GetData());
676}
677
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700678void Class::SetStatus(Status new_status) {
679 CHECK(new_status > GetStatus() || new_status == kStatusError ||
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700680 !Runtime::Current()->IsStarted()) << GetDescriptor()->ToModifiedUtf8();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700681 CHECK(sizeof(Status) == sizeof(uint32_t));
682 return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_),
683 new_status, false);
684}
685
686DexCache* Class::GetDexCache() const {
687 return GetFieldObject<DexCache*>(
688 OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
689}
690
691void Class::SetDexCache(DexCache* new_dex_cache) {
692 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_),
693 new_dex_cache, false);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700694}
695
Brian Carlstrom1f870082011-08-23 16:02:11 -0700696Object* Class::AllocObjectFromCode(uint32_t type_idx, Method* method) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700697 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700698 if (klass == NULL) {
699 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
700 if (klass == NULL) {
701 UNIMPLEMENTED(FATAL) << "throw an error";
702 return NULL;
703 }
704 }
Brian Carlstrom1f870082011-08-23 16:02:11 -0700705 return klass->AllocObject();
706}
707
708Object* Class::AllocObject() {
709 DCHECK(!IsAbstract());
710 return Heap::AllocObject(this, this->object_size_);
Brian Carlstromb63ec392011-08-27 17:38:27 -0700711}
712
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700713void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
714 if (new_reference_offsets != CLASS_WALK_SUPER) {
715 // Sanity check that the number of bits set in the reference offset bitmap
716 // agrees with the number of references
717 Class* cur = this;
718 size_t cnt = 0;
719 while (cur) {
720 cnt += cur->NumReferenceInstanceFieldsDuringLinking();
721 cur = cur->GetSuperClass();
722 }
723 CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), cnt);
724 }
725 SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
726 new_reference_offsets, false);
727}
728
729void Class::SetReferenceStaticOffsets(uint32_t new_reference_offsets) {
730 if (new_reference_offsets != CLASS_WALK_SUPER) {
731 // Sanity check that the number of bits set in the reference offset bitmap
732 // agrees with the number of references
733 CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets),
734 NumReferenceStaticFieldsDuringLinking());
735 }
736 SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_),
737 new_reference_offsets, false);
738}
739
740size_t Class::PrimitiveSize() const {
741 switch (GetPrimitiveType()) {
742 case kPrimBoolean:
743 case kPrimByte:
744 case kPrimChar:
745 case kPrimShort:
746 case kPrimInt:
747 case kPrimFloat:
748 return sizeof(int32_t);
749 case kPrimLong:
750 case kPrimDouble:
751 return sizeof(int64_t);
752 default:
753 LOG(FATAL) << "Primitive type size calculation on invalid type " << this;
754 return 0;
755 }
756}
757
758size_t Class::GetTypeSize(const String* descriptor) {
759 switch (descriptor->CharAt(0)) {
760 case 'B': return 1; // byte
761 case 'C': return 2; // char
762 case 'D': return 8; // double
763 case 'F': return 4; // float
764 case 'I': return 4; // int
765 case 'J': return 8; // long
766 case 'S': return 2; // short
767 case 'Z': return 1; // boolean
768 case 'L': return sizeof(Object*);
769 case '[': return sizeof(Array*);
770 default:
771 LOG(ERROR) << "Unknown type " << descriptor;
772 return 0;
773 }
Elliott Hughesbf86d042011-08-31 17:53:14 -0700774}
775
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700776bool Class::Implements(const Class* klass) const {
777 DCHECK(klass != NULL);
778 DCHECK(klass->IsInterface());
779 // All interfaces implemented directly and by our superclass, and
780 // recursively all super-interfaces of those interfaces, are listed
781 // in iftable_, so we can just do a linear scan through that.
Brian Carlstrom4b620ff2011-09-11 01:11:01 -0700782 int32_t iftable_count = GetIfTableCount();
783 ObjectArray<InterfaceEntry>* iftable = GetIfTable();
784 for (int32_t i = 0; i < iftable_count; i++) {
785 if (iftable->Get(i)->GetInterface() == klass) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700786 return true;
787 }
788 }
789 return false;
790}
791
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700792bool Class::CanPutArrayElement(const Class* object_class, const Class* array_class) {
793 if (object_class->IsArrayClass()) {
794 return array_class->IsArrayAssignableFromArray(object_class);
795 } else {
796 return array_class->GetComponentType()->IsAssignableFrom(object_class);
797 }
798}
799
buzbee9a195c92011-09-16 13:26:02 -0700800void Class::CanPutArrayElementFromCode(const Object* element, const Class* array_class) {
801 if (element == NULL) {
802 return;
803 }
804 if (!CanPutArrayElement(element->GetClass(), array_class)) {
805 LOG(ERROR) << "Can't put a " << PrettyClass(element->GetClass())
Elliott Hughes54e7df12011-09-16 11:47:04 -0700806 << " into a " << PrettyClass(array_class);
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700807 UNIMPLEMENTED(FATAL) << "need to throw ArrayStoreException and unwind stack";
808 }
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700809}
810
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700811// Determine whether "this" is assignable from "klazz", where both of these
812// are array classes.
813//
814// Consider an array class, e.g. Y[][], where Y is a subclass of X.
815// Y[][] = Y[][] --> true (identity)
816// X[][] = Y[][] --> true (element superclass)
817// Y = Y[][] --> false
818// Y[] = Y[][] --> false
819// Object = Y[][] --> true (everything is an object)
820// Object[] = Y[][] --> true
821// Object[][] = Y[][] --> true
822// Object[][][] = Y[][] --> false (too many []s)
823// Serializable = Y[][] --> true (all arrays are Serializable)
824// Serializable[] = Y[][] --> true
825// Serializable[][] = Y[][] --> false (unless Y is Serializable)
826//
827// Don't forget about primitive types.
Elliott Hughes0f4c41d2011-09-04 14:58:03 -0700828// Object[] = int[] --> false
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700829//
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700830bool Class::IsArrayAssignableFromArray(const Class* src) const {
Brian Carlstromb63ec392011-08-27 17:38:27 -0700831 DCHECK(IsArrayClass());
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700832 DCHECK(src->IsArrayClass());
833 return GetComponentType()->IsAssignableFrom(src->GetComponentType());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700834}
835
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700836bool Class::IsAssignableFromArray(const Class* src) const {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700837 DCHECK(!IsInterface()); // handled first in IsAssignableFrom
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700838 DCHECK(src->IsArrayClass());
Brian Carlstromb63ec392011-08-27 17:38:27 -0700839 if (!IsArrayClass()) {
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700840 // If "this" is not also an array, it must be Object.
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700841 // src's super should be java_lang_Object, since it is an array.
842 Class* java_lang_Object = src->GetSuperClass();
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700843 DCHECK(java_lang_Object != NULL);
844 DCHECK(java_lang_Object->GetSuperClass() == NULL);
845 return this == java_lang_Object;
846 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700847 return IsArrayAssignableFromArray(src);
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700848}
849
850bool Class::IsSubClass(const Class* klass) const {
851 DCHECK(!IsInterface());
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700852 DCHECK(!IsArrayClass());
Brian Carlstromf7ed11a2011-08-09 17:55:51 -0700853 const Class* current = this;
854 do {
855 if (current == klass) {
856 return true;
857 }
858 current = current->GetSuperClass();
859 } while (current != NULL);
860 return false;
861}
862
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700863bool Class::IsInSamePackage(const String* descriptor_string_1,
864 const String* descriptor_string_2) {
865 const std::string descriptor1(descriptor_string_1->ToModifiedUtf8());
866 const std::string descriptor2(descriptor_string_2->ToModifiedUtf8());
867
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700868 size_t i = 0;
869 while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
870 ++i;
871 }
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700872 if (descriptor1.find('/', i) != StringPiece::npos ||
873 descriptor2.find('/', i) != StringPiece::npos) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700874 return false;
875 } else {
876 return true;
877 }
878}
879
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700880#if 0
Ian Rogersb033c752011-07-20 12:22:35 -0700881bool Class::IsInSamePackage(const StringPiece& descriptor1,
882 const StringPiece& descriptor2) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700883 size_t size = std::min(descriptor1.size(), descriptor2.size());
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700884 std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos;
Ian Rogersb033c752011-07-20 12:22:35 -0700885 pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size,
886 descriptor2.begin());
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700887 return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos);
888}
889#endif
890
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700891bool Class::IsInSamePackage(const Class* that) const {
892 const Class* klass1 = this;
893 const Class* klass2 = that;
894 if (klass1 == klass2) {
895 return true;
896 }
897 // Class loaders must match.
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700898 if (klass1->GetClassLoader() != klass2->GetClassLoader()) {
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700899 return false;
900 }
901 // Arrays are in the same package when their element classes are.
Brian Carlstromb63ec392011-08-27 17:38:27 -0700902 if (klass1->IsArrayClass()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700903 klass1 = klass1->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700904 }
Brian Carlstromb63ec392011-08-27 17:38:27 -0700905 if (klass2->IsArrayClass()) {
Carl Shapiro0e5d75d2011-07-06 18:28:37 -0700906 klass2 = klass2->GetComponentType();
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700907 }
908 // Compare the package part of the descriptor string.
Brian Carlstrom6cc18452011-07-18 15:10:33 -0700909 return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
Carl Shapiro894d0fa2011-06-30 14:48:49 -0700910}
911
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700912const ClassLoader* Class::GetClassLoader() const {
913 return GetFieldObject<const ClassLoader*>(
914 OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
Brian Carlstromb9edb842011-08-28 16:31:06 -0700915}
916
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700917void Class::SetClassLoader(const ClassLoader* new_cl) {
918 ClassLoader* new_class_loader = const_cast<ClassLoader*>(new_cl);
919 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_),
920 new_class_loader, false);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700921}
922
Brian Carlstrom30b94452011-08-25 21:35:26 -0700923Method* Class::FindVirtualMethodForInterface(Method* method) {
924 Class* declaring_class = method->GetDeclaringClass();
Brian Carlstroma5a97a22011-09-15 14:08:49 -0700925 DCHECK(declaring_class != NULL);
Brian Carlstrom30b94452011-08-25 21:35:26 -0700926 DCHECK(declaring_class->IsInterface());
927 // TODO cache to improve lookup speed
Brian Carlstrom4b620ff2011-09-11 01:11:01 -0700928 int32_t iftable_count = GetIfTableCount();
929 ObjectArray<InterfaceEntry>* iftable = GetIfTable();
930 for (int32_t i = 0; i < iftable_count; i++) {
931 InterfaceEntry* interface_entry = iftable->Get(i);
932 if (interface_entry->GetInterface() == declaring_class) {
933 return interface_entry->GetMethodArray()->Get(method->GetMethodIndex());
Brian Carlstrom30b94452011-08-25 21:35:26 -0700934 }
935 }
Brian Carlstrom16192862011-09-12 17:50:06 -0700936 UNIMPLEMENTED(FATAL) << "Need to throw an error of some kind " << PrettyMethod(method);
Brian Carlstrom30b94452011-08-25 21:35:26 -0700937 return NULL;
938}
939
jeffhaobdb76512011-09-07 11:43:16 -0700940Method* Class::FindInterfaceMethod(const StringPiece& name,
941 const StringPiece& signature) {
942 // Check the current class before checking the interfaces.
943 Method* method = FindVirtualMethod(name, signature);
944 if (method != NULL) {
945 return method;
946 }
947
Brian Carlstrom4b620ff2011-09-11 01:11:01 -0700948 int32_t iftable_count = GetIfTableCount();
949 ObjectArray<InterfaceEntry>* iftable = GetIfTable();
950 for (int32_t i = 0; i < iftable_count; i++) {
951 method = iftable->Get(i)->GetInterface()->FindVirtualMethod(name, signature);
jeffhaobdb76512011-09-07 11:43:16 -0700952 if (method != NULL) {
953 return method;
954 }
955 }
956 return NULL;
957}
958
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700959Method* Class::FindDeclaredDirectMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700960 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700961 for (size_t i = 0; i < NumDirectMethods(); ++i) {
Ian Rogersb033c752011-07-20 12:22:35 -0700962 Method* method = GetDirectMethod(i);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700963 if (method->GetName()->Equals(name) &&
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700964 method->GetSignature()->Equals(signature)) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700965 return method;
Ian Rogersb033c752011-07-20 12:22:35 -0700966 }
967 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700968 return NULL;
Ian Rogersb033c752011-07-20 12:22:35 -0700969}
970
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700971Method* Class::FindDirectMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700972 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700973 for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700974 Method* method = klass->FindDeclaredDirectMethod(name, signature);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700975 if (method != NULL) {
976 return method;
977 }
978 }
979 return NULL;
980}
981
982Method* Class::FindDeclaredVirtualMethod(const StringPiece& name,
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700983 const StringPiece& signature) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700984 for (size_t i = 0; i < NumVirtualMethods(); ++i) {
Ian Rogersb033c752011-07-20 12:22:35 -0700985 Method* method = GetVirtualMethod(i);
Carl Shapiro8860c0e2011-08-04 17:36:16 -0700986 if (method->GetName()->Equals(name) &&
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700987 method->GetSignature()->Equals(signature)) {
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700988 return method;
Ian Rogersb033c752011-07-20 12:22:35 -0700989 }
990 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700991 return NULL;
Ian Rogersb033c752011-07-20 12:22:35 -0700992}
993
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700994Method* Class::FindVirtualMethod(const StringPiece& name,
995 const StringPiece& descriptor) {
996 for (Class* klass = this; klass != NULL; klass = klass->GetSuperClass()) {
997 Method* method = klass->FindDeclaredVirtualMethod(name, descriptor);
998 if (method != NULL) {
999 return method;
1000 }
1001 }
1002 return NULL;
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001003}
1004
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001005Field* Class::FindDeclaredInstanceField(const StringPiece& name, Class* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001006 // Is the field in this class?
1007 // Interfaces are not relevant because they can't contain instance fields.
1008 for (size_t i = 0; i < NumInstanceFields(); ++i) {
1009 Field* f = GetInstanceField(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001010 if (f->GetName()->Equals(name) && type == f->GetType()) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001011 return f;
1012 }
1013 }
1014 return NULL;
1015}
1016
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001017Field* Class::FindInstanceField(const StringPiece& name, Class* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001018 // Is the field in this class, or any of its superclasses?
1019 // Interfaces are not relevant because they can't contain instance fields.
1020 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001021 Field* f = c->FindDeclaredInstanceField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -07001022 if (f != NULL) {
1023 return f;
1024 }
1025 }
1026 return NULL;
1027}
1028
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001029Field* Class::FindDeclaredStaticField(const StringPiece& name, Class* type) {
1030 DCHECK(type != NULL);
Elliott Hughescdf53122011-08-19 15:46:09 -07001031 for (size_t i = 0; i < NumStaticFields(); ++i) {
1032 Field* f = GetStaticField(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001033 if (f->GetName()->Equals(name) && f->GetType() == type) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001034 return f;
1035 }
1036 }
1037 return NULL;
1038}
1039
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001040Field* Class::FindStaticField(const StringPiece& name, Class* type) {
Elliott Hughescdf53122011-08-19 15:46:09 -07001041 // Is the field in this class (or its interfaces), or any of its
1042 // superclasses (or their interfaces)?
1043 for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
1044 // Is the field in this class?
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001045 Field* f = c->FindDeclaredStaticField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -07001046 if (f != NULL) {
1047 return f;
1048 }
1049
1050 // Is this field in any of this class' interfaces?
1051 for (size_t i = 0; i < c->NumInterfaces(); ++i) {
1052 Class* interface = c->GetInterface(i);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001053 f = interface->FindDeclaredStaticField(name, type);
Elliott Hughescdf53122011-08-19 15:46:09 -07001054 if (f != NULL) {
1055 return f;
1056 }
1057 }
1058 }
1059 return NULL;
1060}
1061
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001062Array* Array::Alloc(Class* array_class, int32_t component_count, size_t component_size) {
Elliott Hughes0f4c41d2011-09-04 14:58:03 -07001063 DCHECK(array_class != NULL);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001064 DCHECK_GE(component_count, 0);
1065 DCHECK(array_class->IsArrayClass());
1066 size_t size = SizeOf(component_count, component_size);
1067 Array* array = down_cast<Array*>(Heap::AllocObject(array_class, size));
1068 if (array != NULL) {
1069 DCHECK(array->IsArrayInstance());
1070 array->SetLength(component_count);
1071 }
1072 return array;
1073}
1074
1075Array* Array::Alloc(Class* array_class, int32_t component_count) {
1076 return Alloc(array_class, component_count, array_class->GetComponentSize());
1077}
1078
1079Array* Array::AllocFromCode(uint32_t type_idx, Method* method, int32_t component_count) {
1080 // TODO: throw on negative component_count
1081 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
1082 if (klass == NULL) {
1083 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
1084 if (klass == NULL || !klass->IsArrayClass()) {
1085 UNIMPLEMENTED(FATAL) << "throw an error";
1086 return NULL;
1087 }
1088 }
1089 return Array::Alloc(klass, component_count);
1090}
1091
Elliott Hughesd8ddfd52011-08-15 14:32:53 -07001092template<typename T>
1093PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) {
Elliott Hughesc1674ed2011-08-25 18:09:09 -07001094 DCHECK(array_class_ != NULL);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -07001095 Array* raw_array = Array::Alloc(array_class_, length, sizeof(T));
1096 return down_cast<PrimitiveArray<T>*>(raw_array);
1097}
1098
1099template <typename T> Class* PrimitiveArray<T>::array_class_ = NULL;
1100
1101// Explicitly instantiate all the primitive array types.
1102template class PrimitiveArray<uint8_t>; // BooleanArray
1103template class PrimitiveArray<int8_t>; // ByteArray
1104template class PrimitiveArray<uint16_t>; // CharArray
1105template class PrimitiveArray<double>; // DoubleArray
1106template class PrimitiveArray<float>; // FloatArray
1107template class PrimitiveArray<int32_t>; // IntArray
1108template class PrimitiveArray<int64_t>; // LongArray
1109template class PrimitiveArray<int16_t>; // ShortArray
1110
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001111// TODO: get global references for these
1112Class* String::java_lang_String_ = NULL;
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001113
Brian Carlstroma663ea52011-08-19 23:33:41 -07001114void String::SetClass(Class* java_lang_String) {
1115 CHECK(java_lang_String_ == NULL);
1116 CHECK(java_lang_String != NULL);
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001117 java_lang_String_ = java_lang_String;
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001118}
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001119
Brian Carlstroma663ea52011-08-19 23:33:41 -07001120void String::ResetClass() {
1121 CHECK(java_lang_String_ != NULL);
1122 java_lang_String_ = NULL;
1123}
Jesse Wilsonf7e85a52011-08-01 18:45:58 -07001124
Brian Carlstromc74255f2011-09-11 22:47:39 -07001125String* String::Intern() {
Elliott Hughescf4c6c42011-09-01 15:16:42 -07001126 return Runtime::Current()->GetInternTable()->InternWeak(this);
1127}
1128
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001129int32_t String::GetHashCode() const {
1130 int32_t result = GetField32(
1131 OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false);
1132 DCHECK(result != 0 ||
1133 ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0);
1134 return result;
1135}
1136
1137int32_t String::GetLength() const {
1138 int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), false);
1139 DCHECK(result >= 0 && result <= GetCharArray()->GetLength());
1140 return result;
1141}
1142
1143uint16_t String::CharAt(int32_t index) const {
1144 // TODO: do we need this? Equals is the only caller, and could
1145 // bounds check itself.
1146 if (index < 0 || index >= count_) {
1147 Thread* self = Thread::Current();
1148 self->ThrowNewException("Ljava/lang/StringIndexOutOfBoundsException;",
1149 "length=%i; index=%i", count_, index);
1150 return 0;
1151 }
1152 return GetCharArray()->Get(index + GetOffset());
1153}
1154
1155String* String::AllocFromUtf16(int32_t utf16_length,
1156 const uint16_t* utf16_data_in,
1157 int32_t hash_code) {
1158 String* string = Alloc(GetJavaLangString(), utf16_length);
1159 // TODO: use 16-bit wide memset variant
1160 CharArray* array = const_cast<CharArray*>(string->GetCharArray());
1161 for (int i = 0; i < utf16_length; i++) {
1162 array->Set(i, utf16_data_in[i]);
1163 }
1164 if (hash_code != 0) {
1165 string->SetHashCode(hash_code);
1166 } else {
1167 string->ComputeHashCode();
1168 }
1169 return string;
1170}
1171
1172String* String::AllocFromModifiedUtf8(const char* utf) {
1173 size_t char_count = CountModifiedUtf8Chars(utf);
1174 return AllocFromModifiedUtf8(char_count, utf);
1175}
1176
1177String* String::AllocFromModifiedUtf8(int32_t utf16_length,
1178 const char* utf8_data_in) {
1179 String* string = Alloc(GetJavaLangString(), utf16_length);
1180 uint16_t* utf16_data_out =
1181 const_cast<uint16_t*>(string->GetCharArray()->GetData());
1182 ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in);
1183 string->ComputeHashCode();
1184 return string;
1185}
1186
1187String* String::Alloc(Class* java_lang_String, int32_t utf16_length) {
1188 return Alloc(java_lang_String, CharArray::Alloc(utf16_length));
1189}
1190
1191String* String::Alloc(Class* java_lang_String, CharArray* array) {
1192 String* string = down_cast<String*>(java_lang_String->AllocObject());
1193 string->SetArray(array);
1194 string->SetCount(array->GetLength());
1195 return string;
1196}
1197
1198bool String::Equals(const String* that) const {
1199 if (this == that) {
1200 // Quick reference equality test
1201 return true;
1202 } else if (that == NULL) {
1203 // Null isn't an instanceof anything
1204 return false;
1205 } else if (this->GetLength() != that->GetLength()) {
1206 // Quick length inequality test
1207 return false;
1208 } else {
1209 // NB don't short circuit on hash code as we're presumably here as the
1210 // hash code was already equal
1211 for (int32_t i = 0; i < that->GetLength(); ++i) {
1212 if (this->CharAt(i) != that->CharAt(i)) {
1213 return false;
1214 }
1215 }
1216 return true;
1217 }
1218}
1219
1220bool String::Equals(const uint16_t* that_chars, int32_t that_offset,
1221 int32_t that_length) const {
1222 if (this->GetLength() != that_length) {
1223 return false;
1224 } else {
1225 for (int32_t i = 0; i < that_length; ++i) {
1226 if (this->CharAt(i) != that_chars[that_offset + i]) {
1227 return false;
1228 }
1229 }
1230 return true;
1231 }
1232}
1233
1234bool String::Equals(const char* modified_utf8) const {
1235 for (int32_t i = 0; i < GetLength(); ++i) {
1236 uint16_t ch = GetUtf16FromUtf8(&modified_utf8);
1237 if (ch == '\0' || ch != CharAt(i)) {
1238 return false;
1239 }
1240 }
1241 return *modified_utf8 == '\0';
1242}
1243
1244bool String::Equals(const StringPiece& modified_utf8) const {
Brian Carlstrom69b15fb2011-09-03 12:25:21 -07001245 // TODO: do not assume C-string representation. For now DCHECK.
1246 DCHECK_EQ(modified_utf8.data()[modified_utf8.size()], 0);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001247 return Equals(modified_utf8.data());
1248}
1249
1250// Create a modified UTF-8 encoded std::string from a java/lang/String object.
1251std::string String::ToModifiedUtf8() const {
1252 const uint16_t* chars = GetCharArray()->GetData() + GetOffset();
1253 size_t byte_count(CountUtf8Bytes(chars, GetLength()));
1254 std::string result(byte_count, char(0));
1255 ConvertUtf16ToModifiedUtf8(&result[0], chars, GetLength());
1256 return result;
1257}
1258
Shih-wei Liao55df06b2011-08-26 14:39:27 -07001259Class* StackTraceElement::java_lang_StackTraceElement_ = NULL;
1260
1261void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) {
1262 CHECK(java_lang_StackTraceElement_ == NULL);
1263 CHECK(java_lang_StackTraceElement != NULL);
1264 java_lang_StackTraceElement_ = java_lang_StackTraceElement;
1265}
1266
1267void StackTraceElement::ResetClass() {
1268 CHECK(java_lang_StackTraceElement_ != NULL);
1269 java_lang_StackTraceElement_ = NULL;
1270}
1271
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001272StackTraceElement* StackTraceElement::Alloc(const String* declaring_class,
1273 const String* method_name,
1274 const String* file_name,
1275 int32_t line_number) {
1276 StackTraceElement* trace =
1277 down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject());
1278 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
1279 const_cast<String*>(declaring_class), false);
1280 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
1281 const_cast<String*>(method_name), false);
1282 trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
1283 const_cast<String*>(file_name), false);
1284 trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_),
1285 line_number, false);
1286 return trace;
1287}
1288
Elliott Hughes1f359b02011-07-17 14:27:17 -07001289static const char* kClassStatusNames[] = {
1290 "Error",
1291 "NotReady",
1292 "Idx",
1293 "Loaded",
1294 "Resolved",
1295 "Verifying",
1296 "Verified",
1297 "Initializing",
1298 "Initialized"
1299};
1300std::ostream& operator<<(std::ostream& os, const Class::Status& rhs) {
1301 if (rhs >= Class::kStatusError && rhs <= Class::kStatusInitialized) {
Brian Carlstromae3ac012011-07-27 01:30:28 -07001302 os << kClassStatusNames[rhs + 1];
Elliott Hughes1f359b02011-07-17 14:27:17 -07001303 } else {
Ian Rogersb033c752011-07-20 12:22:35 -07001304 os << "Class::Status[" << static_cast<int>(rhs) << "]";
Elliott Hughes1f359b02011-07-17 14:27:17 -07001305 }
1306 return os;
1307}
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001308
Carl Shapiro3ee755d2011-06-28 12:11:04 -07001309} // namespace art