blob: 935f6706e675bb92085f7048e01eea098751aaca [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Andy McFaddenb51ea112009-05-08 16:50:17 -070016
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080017/*
18 * Declaration of the fundamental Object type and refinements thereof, plus
19 * some functions for manipulating them.
20 */
21#ifndef _DALVIK_OO_OBJECT
22#define _DALVIK_OO_OBJECT
23
Andy McFadden861b3382010-03-05 15:58:31 -080024#include <Atomic.h>
25
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080026#include <stddef.h>
27
28/* fwd decl */
29struct DataObject;
Barry Hayes2c987472009-04-06 10:03:48 -070030struct InitiatingLoaderList;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080031struct ClassObject;
32struct StringObject;
33struct ArrayObject;
34struct Method;
35struct ExceptionEntry;
36struct LineNumEntry;
37struct StaticField;
38struct InstField;
39struct Field;
40struct RegisterMap;
41typedef struct DataObject DataObject;
Barry Hayes2c987472009-04-06 10:03:48 -070042typedef struct InitiatingLoaderList InitiatingLoaderList;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080043typedef struct ClassObject ClassObject;
44typedef struct StringObject StringObject;
45typedef struct ArrayObject ArrayObject;
46typedef struct Method Method;
47typedef struct ExceptionEntry ExceptionEntry;
48typedef struct LineNumEntry LineNumEntry;
49typedef struct StaticField StaticField;
50typedef struct InstField InstField;
51typedef struct Field Field;
52typedef struct RegisterMap RegisterMap;
53
54/*
55 * Native function pointer type.
56 *
57 * "args[0]" holds the "this" pointer for virtual methods.
58 *
59 * The "Bridge" form is a super-set of the "Native" form; in many places
60 * they are used interchangeably. Currently, all functions have all
61 * arguments passed in, but some functions only care about the first two.
62 * Passing extra arguments to a C function is (mostly) harmless.
63 */
64typedef void (*DalvikBridgeFunc)(const u4* args, JValue* pResult,
65 const Method* method, struct Thread* self);
66typedef void (*DalvikNativeFunc)(const u4* args, JValue* pResult);
67
68
69/* vm-internal access flags and related definitions */
70typedef enum AccessFlags {
71 ACC_MIRANDA = 0x8000, // method (internal to VM)
72 JAVA_FLAGS_MASK = 0xffff, // bits set from Java sources (low 16)
73} AccessFlags;
74
75/* Use the top 16 bits of the access flags field for
76 * other class flags. Code should use the *CLASS_FLAG*()
77 * macros to set/get these flags.
78 */
79typedef enum ClassFlags {
80 CLASS_ISFINALIZABLE = (1<<31), // class/ancestor overrides finalize()
81 CLASS_ISARRAY = (1<<30), // class is a "[*"
82 CLASS_ISOBJECTARRAY = (1<<29), // class is a "[L*" or "[[*"
83 CLASS_ISREFERENCE = (1<<28), // class is a soft/weak/phantom ref
84 // only ISREFERENCE is set --> soft
85 CLASS_ISWEAKREFERENCE = (1<<27), // class is a weak reference
86 CLASS_ISPHANTOMREFERENCE = (1<<26), // class is a phantom reference
87
88 CLASS_MULTIPLE_DEFS = (1<<25), // DEX verifier: defs in multiple DEXs
89
90 /* unlike the others, these can be present in the optimized DEX file */
91 CLASS_ISOPTIMIZED = (1<<17), // class may contain opt instrs
92 CLASS_ISPREVERIFIED = (1<<16), // class has been pre-verified
93} ClassFlags;
94
95/* bits we can reasonably expect to see set in a DEX access flags field */
96#define EXPECTED_FILE_FLAGS \
97 (ACC_CLASS_MASK | CLASS_ISPREVERIFIED | CLASS_ISOPTIMIZED)
98
Andy McFaddenb51ea112009-05-08 16:50:17 -070099/*
100 * Get/set class flags.
101 */
102#define SET_CLASS_FLAG(clazz, flag) \
103 do { (clazz)->accessFlags |= (flag); } while (0)
104
105#define CLEAR_CLASS_FLAG(clazz, flag) \
106 do { (clazz)->accessFlags &= ~(flag); } while (0)
107
108#define IS_CLASS_FLAG_SET(clazz, flag) \
109 (((clazz)->accessFlags & (flag)) != 0)
110
111#define GET_CLASS_FLAG_GROUP(clazz, flags) \
112 ((u4)((clazz)->accessFlags & (flags)))
113
114/*
115 * Use the top 16 bits of the access flags field for other method flags.
116 * Code should use the *METHOD_FLAG*() macros to set/get these flags.
117 */
118typedef enum MethodFlags {
119 METHOD_ISWRITABLE = (1<<31), // the method's code is writable
120} MethodFlags;
121
122/*
123 * Get/set method flags.
124 */
125#define SET_METHOD_FLAG(method, flag) \
126 do { (method)->accessFlags |= (flag); } while (0)
127
128#define CLEAR_METHOD_FLAG(method, flag) \
129 do { (method)->accessFlags &= ~(flag); } while (0)
130
131#define IS_METHOD_FLAG_SET(method, flag) \
132 (((method)->accessFlags & (flag)) != 0)
133
134#define GET_METHOD_FLAG_GROUP(method, flags) \
135 ((u4)((method)->accessFlags & (flags)))
136
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800137/* current state of the class, increasing as we progress */
138typedef enum ClassStatus {
139 CLASS_ERROR = -1,
140
141 CLASS_NOTREADY = 0,
Barry Hayesc49db852010-05-14 13:43:34 -0700142 CLASS_IDX = 1, /* loaded, DEX idx in super or ifaces */
143 CLASS_LOADED = 2, /* DEX idx values resolved */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800144 CLASS_RESOLVED = 3, /* part of linking */
145 CLASS_VERIFYING = 4, /* in the process of being verified */
146 CLASS_VERIFIED = 5, /* logically part of linking; done pre-init */
147 CLASS_INITIALIZING = 6, /* class init in progress */
148 CLASS_INITIALIZED = 7, /* ready to go */
149} ClassStatus;
150
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800151/*
152 * Primitive type identifiers. We use these values as indexes into an
153 * array of synthesized classes, so these start at zero and count up.
154 * The order is arbitrary (mimics table in doc for newarray opcode),
155 * but can't be changed without shuffling some reflection tables.
156 *
157 * PRIM_VOID can't be used as an array type, but we include it here for
158 * other uses (e.g. Void.TYPE).
159 */
160typedef enum PrimitiveType {
161 PRIM_NOT = -1, /* value is not a primitive type */
162 PRIM_BOOLEAN = 0,
163 PRIM_CHAR = 1,
164 PRIM_FLOAT = 2,
165 PRIM_DOUBLE = 3,
166 PRIM_BYTE = 4,
167 PRIM_SHORT = 5,
168 PRIM_INT = 6,
169 PRIM_LONG = 7,
170 PRIM_VOID = 8,
171
172 PRIM_MAX
173} PrimitiveType;
174#define PRIM_TYPE_TO_LETTER "ZCFDBSIJV" /* must match order in enum */
175
176/*
Barry Hayeseac47ed2009-06-22 11:45:20 -0700177 * Definitions for packing refOffsets in ClassObject.
178 */
179/*
180 * A magic value for refOffsets. Ignore the bits and walk the super
181 * chain when this is the value.
182 * [This is an unlikely "natural" value, since it would be 30 non-ref instance
183 * fields followed by 2 ref instance fields.]
184 */
185#define CLASS_WALK_SUPER ((unsigned int)(3))
186#define CLASS_SMALLEST_OFFSET (sizeof(struct Object))
187#define CLASS_BITS_PER_WORD (sizeof(unsigned long int) * 8)
188#define CLASS_OFFSET_ALIGNMENT 4
189#define CLASS_HIGH_BIT ((unsigned int)1 << (CLASS_BITS_PER_WORD - 1))
190/*
Barry Hayes6daaac12009-07-08 10:01:56 -0700191 * Given an offset, return the bit number which would encode that offset.
192 * Local use only.
193 */
194#define _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) \
195 (((unsigned int)(byteOffset) - CLASS_SMALLEST_OFFSET) / \
196 CLASS_OFFSET_ALIGNMENT)
197/*
198 * Is the given offset too large to be encoded?
199 */
200#define CLASS_CAN_ENCODE_OFFSET(byteOffset) \
201 (_CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) < CLASS_BITS_PER_WORD)
202/*
203 * Return a single bit, encoding the offset.
204 * Undefined if the offset is too large, as defined above.
Barry Hayeseac47ed2009-06-22 11:45:20 -0700205 */
206#define CLASS_BIT_FROM_OFFSET(byteOffset) \
Barry Hayes6daaac12009-07-08 10:01:56 -0700207 (CLASS_HIGH_BIT >> _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset))
Barry Hayeseac47ed2009-06-22 11:45:20 -0700208/*
209 * Return an offset, given a bit number as returned from CLZ.
210 */
211#define CLASS_OFFSET_FROM_CLZ(rshift) \
212 (((int)(rshift) * CLASS_OFFSET_ALIGNMENT) + CLASS_SMALLEST_OFFSET)
213
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800214
215/*
216 * Used for iftable in ClassObject.
217 */
218typedef struct InterfaceEntry {
219 /* pointer to interface class */
220 ClassObject* clazz;
221
222 /*
223 * Index into array of vtable offsets. This points into the ifviPool,
224 * which holds the vtables for all interfaces declared by this class.
225 */
226 int* methodIndexArray;
227} InterfaceEntry;
228
229
230
231/*
232 * There are three types of objects:
233 * Class objects - an instance of java.lang.Class
234 * Array objects - an object created with a "new array" instruction
235 * Data objects - an object that is neither of the above
236 *
237 * We also define String objects. At present they're equivalent to
238 * DataObject, but that may change. (Either way, they make some of the
239 * code more obvious.)
240 *
241 * All objects have an Object header followed by type-specific data.
242 */
243typedef struct Object {
244 /* ptr to class object */
245 ClassObject* clazz;
246
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800247 /*
248 * A word containing either a "thin" lock or a "fat" monitor. See
249 * the comments in Sync.c for a description of its layout.
250 */
251 u4 lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800252} Object;
253
254/*
255 * Properly initialize an Object.
256 * void DVM_OBJECT_INIT(Object *obj, ClassObject *clazz_)
257 */
Barry Hayes364f9d92010-06-11 16:12:47 -0700258#define DVM_OBJECT_INIT(obj, clazz_) \
259 do { \
260 dvmSetFieldObject((Object *)obj, offsetof(Object, clazz), \
261 (Object *)clazz_); \
262 DVM_LOCK_INIT(&(obj)->lock); \
263 } while (0)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800264
265/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800266 * Data objects have an Object header followed by their instance data.
267 */
268struct DataObject {
269 Object obj; /* MUST be first item */
270
271 /* variable #of u4 slots; u8 uses 2 slots */
272 u4 instanceData[1];
273};
274
275/*
276 * Strings are used frequently enough that we may want to give them their
277 * own unique type.
278 *
279 * Using a dedicated type object to access the instance data provides a
280 * performance advantage but makes the java/lang/String.java implementation
281 * fragile.
282 *
283 * Currently this is just equal to DataObject, and we pull the fields out
284 * like we do for any other object.
285 */
286struct StringObject {
287 Object obj; /* MUST be first item */
288
289 /* variable #of u4 slots; u8 uses 2 slots */
290 u4 instanceData[1];
291};
292
293
294/*
295 * Array objects have these additional fields.
296 *
297 * We don't currently store the size of each element. Usually it's implied
298 * by the instruction. If necessary, the width can be derived from
Elliott Hughesbeea0b72009-11-13 11:20:15 -0800299 * the first char of obj->clazz->descriptor.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800300 */
301struct ArrayObject {
302 Object obj; /* MUST be first item */
303
304 /* number of elements; immutable after init */
305 u4 length;
306
307 /*
308 * Array contents; actual size is (length * sizeof(type)). This is
309 * declared as u8 so that the compiler inserts any necessary padding
310 * (e.g. for EABI); the actual allocation may be smaller than 8 bytes.
311 */
312 u8 contents[1];
313};
314
315/*
Barry Hayes2c987472009-04-06 10:03:48 -0700316 * For classes created early and thus probably in the zygote, the
317 * InitiatingLoaderList is kept in gDvm. Later classes use the structure in
318 * Object Class. This helps keep zygote pages shared.
319 */
320struct InitiatingLoaderList {
321 /* a list of initiating loader Objects; grown and initialized on demand */
322 Object** initiatingLoaders;
323 /* count of loaders in the above list */
324 int initiatingLoaderCount;
325};
326
327/*
Barry Hayes03aa70a2010-03-01 15:49:41 -0800328 * Generic field header. We pass this around when we want a generic Field
329 * pointer (e.g. for reflection stuff). Testing the accessFlags for
330 * ACC_STATIC allows a proper up-cast.
331 */
332struct Field {
333 ClassObject* clazz; /* class in which the field is declared */
334 const char* name;
335 const char* signature; /* e.g. "I", "[C", "Landroid/os/Debug;" */
336 u4 accessFlags;
337#ifdef PROFILE_FIELD_ACCESS
338 u4 gets;
339 u4 puts;
340#endif
341};
342
343/*
344 * Static field.
345 */
346struct StaticField {
347 Field field; /* MUST be first item */
348 JValue value; /* initially set from DEX for primitives */
349};
350
351/*
352 * Instance field.
353 */
354struct InstField {
355 Field field; /* MUST be first item */
356
357 /*
358 * This field indicates the byte offset from the beginning of the
359 * (Object *) to the actual instance data; e.g., byteOffset==0 is
360 * the same as the object pointer (bug!), and byteOffset==4 is 4
361 * bytes farther.
362 */
363 int byteOffset;
364};
365
366/*
Andy McFaddenb51ea112009-05-08 16:50:17 -0700367 * This defines the amount of space we leave for field slots in the
368 * java.lang.Class definition. If we alter the class to have more than
369 * this many fields, the VM will abort at startup.
370 */
371#define CLASS_FIELD_SLOTS 4
372
373/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800374 * Class objects have many additional fields. This is used for both
375 * classes and interfaces, including synthesized classes (arrays and
376 * primitive types).
377 *
378 * Class objects are unusual in that they have some fields allocated with
379 * the system malloc (or LinearAlloc), rather than on the GC heap. This is
380 * handy during initialization, but does require special handling when
381 * discarding java.lang.Class objects.
382 *
383 * The separation of methods (direct vs. virtual) and fields (class vs.
384 * instance) used in Dalvik works out pretty well. The only time it's
385 * annoying is when enumerating or searching for things with reflection.
386 */
387struct ClassObject {
388 Object obj; /* MUST be first item */
389
390 /* leave space for instance data; we could access fields directly if we
391 freeze the definition of java/lang/Class */
392 u4 instanceData[CLASS_FIELD_SLOTS];
393
394 /* UTF-8 descriptor for the class; from constant pool, or on heap
395 if generated ("[C") */
396 const char* descriptor;
397 char* descriptorAlloc;
398
399 /* access flags; low 16 bits are defined by VM spec */
400 u4 accessFlags;
401
402 /* VM-unique class serial number, nonzero, set very early */
403 u4 serialNumber;
404
405 /* DexFile from which we came; needed to resolve constant pool entries */
406 /* (will be NULL for VM-generated, e.g. arrays and primitive classes) */
407 DvmDex* pDvmDex;
408
409 /* state of class initialization */
410 ClassStatus status;
411
412 /* if class verify fails, we must return same error on subsequent tries */
413 ClassObject* verifyErrorClass;
414
415 /* threadId, used to check for recursive <clinit> invocation */
416 u4 initThreadId;
417
418 /*
419 * Total object size; used when allocating storage on gc heap. (For
420 * interfaces and abstract classes this will be zero.)
421 */
422 size_t objectSize;
423
424 /* arrays only: class object for base element, for instanceof/checkcast
425 (for String[][][], this will be String) */
426 ClassObject* elementClass;
427
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800428 /* arrays only: number of dimensions, e.g. int[][] is 2 */
429 int arrayDim;
430
431 /* primitive type index, or PRIM_NOT (-1); set for generated prim classes */
432 PrimitiveType primitiveType;
433
434 /* superclass, or NULL if this is java.lang.Object */
435 ClassObject* super;
436
437 /* defining class loader, or NULL for the "bootstrap" system loader */
438 Object* classLoader;
439
440 /* initiating class loader list */
Barry Hayes2c987472009-04-06 10:03:48 -0700441 /* NOTE: for classes with low serialNumber, these are unused, and the
442 values are kept in a table in gDvm. */
443 InitiatingLoaderList initiatingLoaderList;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800444
445 /* array of interfaces this class implements directly */
446 int interfaceCount;
447 ClassObject** interfaces;
448
449 /* static, private, and <init> methods */
450 int directMethodCount;
451 Method* directMethods;
452
453 /* virtual methods defined in this class; invoked through vtable */
454 int virtualMethodCount;
455 Method* virtualMethods;
456
457 /*
458 * Virtual method table (vtable), for use by "invoke-virtual". The
459 * vtable from the superclass is copied in, and virtual methods from
460 * our class either replace those from the super or are appended.
461 */
462 int vtableCount;
463 Method** vtable;
464
465 /*
466 * Interface table (iftable), one entry per interface supported by
467 * this class. That means one entry for each interface we support
468 * directly, indirectly via superclass, or indirectly via
469 * superinterface. This will be null if neither we nor our superclass
470 * implement any interfaces.
471 *
472 * Why we need this: given "class Foo implements Face", declare
473 * "Face faceObj = new Foo()". Invoke faceObj.blah(), where "blah" is
474 * part of the Face interface. We can't easily use a single vtable.
475 *
476 * For every interface a concrete class implements, we create a list of
477 * virtualMethod indices for the methods in the interface.
478 */
479 int iftableCount;
480 InterfaceEntry* iftable;
481
482 /*
483 * The interface vtable indices for iftable get stored here. By placing
484 * them all in a single pool for each class that implements interfaces,
485 * we decrease the number of allocations.
486 */
487 int ifviPoolCount;
488 int* ifviPool;
489
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800490 /* instance fields
491 *
492 * These describe the layout of the contents of a DataObject-compatible
493 * Object. Note that only the fields directly defined by this class
494 * are listed in ifields; fields defined by a superclass are listed
495 * in the superclass's ClassObject.ifields.
496 *
497 * All instance fields that refer to objects are guaranteed to be
498 * at the beginning of the field list. ifieldRefCount specifies
499 * the number of reference fields.
500 */
501 int ifieldCount;
502 int ifieldRefCount; // number of fields that are object refs
503 InstField* ifields;
504
Barry Hayeseac47ed2009-06-22 11:45:20 -0700505 /* bitmap of offsets of ifields */
506 u4 refOffsets;
507
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800508 /* source file name, if known */
509 const char* sourceFile;
Barry Hayes03aa70a2010-03-01 15:49:41 -0800510
511 /* static fields */
512 int sfieldCount;
513 StaticField sfields[]; /* MUST be last item */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800514};
515
516/*
517 * A method. We create one of these for every method in every class
518 * we load, so try to keep the size to a minimum.
519 *
520 * Much of this comes from and could be accessed in the data held in shared
521 * memory. We hold it all together here for speed. Everything but the
522 * pointers could be held in a shared table generated by the optimizer;
523 * if we're willing to convert them to offsets and take the performance
524 * hit (e.g. "meth->insns" becomes "baseAddr + meth->insnsOffset") we
525 * could move everything but "nativeFunc".
526 */
527struct Method {
528 /* the class we are a part of */
529 ClassObject* clazz;
530
531 /* access flags; low 16 bits are defined by spec (could be u2?) */
532 u4 accessFlags;
533
534 /*
535 * For concrete virtual methods, this is the offset of the method
536 * in "vtable".
537 *
538 * For abstract methods in an interface class, this is the offset
539 * of the method in "iftable[n]->methodIndexArray".
540 */
541 u2 methodIndex;
542
543 /*
544 * Method bounds; not needed for an abstract method.
545 *
546 * For a native method, we compute the size of the argument list, and
547 * set "insSize" and "registerSize" equal to it.
548 */
549 u2 registersSize; /* ins + locals */
550 u2 outsSize;
551 u2 insSize;
552
553 /* method name, e.g. "<init>" or "eatLunch" */
554 const char* name;
555
556 /*
557 * Method prototype descriptor string (return and argument types).
558 *
559 * TODO: This currently must specify the DexFile as well as the proto_ids
560 * index, because generated Proxy classes don't have a DexFile. We can
561 * remove the DexFile* and reduce the size of this struct if we generate
562 * a DEX for proxies.
563 */
564 DexProto prototype;
565
566 /* short-form method descriptor string */
567 const char* shorty;
568
569 /*
570 * The remaining items are not used for abstract or native methods.
571 * (JNI is currently hijacking "insns" as a function pointer, set
572 * after the first call. For internal-native this stays null.)
573 */
574
575 /* the actual code */
576 const u2* insns; /* instructions, in memory-mapped .dex */
577
578 /* cached JNI argument and return-type hints */
579 int jniArgInfo;
580
581 /*
582 * Native method ptr; could be actual function or a JNI bridge. We
583 * don't currently discriminate between DalvikBridgeFunc and
584 * DalvikNativeFunc; the former takes an argument superset (i.e. two
585 * extra args) which will be ignored. If necessary we can use
586 * insns==NULL to detect JNI bridge vs. internal native.
587 */
588 DalvikBridgeFunc nativeFunc;
589
590 /*
591 * Register map data, if available. This will point into the DEX file
592 * if the data was computed during pre-verification, or into the
593 * linear alloc area if not.
594 */
595 const RegisterMap* registerMap;
596
597#ifdef WITH_PROFILER
598 bool inProfile;
599#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800600};
601
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800602
603/*
604 * Find a method within a class. The superclass is not searched.
605 */
606Method* dvmFindDirectMethodByDescriptor(const ClassObject* clazz,
607 const char* methodName, const char* signature);
608Method* dvmFindVirtualMethodByDescriptor(const ClassObject* clazz,
609 const char* methodName, const char* signature);
610Method* dvmFindVirtualMethodByName(const ClassObject* clazz,
611 const char* methodName);
612Method* dvmFindDirectMethod(const ClassObject* clazz, const char* methodName,
613 const DexProto* proto);
614Method* dvmFindVirtualMethod(const ClassObject* clazz, const char* methodName,
615 const DexProto* proto);
616
617
618/*
619 * Find a method within a class hierarchy.
620 */
621Method* dvmFindDirectMethodHierByDescriptor(const ClassObject* clazz,
622 const char* methodName, const char* descriptor);
623Method* dvmFindVirtualMethodHierByDescriptor(const ClassObject* clazz,
624 const char* methodName, const char* signature);
625Method* dvmFindDirectMethodHier(const ClassObject* clazz,
626 const char* methodName, const DexProto* proto);
627Method* dvmFindVirtualMethodHier(const ClassObject* clazz,
628 const char* methodName, const DexProto* proto);
Andy McFadden1d9206d2009-07-15 14:34:49 -0700629Method* dvmFindMethodHier(const ClassObject* clazz, const char* methodName,
630 const DexProto* proto);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800631
632/*
633 * Find the implementation of "meth" in "clazz".
634 *
635 * Returns NULL and throws an exception if not found.
636 */
637const Method* dvmGetVirtualizedMethod(const ClassObject* clazz,
638 const Method* meth);
639
640/*
641 * Get the source file associated with a method.
642 */
643const char* dvmGetMethodSourceFile(const Method* meth);
644
645/*
646 * Find a field within a class. The superclass is not searched.
647 */
648InstField* dvmFindInstanceField(const ClassObject* clazz,
649 const char* fieldName, const char* signature);
650StaticField* dvmFindStaticField(const ClassObject* clazz,
651 const char* fieldName, const char* signature);
652
653/*
654 * Find a field in a class/interface hierarchy.
655 */
656InstField* dvmFindInstanceFieldHier(const ClassObject* clazz,
657 const char* fieldName, const char* signature);
658StaticField* dvmFindStaticFieldHier(const ClassObject* clazz,
659 const char* fieldName, const char* signature);
Andy McFadden1d9206d2009-07-15 14:34:49 -0700660Field* dvmFindFieldHier(const ClassObject* clazz, const char* fieldName,
661 const char* signature);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800662
663/*
664 * Find a field and return the byte offset from the object pointer. Only
665 * searches the specified class, not the superclass.
666 *
667 * Returns -1 on failure.
668 */
669INLINE int dvmFindFieldOffset(const ClassObject* clazz,
670 const char* fieldName, const char* signature)
671{
672 InstField* pField = dvmFindInstanceField(clazz, fieldName, signature);
673 if (pField == NULL)
674 return -1;
675 else
676 return pField->byteOffset;
677}
678
679/*
Barry Hayes364f9d92010-06-11 16:12:47 -0700680 * Note writes to the heap.
681 */
682INLINE void dvmWriteBarrierField(Object *obj, void *addr) {
683}
684INLINE void dvmWriteBarrierObject(Object *obj) {
685}
686INLINE void dvmWriteBarrierArray(const ArrayObject* obj,
687 size_t start, size_t end) {
688}
689/*
690 * Store a single value in the array, and note in the write barrier.
691 */
692INLINE void dvmSetObjectArrayElement(const ArrayObject* obj, int index,
693 Object* val) {
694 ((Object **)(obj)->contents)[index] = val;
695 dvmWriteBarrierArray(obj, index, index+1);
696}
697
698
699/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800700 * Field access functions. Pass in the word offset from Field->byteOffset.
701 *
702 * We guarantee that long/double field data is 64-bit aligned, so it's safe
703 * to access them with ldrd/strd on ARM.
704 *
705 * The VM treats all fields as 32 or 64 bits, so the field set functions
706 * write 32 bits even if the underlying type is smaller.
707 */
708#define BYTE_OFFSET(_ptr, _offset) ((void*) (((u1*)(_ptr)) + (_offset)))
709
710INLINE JValue* dvmFieldPtr(const Object* obj, int offset) {
711 return ((JValue*)BYTE_OFFSET(obj, offset));
712}
713
714INLINE bool dvmGetFieldBoolean(const Object* obj, int offset) {
715 return ((JValue*)BYTE_OFFSET(obj, offset))->z;
716}
717INLINE s1 dvmGetFieldByte(const Object* obj, int offset) {
718 return ((JValue*)BYTE_OFFSET(obj, offset))->b;
719}
720INLINE s2 dvmGetFieldShort(const Object* obj, int offset) {
721 return ((JValue*)BYTE_OFFSET(obj, offset))->s;
722}
723INLINE u2 dvmGetFieldChar(const Object* obj, int offset) {
724 return ((JValue*)BYTE_OFFSET(obj, offset))->c;
725}
726INLINE s4 dvmGetFieldInt(const Object* obj, int offset) {
727 return ((JValue*)BYTE_OFFSET(obj, offset))->i;
728}
729INLINE s8 dvmGetFieldLong(const Object* obj, int offset) {
730 return ((JValue*)BYTE_OFFSET(obj, offset))->j;
731}
732INLINE float dvmGetFieldFloat(const Object* obj, int offset) {
733 return ((JValue*)BYTE_OFFSET(obj, offset))->f;
734}
735INLINE double dvmGetFieldDouble(const Object* obj, int offset) {
736 return ((JValue*)BYTE_OFFSET(obj, offset))->d;
737}
738INLINE Object* dvmGetFieldObject(const Object* obj, int offset) {
739 return ((JValue*)BYTE_OFFSET(obj, offset))->l;
740}
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700741INLINE s4 dvmGetFieldIntVolatile(const Object* obj, int offset) {
742 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
743 return android_atomic_acquire_load(ptr);
744}
745INLINE Object* dvmGetFieldObjectVolatile(const Object* obj, int offset) {
746 void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
747 return (Object*) android_atomic_acquire_load((int32_t*)ptr);
748}
Andy McFadden861b3382010-03-05 15:58:31 -0800749INLINE s8 dvmGetFieldLongVolatile(const Object* obj, int offset) {
750 const s8* addr = BYTE_OFFSET(obj, offset);
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700751 s8 val = dvmQuasiAtomicRead64(addr);
752 ANDROID_MEMBAR_FULL();
753 return val;
Andy McFadden861b3382010-03-05 15:58:31 -0800754}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800755
756INLINE void dvmSetFieldBoolean(Object* obj, int offset, bool val) {
757 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
758}
759INLINE void dvmSetFieldByte(Object* obj, int offset, s1 val) {
760 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
761}
762INLINE void dvmSetFieldShort(Object* obj, int offset, s2 val) {
763 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
764}
765INLINE void dvmSetFieldChar(Object* obj, int offset, u2 val) {
766 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
767}
768INLINE void dvmSetFieldInt(Object* obj, int offset, s4 val) {
769 ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
770}
771INLINE void dvmSetFieldLong(Object* obj, int offset, s8 val) {
772 ((JValue*)BYTE_OFFSET(obj, offset))->j = val;
773}
774INLINE void dvmSetFieldFloat(Object* obj, int offset, float val) {
775 ((JValue*)BYTE_OFFSET(obj, offset))->f = val;
776}
777INLINE void dvmSetFieldDouble(Object* obj, int offset, double val) {
778 ((JValue*)BYTE_OFFSET(obj, offset))->d = val;
779}
780INLINE void dvmSetFieldObject(Object* obj, int offset, Object* val) {
Barry Hayes364f9d92010-06-11 16:12:47 -0700781 JValue* lhs = BYTE_OFFSET(obj, offset);
782 lhs->l = val;
783 dvmWriteBarrierField(obj, &lhs->l);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800784}
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700785INLINE void dvmSetFieldIntVolatile(Object* obj, int offset, s4 val) {
786 s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i;
787 android_atomic_release_store(val, ptr);
788}
789INLINE void dvmSetFieldObjectVolatile(Object* obj, int offset, Object* val) {
790 void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l;
791 android_atomic_release_store((int32_t)val, (int32_t*)ptr);
Barry Hayes364f9d92010-06-11 16:12:47 -0700792 dvmWriteBarrierField(obj, ptr);
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700793}
Andy McFadden861b3382010-03-05 15:58:31 -0800794INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
795 s8* addr = BYTE_OFFSET(obj, offset);
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700796 ANDROID_MEMBAR_FULL();
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700797 dvmQuasiAtomicSwap64(val, addr);
Andy McFadden861b3382010-03-05 15:58:31 -0800798}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800799
800/*
801 * Static field access functions.
802 */
803INLINE JValue* dvmStaticFieldPtr(const StaticField* sfield) {
804 return (JValue*)&sfield->value;
805}
806
807INLINE bool dvmGetStaticFieldBoolean(const StaticField* sfield) {
808 return sfield->value.z;
809}
810INLINE s1 dvmGetStaticFieldByte(const StaticField* sfield) {
811 return sfield->value.b;
812}
813INLINE s2 dvmGetStaticFieldShort(const StaticField* sfield) {
814 return sfield->value.s;
815}
816INLINE u2 dvmGetStaticFieldChar(const StaticField* sfield) {
817 return sfield->value.c;
818}
819INLINE s4 dvmGetStaticFieldInt(const StaticField* sfield) {
820 return sfield->value.i;
821}
822INLINE s8 dvmGetStaticFieldLong(const StaticField* sfield) {
823 return sfield->value.j;
824}
825INLINE float dvmGetStaticFieldFloat(const StaticField* sfield) {
826 return sfield->value.f;
827}
828INLINE double dvmGetStaticFieldDouble(const StaticField* sfield) {
829 return sfield->value.d;
830}
831INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
832 return sfield->value.l;
833}
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700834INLINE s4 dvmGetStaticFieldIntVolatile(const StaticField* sfield) {
835 const s4* ptr = &(sfield->value.i);
836 return android_atomic_acquire_load((s4*)ptr);
837}
838INLINE Object* dvmGetStaticFieldObjectVolatile(const StaticField* sfield) {
839 void* const* ptr = &(sfield->value.l);
840 return (Object*) android_atomic_acquire_load((int32_t*)ptr);
841}
Andy McFadden861b3382010-03-05 15:58:31 -0800842INLINE s8 dvmGetStaticFieldLongVolatile(const StaticField* sfield) {
843 const s8* addr = &sfield->value.j;
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700844 s8 val = dvmQuasiAtomicRead64(addr);
845 ANDROID_MEMBAR_FULL();
846 return val;
Andy McFadden861b3382010-03-05 15:58:31 -0800847}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800848
849INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
850 sfield->value.i = val;
851}
852INLINE void dvmSetStaticFieldByte(StaticField* sfield, s1 val) {
853 sfield->value.i = val;
854}
855INLINE void dvmSetStaticFieldShort(StaticField* sfield, s2 val) {
856 sfield->value.i = val;
857}
858INLINE void dvmSetStaticFieldChar(StaticField* sfield, u2 val) {
859 sfield->value.i = val;
860}
861INLINE void dvmSetStaticFieldInt(StaticField* sfield, s4 val) {
862 sfield->value.i = val;
863}
864INLINE void dvmSetStaticFieldLong(StaticField* sfield, s8 val) {
865 sfield->value.j = val;
866}
867INLINE void dvmSetStaticFieldFloat(StaticField* sfield, float val) {
868 sfield->value.f = val;
869}
870INLINE void dvmSetStaticFieldDouble(StaticField* sfield, double val) {
871 sfield->value.d = val;
872}
873INLINE void dvmSetStaticFieldObject(StaticField* sfield, Object* val) {
874 sfield->value.l = val;
Barry Hayes364f9d92010-06-11 16:12:47 -0700875 dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800876}
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700877INLINE void dvmSetStaticFieldIntVolatile(StaticField* sfield, s4 val) {
878 s4* ptr = &(sfield->value.i);
879 android_atomic_release_store(val, ptr);
880}
881INLINE void dvmSetStaticFieldObjectVolatile(StaticField* sfield, Object* val) {
882 void** ptr = &(sfield->value.l);
883 android_atomic_release_store((int32_t)val, (int32_t*)ptr);
Barry Hayes364f9d92010-06-11 16:12:47 -0700884 dvmWriteBarrierField((Object *)sfield->field.clazz, &sfield->value.l);
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700885}
Andy McFadden861b3382010-03-05 15:58:31 -0800886INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
887 s8* addr = &sfield->value.j;
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700888 ANDROID_MEMBAR_FULL();
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700889 dvmQuasiAtomicSwap64(val, addr);
Andy McFadden861b3382010-03-05 15:58:31 -0800890}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800891
892/*
893 * Helpers.
894 */
895INLINE bool dvmIsPublicMethod(const Method* method) {
896 return (method->accessFlags & ACC_PUBLIC) != 0;
897}
898INLINE bool dvmIsPrivateMethod(const Method* method) {
899 return (method->accessFlags & ACC_PRIVATE) != 0;
900}
901INLINE bool dvmIsStaticMethod(const Method* method) {
902 return (method->accessFlags & ACC_STATIC) != 0;
903}
904INLINE bool dvmIsSynchronizedMethod(const Method* method) {
905 return (method->accessFlags & ACC_SYNCHRONIZED) != 0;
906}
907INLINE bool dvmIsDeclaredSynchronizedMethod(const Method* method) {
908 return (method->accessFlags & ACC_DECLARED_SYNCHRONIZED) != 0;
909}
910INLINE bool dvmIsFinalMethod(const Method* method) {
911 return (method->accessFlags & ACC_FINAL) != 0;
912}
913INLINE bool dvmIsNativeMethod(const Method* method) {
914 return (method->accessFlags & ACC_NATIVE) != 0;
915}
916INLINE bool dvmIsAbstractMethod(const Method* method) {
917 return (method->accessFlags & ACC_ABSTRACT) != 0;
918}
919INLINE bool dvmIsMirandaMethod(const Method* method) {
920 return (method->accessFlags & ACC_MIRANDA) != 0;
921}
922INLINE bool dvmIsConstructorMethod(const Method* method) {
923 return *method->name == '<';
924}
925/* Dalvik puts private, static, and constructors into non-virtual table */
926INLINE bool dvmIsDirectMethod(const Method* method) {
927 return dvmIsPrivateMethod(method) ||
928 dvmIsStaticMethod(method) ||
929 dvmIsConstructorMethod(method);
930}
931/* Get whether the given method has associated bytecode. This is the
932 * case for methods which are neither native nor abstract. */
933INLINE bool dvmIsBytecodeMethod(const Method* method) {
934 return (method->accessFlags & (ACC_NATIVE | ACC_ABSTRACT)) == 0;
935}
936
937INLINE bool dvmIsProtectedField(const Field* field) {
938 return (field->accessFlags & ACC_PROTECTED) != 0;
939}
940INLINE bool dvmIsStaticField(const Field* field) {
941 return (field->accessFlags & ACC_STATIC) != 0;
942}
943INLINE bool dvmIsFinalField(const Field* field) {
944 return (field->accessFlags & ACC_FINAL) != 0;
945}
Andy McFadden861b3382010-03-05 15:58:31 -0800946INLINE bool dvmIsVolatileField(const Field* field) {
947 return (field->accessFlags & ACC_VOLATILE) != 0;
948}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800949
950INLINE bool dvmIsInterfaceClass(const ClassObject* clazz) {
951 return (clazz->accessFlags & ACC_INTERFACE) != 0;
952}
953INLINE bool dvmIsPublicClass(const ClassObject* clazz) {
954 return (clazz->accessFlags & ACC_PUBLIC) != 0;
955}
956INLINE bool dvmIsFinalClass(const ClassObject* clazz) {
957 return (clazz->accessFlags & ACC_FINAL) != 0;
958}
959INLINE bool dvmIsAbstractClass(const ClassObject* clazz) {
960 return (clazz->accessFlags & ACC_ABSTRACT) != 0;
961}
Carl Shapirode750892010-06-08 16:37:12 -0700962INLINE bool dvmIsAnnotationClass(const ClassObject* clazz) {
963 return (clazz->accessFlags & ACC_ANNOTATION) != 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800964}
965INLINE bool dvmIsPrimitiveClass(const ClassObject* clazz) {
966 return clazz->primitiveType != PRIM_NOT;
967}
968
969/* linked, here meaning prepared and resolved */
970INLINE bool dvmIsClassLinked(const ClassObject* clazz) {
971 return clazz->status >= CLASS_RESOLVED;
972}
973/* has class been verified? */
974INLINE bool dvmIsClassVerified(const ClassObject* clazz) {
975 return clazz->status >= CLASS_VERIFIED;
976}
977
978/*
979 * Get the associated code struct for a method. This returns NULL
980 * for non-bytecode methods.
981 */
982INLINE const DexCode* dvmGetMethodCode(const Method* meth) {
983 if (dvmIsBytecodeMethod(meth)) {
984 /*
985 * The insns field for a bytecode method actually points at
986 * &(DexCode.insns), so we can subtract back to get at the
987 * DexCode in front.
988 */
989 return (const DexCode*)
990 (((const u1*) meth->insns) - offsetof(DexCode, insns));
991 } else {
992 return NULL;
993 }
994}
995
996/*
997 * Get the size of the insns associated with a method. This returns 0
998 * for non-bytecode methods.
999 */
1000INLINE u4 dvmGetMethodInsnsSize(const Method* meth) {
1001 const DexCode* pCode = dvmGetMethodCode(meth);
1002 return (pCode == NULL) ? 0 : pCode->insnsSize;
1003}
1004
1005/* debugging */
1006void dvmDumpObject(const Object* obj);
1007
1008#endif /*_DALVIK_OO_OBJECT*/