| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 1 | // Copyright 2011 Google Inc. All Rights Reserved. | 
|  | 2 |  | 
|  | 3 | #ifndef ART_SRC_OBJECT_H_ | 
|  | 4 | #define ART_SRC_OBJECT_H_ | 
|  | 5 |  | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 6 | #include "constants.h" | 
|  | 7 | #include "casts.h" | 
|  | 8 | #include "globals.h" | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 9 | #include "heap.h" | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 10 | #include "logging.h" | 
|  | 11 | #include "macros.h" | 
|  | 12 | #include "offsets.h" | 
|  | 13 | #include "stringpiece.h" | 
|  | 14 | #include "monitor.h" | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 15 |  | 
|  | 16 | namespace art { | 
|  | 17 |  | 
|  | 18 | class Array; | 
|  | 19 | class Class; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 20 | class DexCache; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 21 | class InstanceField; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 22 | class InterfaceEntry; | 
|  | 23 | class Monitor; | 
|  | 24 | class Method; | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 25 | class Object; | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 26 | template<class T> class ObjectArray; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 27 | class StaticField; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 28 |  | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 29 | union JValue { | 
|  | 30 | uint8_t z; | 
|  | 31 | int8_t b; | 
|  | 32 | uint16_t c; | 
|  | 33 | int16_t s; | 
|  | 34 | int32_t i; | 
|  | 35 | int64_t j; | 
|  | 36 | float f; | 
|  | 37 | double d; | 
|  | 38 | Object* l; | 
|  | 39 | }; | 
|  | 40 |  | 
| Brian Carlstrom | be97785 | 2011-07-19 14:54:54 -0700 | [diff] [blame] | 41 | static const uint32_t kAccPublic = 0x0001;  // class, field, method, ic | 
|  | 42 | static const uint32_t kAccPrivate = 0x0002;  // field, method, ic | 
|  | 43 | static const uint32_t kAccProtected = 0x0004;  // field, method, ic | 
|  | 44 | static const uint32_t kAccStatic = 0x0008;  // field, method, ic | 
|  | 45 | static const uint32_t kAccFinal = 0x0010;  // class, field, method, ic | 
|  | 46 | static const uint32_t kAccSynchronized = 0x0020;  // method (only allowed on natives) | 
|  | 47 | static const uint32_t kAccSuper = 0x0020;  // class (not used in Dalvik) | 
|  | 48 | static const uint32_t kAccVolatile = 0x0040;  // field | 
|  | 49 | static const uint32_t kAccBridge = 0x0040;  // method (1.5) | 
|  | 50 | static const uint32_t kAccTransient = 0x0080;  // field | 
|  | 51 | static const uint32_t kAccVarargs = 0x0080;  // method (1.5) | 
|  | 52 | static const uint32_t kAccNative = 0x0100;  // method | 
|  | 53 | static const uint32_t kAccInterface = 0x0200;  // class, ic | 
|  | 54 | static const uint32_t kAccAbstract = 0x0400;  // class, method, ic | 
|  | 55 | static const uint32_t kAccStrict = 0x0800;  // method | 
|  | 56 | static const uint32_t kAccSynthetic = 0x1000;  // field, method, ic | 
|  | 57 | static const uint32_t kAccAnnotation = 0x2000;  // class, ic (1.5) | 
|  | 58 | static const uint32_t kAccEnum = 0x4000;  // class, field, ic (1.5) | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 59 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 60 | static const uint32_t kAccMiranda = 0x8000;  // method | 
|  | 61 |  | 
| Brian Carlstrom | a331b3c | 2011-07-18 17:47:56 -0700 | [diff] [blame] | 62 | static const uint32_t kAccJavaFlagsMask = 0xffff;  // bits set from Java sources (low 16) | 
|  | 63 |  | 
| Brian Carlstrom | be97785 | 2011-07-19 14:54:54 -0700 | [diff] [blame] | 64 | static const uint32_t kAccConstructor = 0x00010000;  // method (Dalvik only) | 
|  | 65 | static const uint32_t kAccDeclaredSynchronized = 0x00020000;  // method (Dalvik only) | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 66 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 67 | /* | 
| Brian Carlstrom | a331b3c | 2011-07-18 17:47:56 -0700 | [diff] [blame] | 68 | * Definitions for packing refOffsets in Class. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 69 | */ | 
|  | 70 | /* | 
|  | 71 | * A magic value for refOffsets. Ignore the bits and walk the super | 
|  | 72 | * chain when this is the value. | 
|  | 73 | * [This is an unlikely "natural" value, since it would be 30 non-ref instance | 
|  | 74 | * fields followed by 2 ref instance fields.] | 
|  | 75 | */ | 
|  | 76 | #define CLASS_WALK_SUPER ((unsigned int)(3)) | 
|  | 77 | #define CLASS_SMALLEST_OFFSET (sizeof(struct Object)) | 
|  | 78 | #define CLASS_BITS_PER_WORD (sizeof(unsigned long int) * 8) | 
|  | 79 | #define CLASS_OFFSET_ALIGNMENT 4 | 
|  | 80 | #define CLASS_HIGH_BIT ((unsigned int)1 << (CLASS_BITS_PER_WORD - 1)) | 
|  | 81 | /* | 
|  | 82 | * Given an offset, return the bit number which would encode that offset. | 
|  | 83 | * Local use only. | 
|  | 84 | */ | 
|  | 85 | #define _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) \ | 
|  | 86 | (((unsigned int)(byteOffset) - CLASS_SMALLEST_OFFSET) / \ | 
|  | 87 | CLASS_OFFSET_ALIGNMENT) | 
|  | 88 | /* | 
|  | 89 | * Is the given offset too large to be encoded? | 
|  | 90 | */ | 
|  | 91 | #define CLASS_CAN_ENCODE_OFFSET(byteOffset) \ | 
|  | 92 | (_CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) < CLASS_BITS_PER_WORD) | 
|  | 93 | /* | 
|  | 94 | * Return a single bit, encoding the offset. | 
|  | 95 | * Undefined if the offset is too large, as defined above. | 
|  | 96 | */ | 
|  | 97 | #define CLASS_BIT_FROM_OFFSET(byteOffset) \ | 
|  | 98 | (CLASS_HIGH_BIT >> _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset)) | 
|  | 99 | /* | 
|  | 100 | * Return an offset, given a bit number as returned from CLZ. | 
|  | 101 | */ | 
|  | 102 | #define CLASS_OFFSET_FROM_CLZ(rshift) \ | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 103 | ((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT) + CLASS_SMALLEST_OFFSET) | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 104 |  | 
|  | 105 |  | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 106 | class Object { | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 107 | public: | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 108 | static Object* Alloc(Class* klass); | 
|  | 109 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 110 | Class* GetClass() const { | 
|  | 111 | return klass_; | 
|  | 112 | } | 
|  | 113 |  | 
|  | 114 | void MonitorEnter() { | 
|  | 115 | monitor_->Enter(); | 
|  | 116 | } | 
|  | 117 |  | 
|  | 118 | void MonitorExit() { | 
|  | 119 | monitor_->Exit(); | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | void Notify() { | 
|  | 123 | monitor_->Notify(); | 
|  | 124 | } | 
|  | 125 |  | 
|  | 126 | void NotifyAll() { | 
|  | 127 | monitor_->NotifyAll(); | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | void Wait() { | 
|  | 131 | monitor_->Wait(); | 
|  | 132 | } | 
|  | 133 |  | 
|  | 134 | void Wait(int64_t timeout) { | 
|  | 135 | monitor_->Wait(timeout); | 
|  | 136 | } | 
|  | 137 |  | 
|  | 138 | void Wait(int64_t timeout, int32_t nanos) { | 
|  | 139 | monitor_->Wait(timeout, nanos); | 
|  | 140 | } | 
|  | 141 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 142 | const Object* GetFieldObject(size_t field_offset) const { | 
|  | 143 | const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset; | 
|  | 144 | return *reinterpret_cast<Object* const*>(raw_addr); | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 | Object* GetFieldObject(size_t field_offset) { | 
|  | 148 | return const_cast<Object*>(GetFieldObject(field_offset)); | 
|  | 149 | } | 
|  | 150 |  | 
|  | 151 | void SetFieldObject(size_t offset, Object* new_value) { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 152 | byte* raw_addr = reinterpret_cast<byte*>(this) + offset; | 
|  | 153 | *reinterpret_cast<Object**>(raw_addr) = new_value; | 
|  | 154 | // TODO: write barrier | 
|  | 155 | } | 
|  | 156 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 157 | bool IsClass() const { | 
|  | 158 | LOG(FATAL) << "Unimplemented"; | 
|  | 159 | return true; | 
|  | 160 | } | 
|  | 161 |  | 
|  | 162 | Class* AsClass() { | 
|  | 163 | return down_cast<Class*>(this); | 
|  | 164 | } | 
|  | 165 |  | 
|  | 166 | const Class* AsClass() const { | 
|  | 167 | return down_cast<const Class*>(this); | 
|  | 168 | } | 
|  | 169 |  | 
|  | 170 | bool IsObjectArray() const { | 
|  | 171 | LOG(FATAL) << "Unimplemented"; | 
|  | 172 | return true; | 
|  | 173 | } | 
|  | 174 |  | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 175 | const ObjectArray<Object>* AsObjectArray() const { | 
|  | 176 | return down_cast<const ObjectArray<Object>*>(this); | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 177 | } | 
|  | 178 |  | 
|  | 179 | bool IsReference() const { | 
|  | 180 | LOG(FATAL) << "Unimplemented"; | 
|  | 181 | return true; | 
|  | 182 | } | 
|  | 183 |  | 
|  | 184 | bool IsWeakReference() const { | 
|  | 185 | LOG(FATAL) << "Unimplemented"; | 
|  | 186 | return true; | 
|  | 187 | } | 
|  | 188 |  | 
|  | 189 | bool IsSoftReference() const { | 
|  | 190 | LOG(FATAL) << "Unimplemented"; | 
|  | 191 | return true; | 
|  | 192 | } | 
|  | 193 |  | 
|  | 194 | bool IsFinalizerReference() const { | 
|  | 195 | LOG(FATAL) << "Unimplemented"; | 
|  | 196 | return true; | 
|  | 197 | } | 
|  | 198 |  | 
|  | 199 | bool IsPhantomReference() const { | 
|  | 200 | LOG(FATAL) << "Unimplemented"; | 
|  | 201 | return true; | 
|  | 202 | } | 
|  | 203 |  | 
|  | 204 | bool IsArray() const { | 
|  | 205 | LOG(FATAL) << "Unimplemented"; | 
|  | 206 | return true; | 
|  | 207 | } | 
|  | 208 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 209 | public: | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 210 | Class* klass_; | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 211 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 212 | Monitor* monitor_; | 
|  | 213 |  | 
|  | 214 | private: | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 215 | Object(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 216 | DISALLOW_COPY_AND_ASSIGN(Object); | 
|  | 217 | }; | 
|  | 218 |  | 
|  | 219 | class ObjectLock { | 
|  | 220 | public: | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 221 | explicit ObjectLock(Object* object) : obj_(object) { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 222 | CHECK(object != NULL); | 
|  | 223 | obj_->MonitorEnter(); | 
|  | 224 | } | 
|  | 225 |  | 
|  | 226 | ~ObjectLock() { | 
|  | 227 | obj_->MonitorExit(); | 
|  | 228 | } | 
|  | 229 |  | 
|  | 230 | void Wait(int64_t millis = 0) { | 
|  | 231 | return obj_->Wait(millis); | 
|  | 232 | } | 
|  | 233 |  | 
|  | 234 | void Notify() { | 
|  | 235 | obj_->Notify(); | 
|  | 236 | } | 
|  | 237 |  | 
|  | 238 | void NotifyAll() { | 
|  | 239 | obj_->NotifyAll(); | 
|  | 240 | } | 
|  | 241 |  | 
|  | 242 | private: | 
|  | 243 | Object* obj_; | 
|  | 244 | DISALLOW_COPY_AND_ASSIGN(ObjectLock); | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 245 | }; | 
|  | 246 |  | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 247 | class Field : public Object { | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 248 | public: | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 249 | Class* GetDeclaringClass() const { | 
|  | 250 | return declaring_class_; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 251 | } | 
|  | 252 |  | 
| Brian Carlstrom | ae3ac01 | 2011-07-27 01:30:28 -0700 | [diff] [blame] | 253 | const StringPiece& GetName() const { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 254 | return name_; | 
|  | 255 | } | 
|  | 256 |  | 
|  | 257 | char GetType() const {  // TODO: return type | 
| Brian Carlstrom | ae3ac01 | 2011-07-27 01:30:28 -0700 | [diff] [blame] | 258 | return descriptor_[0]; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 259 | } | 
|  | 260 |  | 
| Brian Carlstrom | ae3ac01 | 2011-07-27 01:30:28 -0700 | [diff] [blame] | 261 | const StringPiece& GetDescriptor() const { | 
|  | 262 | return descriptor_; | 
| Carl Shapiro | 5fafe2b | 2011-07-09 15:34:41 -0700 | [diff] [blame] | 263 | } | 
|  | 264 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 265 | public:  // TODO: private | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 266 | #define FIELD_FIELD_SLOTS 1+6 | 
|  | 267 | // AccessibleObject #0 flag | 
|  | 268 | // Field #0 declaringClass | 
|  | 269 | // Field #1 genericType | 
|  | 270 | // Field #2 genericTypesAreInitialized | 
|  | 271 | // Field #3 name | 
|  | 272 | // Field #4 slot | 
|  | 273 | // Field #5 type | 
|  | 274 | uint32_t instance_data_[FIELD_FIELD_SLOTS]; | 
|  | 275 | #undef FIELD_FIELD_SLOTS | 
|  | 276 |  | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 277 | // The class in which this field is declared. | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 278 | Class* declaring_class_; | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 279 |  | 
| Brian Carlstrom | ae3ac01 | 2011-07-27 01:30:28 -0700 | [diff] [blame] | 280 | StringPiece name_; | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 281 |  | 
|  | 282 | // e.g. "I", "[C", "Landroid/os/Debug;" | 
| Brian Carlstrom | ae3ac01 | 2011-07-27 01:30:28 -0700 | [diff] [blame] | 283 | StringPiece descriptor_; | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 284 |  | 
|  | 285 | uint32_t access_flags_; | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 286 |  | 
|  | 287 | private: | 
|  | 288 | Field(); | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 289 | }; | 
|  | 290 |  | 
|  | 291 | // Instance fields. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 292 | class InstanceField : public Field { | 
|  | 293 | public: | 
|  | 294 | uint32_t GetOffset() const { | 
|  | 295 | return offset_; | 
|  | 296 | } | 
|  | 297 |  | 
|  | 298 | void SetOffset(size_t num_bytes) { | 
|  | 299 | offset_ = num_bytes; | 
|  | 300 | } | 
|  | 301 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 302 | private: | 
|  | 303 | size_t offset_; | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 304 | InstanceField(); | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 305 | }; | 
|  | 306 |  | 
|  | 307 | // Static fields. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 308 | class StaticField : public Field { | 
| Carl Shapiro | 5fafe2b | 2011-07-09 15:34:41 -0700 | [diff] [blame] | 309 | public: | 
|  | 310 | void SetBoolean(bool z) { | 
|  | 311 | CHECK_EQ(GetType(), 'Z'); | 
|  | 312 | value_.z = z; | 
|  | 313 | } | 
|  | 314 |  | 
|  | 315 | void SetByte(int8_t b) { | 
|  | 316 | CHECK_EQ(GetType(), 'B'); | 
|  | 317 | value_.b = b; | 
|  | 318 | } | 
|  | 319 |  | 
|  | 320 | void SetChar(uint16_t c) { | 
|  | 321 | CHECK_EQ(GetType(), 'C'); | 
|  | 322 | value_.c = c; | 
|  | 323 | } | 
|  | 324 |  | 
|  | 325 | void SetShort(uint16_t s) { | 
|  | 326 | CHECK_EQ(GetType(), 'S'); | 
|  | 327 | value_.s = s; | 
|  | 328 | } | 
|  | 329 |  | 
|  | 330 | void SetInt(int32_t i) { | 
|  | 331 | CHECK_EQ(GetType(), 'I'); | 
|  | 332 | value_.i = i; | 
|  | 333 | } | 
|  | 334 |  | 
|  | 335 | int64_t GetLong() { | 
|  | 336 | CHECK_EQ(GetType(), 'J'); | 
|  | 337 | return value_.j; | 
|  | 338 | } | 
|  | 339 |  | 
|  | 340 | void SetLong(int64_t j) { | 
|  | 341 | CHECK_EQ(GetType(), 'J'); | 
|  | 342 | value_.j = j; | 
|  | 343 | } | 
|  | 344 |  | 
|  | 345 | void SetFloat(float f) { | 
|  | 346 | CHECK_EQ(GetType(), 'F'); | 
|  | 347 | value_.f = f; | 
|  | 348 | } | 
|  | 349 |  | 
|  | 350 | void SetDouble(double d) { | 
|  | 351 | CHECK_EQ(GetType(), 'D'); | 
|  | 352 | value_.d = d; | 
|  | 353 | } | 
|  | 354 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 355 | Object* GetObject() { | 
|  | 356 | return value_.l; | 
|  | 357 | } | 
|  | 358 |  | 
|  | 359 | const Object* GetObject() const { | 
|  | 360 | return value_.l; | 
|  | 361 | } | 
|  | 362 |  | 
| Carl Shapiro | 5fafe2b | 2011-07-09 15:34:41 -0700 | [diff] [blame] | 363 | void SetObject(Object* l) { | 
| Carl Shapiro | 565f507 | 2011-07-10 13:39:43 -0700 | [diff] [blame] | 364 | CHECK(GetType() == 'L' || GetType() == '['); | 
| Carl Shapiro | 5fafe2b | 2011-07-09 15:34:41 -0700 | [diff] [blame] | 365 | value_.l = l; | 
|  | 366 | // TODO: write barrier | 
|  | 367 | } | 
|  | 368 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 369 | private: | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 370 | JValue value_; | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 371 | StaticField(); | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 372 | }; | 
|  | 373 |  | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 374 | class Method : public Object { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 375 | public: | 
| Brian Carlstrom | ae3ac01 | 2011-07-27 01:30:28 -0700 | [diff] [blame] | 376 | // Returns the method name, e.g. "<init>" or "eatLunch" | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 377 | const StringPiece& GetName() const { | 
|  | 378 | return name_; | 
|  | 379 | } | 
|  | 380 |  | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 381 | Class* GetDeclaringClass() const { | 
|  | 382 | return declaring_class_; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 383 | } | 
|  | 384 |  | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 385 | static MemberOffset ClassOffset() { | 
|  | 386 | return MemberOffset(OFFSETOF_MEMBER(Method, klass_)); | 
|  | 387 | } | 
|  | 388 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 389 | // const char* GetReturnTypeDescriptor() const { | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 390 | //   return FindDexFile(declaring_class_->GetDexCache() | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 391 | //          ->dexStringByTypeIdx(proto_id_.return_type_id_); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 392 | // } | 
|  | 393 |  | 
|  | 394 | // Returns true if the method is declared public. | 
|  | 395 | bool IsPublic() const { | 
|  | 396 | return (access_flags_ & kAccPublic) != 0; | 
|  | 397 | } | 
|  | 398 |  | 
|  | 399 | // Returns true if the method is declared private. | 
|  | 400 | bool IsPrivate() const { | 
|  | 401 | return (access_flags_ & kAccPrivate) != 0; | 
|  | 402 | } | 
|  | 403 |  | 
|  | 404 | // Returns true if the method is declared static. | 
|  | 405 | bool IsStatic() const { | 
|  | 406 | return (access_flags_ & kAccStatic) != 0; | 
|  | 407 | } | 
|  | 408 |  | 
|  | 409 | // Returns true if the method is declared synchronized. | 
|  | 410 | bool IsSynchronized() const { | 
|  | 411 | uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized; | 
|  | 412 | return (access_flags_ & synchonized) != 0; | 
|  | 413 | } | 
|  | 414 |  | 
|  | 415 | // Returns true if the method is declared final. | 
|  | 416 | bool IsFinal() const { | 
|  | 417 | return (access_flags_ & kAccFinal) != 0; | 
|  | 418 | } | 
|  | 419 |  | 
|  | 420 | // Returns true if the method is declared native. | 
|  | 421 | bool IsNative() const { | 
|  | 422 | return (access_flags_ & kAccNative) != 0; | 
|  | 423 | } | 
|  | 424 |  | 
|  | 425 | // Returns true if the method is declared abstract. | 
|  | 426 | bool IsAbstract() const { | 
|  | 427 | return (access_flags_ & kAccAbstract) != 0; | 
|  | 428 | } | 
|  | 429 |  | 
|  | 430 | bool IsSynthetic() const { | 
|  | 431 | return (access_flags_ & kAccSynthetic) != 0; | 
|  | 432 | } | 
|  | 433 |  | 
|  | 434 | // Number of argument registers required by the prototype. | 
|  | 435 | uint32_t NumArgRegisters(); | 
|  | 436 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 437 | public:  // TODO: private | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 438 | #define METHOD_FIELD_SLOTS 1+11 | 
|  | 439 | // AccessibleObject #0 flag | 
|  | 440 | // Method #0  declaringClass | 
|  | 441 | // Method #1  exceptionTypes | 
|  | 442 | // Method #2  formalTypeParameters | 
|  | 443 | // Method #3  genericExceptionTypes | 
|  | 444 | // Method #4  genericParameterTypes | 
|  | 445 | // Method #5  genericReturnType | 
|  | 446 | // Method #6  genericTypesAreInitialized | 
|  | 447 | // Method #7  name | 
|  | 448 | // Method #8  parameterTypes | 
|  | 449 | // Method #9  returnType | 
|  | 450 | // Method #10 slot | 
|  | 451 | uint32_t instance_data_[METHOD_FIELD_SLOTS]; | 
|  | 452 | #undef METHOD_FIELD_SLOTS | 
|  | 453 |  | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 454 | bool IsReturnAReference() const { | 
|  | 455 | return (shorty_[0] == 'L') || (shorty_[0] == '['); | 
|  | 456 | } | 
|  | 457 |  | 
|  | 458 | bool IsReturnAFloatOrDouble() const { | 
|  | 459 | return (shorty_[0] == 'F') || (shorty_[0] == 'D'); | 
|  | 460 | } | 
|  | 461 |  | 
|  | 462 | bool IsReturnAFloat() const { | 
|  | 463 | return shorty_[0] == 'F'; | 
|  | 464 | } | 
|  | 465 |  | 
|  | 466 | bool IsReturnADouble() const { | 
|  | 467 | return shorty_[0] == 'D'; | 
|  | 468 | } | 
|  | 469 |  | 
|  | 470 | bool IsReturnALong() const { | 
|  | 471 | return shorty_[0] == 'J'; | 
|  | 472 | } | 
|  | 473 |  | 
| Ian Rogers | 45a76cb | 2011-07-21 22:00:15 -0700 | [diff] [blame] | 474 | bool IsReturnVoid() const { | 
|  | 475 | return shorty_[0] == 'V'; | 
|  | 476 | } | 
|  | 477 |  | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 478 | // The number of arguments that should be supplied to this method | 
|  | 479 | size_t NumArgs() const { | 
|  | 480 | return (IsStatic() ? 0 : 1) + shorty_.length() - 1; | 
|  | 481 | } | 
|  | 482 |  | 
|  | 483 | // The number of reference arguments to this method including implicit this | 
|  | 484 | // pointer | 
|  | 485 | size_t NumReferenceArgs() const; | 
|  | 486 |  | 
|  | 487 | // The number of long or double arguments | 
|  | 488 | size_t NumLongOrDoubleArgs() const; | 
|  | 489 |  | 
|  | 490 | // The number of reference arguments to this method before the given | 
|  | 491 | // parameter index | 
|  | 492 | size_t NumReferenceArgsBefore(unsigned int param) const; | 
|  | 493 |  | 
|  | 494 | // Is the given method parameter a reference? | 
|  | 495 | bool IsParamAReference(unsigned int param) const; | 
|  | 496 |  | 
|  | 497 | // Is the given method parameter a long or double? | 
|  | 498 | bool IsParamALongOrDouble(unsigned int param) const; | 
|  | 499 |  | 
| Ian Rogers | df20fe0 | 2011-07-20 20:34:16 -0700 | [diff] [blame] | 500 | // Size in bytes of the given parameter | 
|  | 501 | size_t ParamSize(unsigned int param) const; | 
|  | 502 |  | 
|  | 503 | // Size in bytes of the return value | 
|  | 504 | size_t ReturnSize() const; | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 505 |  | 
|  | 506 | void SetCode(const void* code) { | 
|  | 507 | code_ = code; | 
|  | 508 | } | 
|  | 509 |  | 
|  | 510 | const void* GetCode() const { | 
|  | 511 | return code_; | 
|  | 512 | } | 
|  | 513 |  | 
|  | 514 | void RegisterNative(const void* native_method) { | 
|  | 515 | native_method_ = native_method; | 
|  | 516 | } | 
|  | 517 |  | 
|  | 518 | static MemberOffset NativeMethodOffset() { | 
|  | 519 | return MemberOffset(OFFSETOF_MEMBER(Method, native_method_)); | 
|  | 520 | } | 
|  | 521 |  | 
|  | 522 | public:  // TODO: private/const | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 523 | // the class we are a part of | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 524 | Class* declaring_class_; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 525 |  | 
|  | 526 | // access flags; low 16 bits are defined by spec (could be uint16_t?) | 
|  | 527 | uint32_t access_flags_; | 
|  | 528 |  | 
|  | 529 | // For concrete virtual methods, this is the offset of the method | 
|  | 530 | // in "vtable". | 
|  | 531 | // | 
|  | 532 | // For abstract methods in an interface class, this is the offset | 
|  | 533 | // of the method in "iftable[n]->methodIndexArray". | 
|  | 534 | uint16_t method_index_; | 
|  | 535 |  | 
|  | 536 | // Method bounds; not needed for an abstract method. | 
|  | 537 | // | 
|  | 538 | // For a native method, we compute the size of the argument list, and | 
|  | 539 | // set "insSize" and "registerSize" equal to it. | 
|  | 540 | uint16_t num_registers_;  // ins + locals | 
|  | 541 | uint16_t num_outs_; | 
|  | 542 | uint16_t num_ins_; | 
|  | 543 |  | 
|  | 544 | // method name, e.g. "<init>" or "eatLunch" | 
|  | 545 | StringPiece name_; | 
|  | 546 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 547 | // Method prototype descriptor string (return and argument types). | 
|  | 548 | uint32_t proto_idx_; | 
|  | 549 |  | 
|  | 550 | // The short-form method descriptor string. | 
|  | 551 | StringPiece shorty_; | 
|  | 552 |  | 
|  | 553 | // A pointer to the memory-mapped DEX code. | 
|  | 554 | const uint16_t* insns_; | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 555 |  | 
|  | 556 | private: | 
|  | 557 | Method(); | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 558 |  | 
|  | 559 | // Compiled code associated with this method | 
|  | 560 | const void* code_; | 
|  | 561 |  | 
|  | 562 | // Any native method registered with this method | 
|  | 563 | const void* native_method_; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 564 | }; | 
|  | 565 |  | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 566 | class Array : public Object { | 
|  | 567 | public: | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 568 | static Array* Alloc(Class* array_class, | 
|  | 569 | size_t component_count, | 
|  | 570 | size_t component_size) { | 
|  | 571 | size_t size = sizeof(Array) + component_count * component_size; | 
|  | 572 | Array* array = down_cast<Array*>(Heap::AllocObject(array_class, size)); | 
|  | 573 | if (array != NULL) { | 
|  | 574 | array->SetLength(component_count); | 
|  | 575 | } | 
|  | 576 | return array; | 
|  | 577 | } | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 578 | uint32_t GetLength() const { | 
|  | 579 | return length_; | 
|  | 580 | } | 
|  | 581 | void SetLength(uint32_t length) { | 
|  | 582 | length_ = length; | 
|  | 583 | } | 
|  | 584 | const void* GetData() const { | 
|  | 585 | return &elements_; | 
|  | 586 | } | 
|  | 587 | void* GetData() { | 
|  | 588 | return &elements_; | 
|  | 589 | } | 
|  | 590 |  | 
|  | 591 | private: | 
|  | 592 | // The number of array elements. | 
|  | 593 | uint32_t length_; | 
|  | 594 | // Location of first element. | 
|  | 595 | uint32_t elements_[0]; | 
|  | 596 | Array(); | 
|  | 597 | }; | 
|  | 598 |  | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 599 | template<class T> | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 600 | class ObjectArray : public Array { | 
|  | 601 | public: | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 602 | static ObjectArray<T>* Alloc(Class* object_array_class, | 
|  | 603 | size_t length) { | 
|  | 604 | return down_cast<ObjectArray<T>*>(Array::Alloc(object_array_class, | 
|  | 605 | length, | 
|  | 606 | sizeof(uint32_t))); | 
|  | 607 | } | 
|  | 608 |  | 
|  | 609 | T* Get(uint32_t i) const { | 
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 610 | CHECK_LT(i, GetLength()); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 611 | Object* const * data = reinterpret_cast<Object* const *>(GetData()); | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 612 | return down_cast<T*>(data[i]); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 613 | } | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 614 | void Set(uint32_t i, T* object) { | 
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 615 | CHECK_LT(i, GetLength()); | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 616 | T** data = reinterpret_cast<T**>(GetData()); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 617 | data[i] = object; | 
|  | 618 | } | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 619 | static void Copy(ObjectArray<T>* src, int src_pos, ObjectArray<T>* dst, int dst_pos, size_t length) { | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 620 | for (size_t i = 0; i < length; i++) { | 
|  | 621 | dst->Set(dst_pos + i, src->Get(src_pos + i)); | 
|  | 622 | } | 
|  | 623 | } | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 624 | ObjectArray<T>* CopyOf(size_t new_length) { | 
|  | 625 | ObjectArray<T>* new_array = Alloc(klass_, new_length); | 
|  | 626 | Copy(this, 0, new_array, 0, std::min(GetLength(), new_length)); | 
|  | 627 | return new_array; | 
|  | 628 | } | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 629 |  | 
|  | 630 | private: | 
|  | 631 | ObjectArray(); | 
|  | 632 | }; | 
|  | 633 |  | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 634 | // Class objects. | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 635 | class Class : public Object { | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 636 | public: | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 637 | enum Status { | 
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 638 | kStatusError = -1, | 
|  | 639 | kStatusNotReady = 0, | 
|  | 640 | kStatusIdx = 1,  // loaded, DEX idx in super or ifaces | 
|  | 641 | kStatusLoaded = 2,  // DEX idx values resolved | 
|  | 642 | kStatusResolved = 3,  // part of linking | 
|  | 643 | kStatusVerifying = 4,  // in the process of being verified | 
|  | 644 | kStatusVerified = 5,  // logically part of linking; done pre-init | 
|  | 645 | kStatusInitializing = 6,  // class init in progress | 
|  | 646 | kStatusInitialized = 7,  // ready to go | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 647 | }; | 
|  | 648 |  | 
|  | 649 | enum PrimitiveType { | 
|  | 650 | kPrimNot = -1 | 
|  | 651 | }; | 
|  | 652 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 653 | Class* GetSuperClass() const { | 
|  | 654 | return super_class_; | 
|  | 655 | } | 
|  | 656 |  | 
|  | 657 | uint32_t GetSuperClassIdx() const { | 
|  | 658 | return super_class_idx_; | 
|  | 659 | } | 
|  | 660 |  | 
|  | 661 | bool HasSuperClass() const { | 
|  | 662 | return super_class_ != NULL; | 
|  | 663 | } | 
|  | 664 |  | 
|  | 665 | Object* GetClassLoader() const { | 
|  | 666 | return class_loader_; | 
|  | 667 | } | 
|  | 668 |  | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 669 | DexCache* GetDexCache() const { | 
|  | 670 | return dex_cache_; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 671 | } | 
|  | 672 |  | 
|  | 673 | Class* GetComponentType() const { | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 674 | DCHECK(IsArray()); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 675 | return component_type_; | 
|  | 676 | } | 
|  | 677 |  | 
|  | 678 | const StringPiece& GetDescriptor() const { | 
|  | 679 | return descriptor_; | 
|  | 680 | } | 
|  | 681 |  | 
|  | 682 | Status GetStatus() const { | 
|  | 683 | return status_; | 
|  | 684 | } | 
|  | 685 |  | 
|  | 686 | void SetStatus(Status new_status) { | 
|  | 687 | // TODO: validate transition | 
|  | 688 | status_ = new_status; | 
|  | 689 | } | 
|  | 690 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 691 | // Returns true if the class has failed to link. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 692 | bool IsErroneous() const { | 
|  | 693 | return GetStatus() == kStatusError; | 
|  | 694 | } | 
|  | 695 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 696 | // Returns true if the class has been verified. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 697 | bool IsVerified() const { | 
|  | 698 | return GetStatus() >= kStatusVerified; | 
|  | 699 | } | 
|  | 700 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 701 | // Returns true if the class has been linked. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 702 | bool IsLinked() const { | 
|  | 703 | return GetStatus() >= kStatusResolved; | 
|  | 704 | } | 
|  | 705 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 706 | bool IsLoaded() const { | 
|  | 707 | return GetStatus() >= kStatusLoaded; | 
|  | 708 | } | 
|  | 709 |  | 
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 710 | // Returns true if this class is in the same packages as that class. | 
|  | 711 | bool IsInSamePackage(const Class* that) const; | 
|  | 712 |  | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 713 | static bool IsInSamePackage(const StringPiece& descriptor1, | 
|  | 714 | const StringPiece& descriptor2); | 
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 715 |  | 
|  | 716 | // Returns true if this class represents an array class. | 
|  | 717 | bool IsArray() const { | 
|  | 718 | return descriptor_[0] == '[';  // TODO: avoid parsing the descriptor | 
|  | 719 | } | 
|  | 720 |  | 
|  | 721 | // Returns true if the class is an interface. | 
|  | 722 | bool IsInterface() const { | 
|  | 723 | return (access_flags_ & kAccInterface) != 0; | 
|  | 724 | } | 
|  | 725 |  | 
|  | 726 | // Returns true if the class is declared public. | 
|  | 727 | bool IsPublic() const { | 
|  | 728 | return (access_flags_ & kAccPublic) != 0; | 
|  | 729 | } | 
|  | 730 |  | 
|  | 731 | // Returns true if the class is declared final. | 
|  | 732 | bool IsFinal() const { | 
|  | 733 | return (access_flags_ & kAccFinal) != 0; | 
|  | 734 | } | 
|  | 735 |  | 
|  | 736 | // Returns true if the class is abstract. | 
|  | 737 | bool IsAbstract() const { | 
|  | 738 | return (access_flags_ & kAccAbstract) != 0; | 
|  | 739 | } | 
|  | 740 |  | 
|  | 741 | // Returns true if the class is an annotation. | 
|  | 742 | bool IsAnnotation() const { | 
|  | 743 | return (access_flags_ & kAccAnnotation) != 0; | 
|  | 744 | } | 
|  | 745 |  | 
|  | 746 | // Returns true if the class is a primitive type. | 
|  | 747 | bool IsPrimitive() const { | 
|  | 748 | return primitive_type_ != kPrimNot; | 
|  | 749 | } | 
|  | 750 |  | 
| Brian Carlstrom | ae3ac01 | 2011-07-27 01:30:28 -0700 | [diff] [blame] | 751 | // Returns true if the class is synthetic. | 
|  | 752 | bool IsSynthetic() const { | 
|  | 753 | return (access_flags_ & kAccSynthetic) != 0; | 
|  | 754 | } | 
|  | 755 |  | 
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 756 | // Returns true if this class can access that class. | 
|  | 757 | bool CanAccess(const Class* that) const { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 758 | return that->IsPublic() || this->IsInSamePackage(that); | 
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 759 | } | 
|  | 760 |  | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 761 | // Returns the size in bytes of a class object instance with the | 
|  | 762 | // given number of static fields. | 
| Carl Shapiro | 565f507 | 2011-07-10 13:39:43 -0700 | [diff] [blame] | 763 | // static size_t Size(size_t num_sfields) { | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 764 | //   return OFFSETOF_MEMBER(Class, sfields_) + | 
|  | 765 | //          sizeof(StaticField) * num_sfields; | 
| Carl Shapiro | 565f507 | 2011-07-10 13:39:43 -0700 | [diff] [blame] | 766 | // } | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 767 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 768 | // Returns the number of static, private, and constructor methods. | 
|  | 769 | size_t NumDirectMethods() const { | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 770 | return (direct_methods_ != NULL) ? direct_methods_->GetLength() : 0; | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 771 | } | 
|  | 772 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 773 | Method* GetDirectMethod(uint32_t i) const { | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 774 | DCHECK_NE(NumDirectMethods(), 0U); | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 775 | return direct_methods_->Get(i); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 776 | } | 
|  | 777 |  | 
|  | 778 | void SetDirectMethod(uint32_t i, Method* f) {  // TODO: uint16_t | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 779 | DCHECK_NE(NumDirectMethods(), 0U); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 780 | direct_methods_->Set(i, f); | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 781 | } | 
|  | 782 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 783 | // Returns the number of non-inherited virtual methods. | 
|  | 784 | size_t NumVirtualMethods() const { | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 785 | return (virtual_methods_ != NULL) ? virtual_methods_->GetLength() : 0; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 786 | } | 
|  | 787 |  | 
|  | 788 | Method* GetVirtualMethod(uint32_t i) const { | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 789 | DCHECK_NE(NumVirtualMethods(), 0U); | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 790 | return virtual_methods_->Get(i); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 791 | } | 
|  | 792 |  | 
|  | 793 | void SetVirtualMethod(uint32_t i, Method* f) {  // TODO: uint16_t | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 794 | DCHECK_NE(NumVirtualMethods(), 0U); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 795 | virtual_methods_->Set(i, f); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 796 | } | 
|  | 797 |  | 
|  | 798 | size_t NumInstanceFields() const { | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 799 | return (ifields_ != NULL) ? ifields_->GetLength() : 0; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 800 | } | 
|  | 801 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 802 | // Returns the number of instance fields containing reference types. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 803 | size_t NumReferenceInstanceFields() const { | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 804 | return num_reference_instance_fields_; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 805 | } | 
|  | 806 |  | 
|  | 807 | InstanceField* GetInstanceField(uint32_t i) {  // TODO: uint16_t | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 808 | DCHECK_NE(NumInstanceFields(), 0U); | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 809 | return ifields_->Get(i); | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 810 | } | 
|  | 811 |  | 
|  | 812 | void SetInstanceField(uint32_t i, InstanceField* f) {  // TODO: uint16_t | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 813 | DCHECK_NE(NumInstanceFields(), 0U); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 814 | ifields_->Set(i, f); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 815 | } | 
|  | 816 |  | 
|  | 817 | size_t NumStaticFields() const { | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 818 | return (sfields_ != NULL) ? sfields_->GetLength() : 0; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 819 | } | 
|  | 820 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 821 | StaticField* GetStaticField(uint32_t i) const {  // TODO: uint16_t | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 822 | DCHECK_NE(NumStaticFields(), 0U); | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 823 | return sfields_->Get(i); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 824 | } | 
|  | 825 |  | 
|  | 826 | void SetStaticField(uint32_t i, StaticField* f) {  // TODO: uint16_t | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 827 | DCHECK_NE(NumStaticFields(), 0U); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 828 | sfields_->Set(i, f); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 829 | } | 
|  | 830 |  | 
|  | 831 | uint32_t GetReferenceOffsets() const { | 
|  | 832 | return reference_offsets_; | 
|  | 833 | } | 
|  | 834 |  | 
|  | 835 | void SetReferenceOffsets(uint32_t new_reference_offsets) { | 
|  | 836 | reference_offsets_ = new_reference_offsets; | 
|  | 837 | } | 
|  | 838 |  | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 839 | Method* FindDirectMethod(const StringPiece& name) const; | 
|  | 840 |  | 
|  | 841 | Method* FindVirtualMethod(const StringPiece& name) const; | 
|  | 842 |  | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 843 | size_t NumInterfaces() const { | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 844 | return (interfaces_ != NULL) ? interfaces_->GetLength() : 0; | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 845 | } | 
|  | 846 |  | 
|  | 847 | Class* GetInterface(uint32_t i) const { | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 848 | DCHECK_NE(NumInterfaces(), 0U); | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 849 | return interfaces_->Get(i); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 850 | } | 
|  | 851 |  | 
|  | 852 | void SetInterface(uint32_t i, Class* f) {  // TODO: uint16_t | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame^] | 853 | DCHECK_NE(NumInterfaces(), 0U); | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 854 | interfaces_->Set(i, f); | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 855 | } | 
|  | 856 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 857 | Method* FindDirectMethodLocally(const StringPiece& name, | 
|  | 858 | const StringPiece& descriptor) const; | 
|  | 859 |  | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 860 | public:  // TODO: private | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 861 | // leave space for instance data; we could access fields directly if | 
|  | 862 | // we freeze the definition of java/lang/Class | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 863 | #define CLASS_FIELD_SLOTS 1 | 
|  | 864 | // Class.#0 name | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 865 | uint32_t instance_data_[CLASS_FIELD_SLOTS]; | 
|  | 866 | #undef CLASS_FIELD_SLOTS | 
|  | 867 |  | 
|  | 868 | // UTF-8 descriptor for the class from constant pool | 
|  | 869 | // ("Ljava/lang/Class;"), or on heap if generated ("[C") | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 870 | StringPiece descriptor_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 871 |  | 
|  | 872 | // Proxy classes have their descriptor allocated on the native heap. | 
|  | 873 | // When this field is non-NULL it must be explicitly freed. | 
| Brian Carlstrom | a331b3c | 2011-07-18 17:47:56 -0700 | [diff] [blame] | 874 | std::string* descriptor_alloc_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 875 |  | 
|  | 876 | // access flags; low 16 bits are defined by VM spec | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 877 | uint32_t access_flags_;  // TODO: make an instance field? | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 878 |  | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 879 | // DexCache of resolved constant pool entries | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 880 | // (will be NULL for VM-generated, e.g. arrays and primitive classes) | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 881 | DexCache* dex_cache_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 882 |  | 
|  | 883 | // state of class initialization | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 884 | Status status_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 885 |  | 
|  | 886 | // if class verify fails, we must return same error on subsequent tries | 
|  | 887 | Class* verify_error_class_; | 
|  | 888 |  | 
|  | 889 | // threadId, used to check for recursive <clinit> invocation | 
|  | 890 | uint32_t clinit_thread_id_; | 
|  | 891 |  | 
|  | 892 | // Total object size; used when allocating storage on gc heap.  (For | 
|  | 893 | // interfaces and abstract classes this will be zero.) | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 894 | size_t object_size_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 895 |  | 
|  | 896 | // For array classes, the class object for base element, for | 
|  | 897 | // instanceof/checkcast (for String[][][], this will be String). | 
|  | 898 | // Otherwise, NULL. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 899 | Class* component_type_;  // TODO: make an instance field | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 900 |  | 
|  | 901 | // For array classes, the number of array dimensions, e.g. int[][] | 
|  | 902 | // is 2.  Otherwise 0. | 
|  | 903 | int32_t array_rank_; | 
|  | 904 |  | 
|  | 905 | // primitive type index, or PRIM_NOT (-1); set for generated prim classes | 
|  | 906 | PrimitiveType primitive_type_; | 
|  | 907 |  | 
|  | 908 | // The superclass, or NULL if this is java.lang.Object or a | 
|  | 909 | // primitive type. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 910 | Class* super_class_;  // TODO: make an instance field | 
|  | 911 | uint32_t super_class_idx_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 912 |  | 
|  | 913 | // defining class loader, or NULL for the "bootstrap" system loader | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 914 | Object* class_loader_;  // TODO: make an instance field | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 915 |  | 
|  | 916 | // initiating class loader list | 
|  | 917 | // NOTE: for classes with low serialNumber, these are unused, and the | 
|  | 918 | // values are kept in a table in gDvm. | 
| Ian Rogers | b033c75 | 2011-07-20 12:22:35 -0700 | [diff] [blame] | 919 | // InitiatingLoaderList initiating_loader_list_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 920 |  | 
|  | 921 | // array of interfaces this class implements directly | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 922 | ObjectArray<Class>* interfaces_; | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 923 | uint32_t* interfaces_idx_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 924 |  | 
|  | 925 | // static, private, and <init> methods | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 926 | ObjectArray<Method>* direct_methods_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 927 |  | 
|  | 928 | // virtual methods defined in this class; invoked through vtable | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 929 | ObjectArray<Method>* virtual_methods_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 930 |  | 
|  | 931 | // Virtual method table (vtable), for use by "invoke-virtual".  The | 
|  | 932 | // vtable from the superclass is copied in, and virtual methods from | 
|  | 933 | // our class either replace those from the super or are appended. | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 934 | ObjectArray<Method>* vtable_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 935 |  | 
|  | 936 | // Interface table (iftable), one entry per interface supported by | 
|  | 937 | // this class.  That means one entry for each interface we support | 
|  | 938 | // directly, indirectly via superclass, or indirectly via | 
|  | 939 | // superinterface.  This will be null if neither we nor our | 
|  | 940 | // superclass implement any interfaces. | 
|  | 941 | // | 
|  | 942 | // Why we need this: given "class Foo implements Face", declare | 
|  | 943 | // "Face faceObj = new Foo()".  Invoke faceObj.blah(), where "blah" | 
|  | 944 | // is part of the Face interface.  We can't easily use a single | 
|  | 945 | // vtable. | 
|  | 946 | // | 
|  | 947 | // For every interface a concrete class implements, we create a list | 
|  | 948 | // of virtualMethod indices for the methods in the interface. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 949 | size_t iftable_count_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 950 | InterfaceEntry* iftable_; | 
|  | 951 |  | 
|  | 952 | // The interface vtable indices for iftable get stored here.  By | 
|  | 953 | // placing them all in a single pool for each class that implements | 
|  | 954 | // interfaces, we decrease the number of allocations. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 955 | size_t ifvi_pool_count_; | 
|  | 956 | uint32_t* ifvi_pool_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 957 |  | 
|  | 958 | // instance fields | 
|  | 959 | // | 
|  | 960 | // These describe the layout of the contents of a | 
|  | 961 | // DataObject-compatible Object.  Note that only the fields directly | 
|  | 962 | // declared by this class are listed in ifields; fields declared by | 
| Brian Carlstrom | a331b3c | 2011-07-18 17:47:56 -0700 | [diff] [blame] | 963 | // a superclass are listed in the superclass's Class.ifields. | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 964 | // | 
|  | 965 | // All instance fields that refer to objects are guaranteed to be at | 
| Brian Carlstrom | 913af1b | 2011-07-23 21:41:13 -0700 | [diff] [blame] | 966 | // the beginning of the field list.  num_reference_instance_fields_ | 
|  | 967 | // specifies the number of reference fields. | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 968 | ObjectArray<InstanceField>* ifields_; | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 969 |  | 
|  | 970 | // number of fields that are object refs | 
| Carl Shapiro | 69759ea | 2011-07-21 18:13:35 -0700 | [diff] [blame] | 971 | size_t num_reference_instance_fields_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 972 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 973 | // Bitmap of offsets of ifields. | 
|  | 974 | uint32_t reference_offsets_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 975 |  | 
|  | 976 | // source file name, if known.  Otherwise, NULL. | 
|  | 977 | const char* source_file_; | 
|  | 978 |  | 
|  | 979 | // Static fields | 
| Brian Carlstrom | 4a96b60 | 2011-07-26 16:40:23 -0700 | [diff] [blame] | 980 | ObjectArray<StaticField>* sfields_; | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 981 |  | 
|  | 982 | private: | 
|  | 983 | Class(); | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 984 | }; | 
| Elliott Hughes | 1f359b0 | 2011-07-17 14:27:17 -0700 | [diff] [blame] | 985 | std::ostream& operator<<(std::ostream& os, const Class::Status& rhs); | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 986 |  | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 987 | inline Object* Object::Alloc(Class* klass) { | 
|  | 988 | return Heap::AllocObject(klass, klass->object_size_); | 
|  | 989 | } | 
|  | 990 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 991 | class DataObject : public Object { | 
|  | 992 | public: | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 993 | uint32_t fields_[0]; | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 994 | private: | 
|  | 995 | DataObject(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 996 | }; | 
|  | 997 |  | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 998 | class CharArray : public Array { | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 999 | public: | 
|  | 1000 | static CharArray* Alloc(Class* char_array_class, size_t length) { | 
|  | 1001 | return down_cast<CharArray*>(Array::Alloc(char_array_class, | 
|  | 1002 | length, | 
|  | 1003 | sizeof(uint16_t))); | 
|  | 1004 | } | 
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 1005 |  | 
|  | 1006 | uint16_t* GetChars() { | 
|  | 1007 | return reinterpret_cast<uint16_t*>(GetData()); | 
|  | 1008 | } | 
|  | 1009 |  | 
|  | 1010 | const uint16_t* GetChars() const { | 
|  | 1011 | return reinterpret_cast<const uint16_t*>(GetData()); | 
|  | 1012 | } | 
|  | 1013 |  | 
|  | 1014 | uint16_t GetChar(uint32_t i) const { | 
|  | 1015 | CHECK_LT(i, GetLength()); | 
|  | 1016 | return GetChars()[i]; | 
|  | 1017 | } | 
|  | 1018 |  | 
|  | 1019 | void  SetChar(uint32_t i, uint16_t ch) { | 
|  | 1020 | CHECK_LT(i, GetLength()); | 
|  | 1021 | GetChars()[i] = ch; | 
|  | 1022 | } | 
|  | 1023 |  | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 1024 | private: | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 1025 | CharArray(); | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 1026 | }; | 
| Carl Shapiro | 5fafe2b | 2011-07-09 15:34:41 -0700 | [diff] [blame] | 1027 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1028 | class String : public Object { | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 1029 | public: | 
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 1030 | static String* AllocFromUtf16(Class* java_lang_String, | 
|  | 1031 | Class* char_array, | 
|  | 1032 | int32_t utf16_length, | 
|  | 1033 | uint16_t* utf16_data_in) { | 
|  | 1034 | String* string = Alloc(java_lang_String, char_array, utf16_length); | 
|  | 1035 | uint16_t* utf16_data_out = string->array_->GetChars(); | 
|  | 1036 | // TODO use 16-bit wide memset variant | 
|  | 1037 | for (int i = 0; i < utf16_length; i++ ) { | 
|  | 1038 | utf16_data_out[i] = utf16_data_in[i]; | 
|  | 1039 | } | 
|  | 1040 | string->hash_code_ = ComputeUtf16Hash(utf16_data_out, utf16_length); | 
|  | 1041 | return string; | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 1042 | } | 
|  | 1043 |  | 
|  | 1044 | static String* AllocFromModifiedUtf8(Class* java_lang_String, | 
|  | 1045 | Class* char_array, | 
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 1046 | int32_t utf16_length, | 
|  | 1047 | const char* utf8_data_in) { | 
|  | 1048 | String* string = Alloc(java_lang_String, char_array, utf16_length); | 
|  | 1049 | uint16_t* utf16_data_out = string->array_->GetChars(); | 
|  | 1050 | ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in); | 
|  | 1051 | string->hash_code_ = ComputeUtf16Hash(utf16_data_out, utf16_length); | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 1052 | return string; | 
|  | 1053 | } | 
|  | 1054 |  | 
|  | 1055 | public: // TODO: private | 
| Jesse Wilson | ac5b9e2 | 2011-07-27 15:11:13 -0400 | [diff] [blame] | 1056 | // Field order required by test "ValidateFieldOrderOfJavaLangString". | 
| Carl Shapiro | 5fafe2b | 2011-07-09 15:34:41 -0700 | [diff] [blame] | 1057 | CharArray* array_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 1058 |  | 
|  | 1059 | uint32_t hash_code_; | 
|  | 1060 |  | 
|  | 1061 | uint32_t offset_; | 
|  | 1062 |  | 
|  | 1063 | uint32_t count_; | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 1064 |  | 
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 1065 | static String* Alloc(Class* java_lang_String, | 
|  | 1066 | Class* char_array, | 
|  | 1067 | int32_t utf16_length) { | 
|  | 1068 | String* string = down_cast<String*>(Object::Alloc(java_lang_String)); | 
|  | 1069 | CharArray* array = CharArray::Alloc(char_array, utf16_length); | 
|  | 1070 | string->array_ = array; | 
|  | 1071 | string->count_ = utf16_length; | 
|  | 1072 | return string; | 
|  | 1073 | } | 
|  | 1074 |  | 
|  | 1075 | // Convert Modified UTF-8 to UTF-16 | 
|  | 1076 | // http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8 | 
|  | 1077 | static void ConvertModifiedUtf8ToUtf16(uint16_t* utf16_data_out, const char* utf8_data_in) { | 
|  | 1078 | while (*utf8_data_in != '\0') { | 
|  | 1079 | *utf16_data_out++ = GetUtf16FromUtf8(&utf8_data_in); | 
|  | 1080 | } | 
|  | 1081 | } | 
|  | 1082 |  | 
|  | 1083 | // Retrieve the next UTF-16 character from a UTF-8 string. | 
|  | 1084 | // | 
|  | 1085 | // Advances "*pUtf8Ptr" to the start of the next character. | 
|  | 1086 | // | 
|  | 1087 | // WARNING: If a string is corrupted by dropping a '\0' in the middle | 
|  | 1088 | // of a 3-byte sequence, you can end up overrunning the buffer with | 
|  | 1089 | // reads (and possibly with the writes if the length was computed and | 
|  | 1090 | // cached before the damage). For performance reasons, this function | 
|  | 1091 | // assumes that the string being parsed is known to be valid (e.g., by | 
|  | 1092 | // already being verified). Most strings we process here are coming | 
|  | 1093 | // out of dex files or other internal translations, so the only real | 
|  | 1094 | // risk comes from the JNI NewStringUTF call. | 
|  | 1095 | static uint16_t GetUtf16FromUtf8(const char** utf8_data_in) { | 
|  | 1096 | uint8_t one = *(*utf8_data_in)++; | 
|  | 1097 | if ((one & 0x80) == 0) { | 
|  | 1098 | /* one-byte encoding */ | 
|  | 1099 | return one; | 
|  | 1100 | } | 
|  | 1101 | /* two- or three-byte encoding */ | 
|  | 1102 | uint8_t two = *(*utf8_data_in)++; | 
|  | 1103 | if ((one & 0x20) == 0) { | 
|  | 1104 | /* two-byte encoding */ | 
|  | 1105 | return ((one & 0x1f) << 6) | | 
|  | 1106 | (two & 0x3f); | 
|  | 1107 | } | 
|  | 1108 | /* three-byte encoding */ | 
|  | 1109 | uint8_t three = *(*utf8_data_in)++; | 
|  | 1110 | return ((one & 0x0f) << 12) | | 
|  | 1111 | ((two & 0x3f) << 6) | | 
|  | 1112 | (three & 0x3f); | 
|  | 1113 | } | 
|  | 1114 |  | 
|  | 1115 | // The java/lang/String.computeHashCode() algorithm | 
|  | 1116 | static uint32_t ComputeUtf16Hash(const uint16_t* string_data, size_t string_length) { | 
|  | 1117 | uint32_t hash = 0; | 
|  | 1118 | while (string_length--) { | 
|  | 1119 | hash = hash * 31 + *string_data++; | 
|  | 1120 | } | 
|  | 1121 | return hash; | 
|  | 1122 | } | 
|  | 1123 |  | 
| Brian Carlstrom | a7f4f48 | 2011-07-17 17:01:34 -0700 | [diff] [blame] | 1124 | private: | 
|  | 1125 | String(); | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 1126 | }; | 
|  | 1127 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1128 | class InterfaceEntry { | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 1129 | public: | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1130 | Class* GetClass() const { | 
|  | 1131 | return klass_; | 
|  | 1132 | }; | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 1133 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1134 | void SetClass(Class* klass) { | 
|  | 1135 | klass_ = klass; | 
|  | 1136 | }; | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 1137 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1138 | private: | 
|  | 1139 | // Points to the interface class. | 
| Carl Shapiro | 3ee755d | 2011-06-28 12:11:04 -0700 | [diff] [blame] | 1140 | Class* klass_; | 
|  | 1141 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1142 | public:  // TODO: private | 
|  | 1143 | // Index into array of vtable offsets.  This points into the | 
|  | 1144 | // ifviPool, which holds the vtables for all interfaces declared by | 
|  | 1145 | // this class. | 
|  | 1146 | uint32_t* method_index_array_; | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 1147 | }; | 
|  | 1148 |  | 
|  | 1149 | }  // namespace art | 
|  | 1150 |  | 
|  | 1151 | #endif  // ART_SRC_OBJECT_H_ |