summaryrefslogtreecommitdiffstats
path: root/vm
diff options
context:
space:
mode:
authorDan Bornstein <danfuzz@android.com>2011-03-11 16:49:32 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-03-11 16:49:32 -0800
commita5e5f6eb3ecb7950812a4718b8e795299ce79783 (patch)
tree1f2453e1cbf675f2242ee04acfe2c748585141bf /vm
parent190b97277ab6f1163ac3ccde34bd521940f73630 (diff)
parenta9c49df6714b3a37b7a7d0522932e622be2b35ac (diff)
downloadandroid_dalvik-a5e5f6eb3ecb7950812a4718b8e795299ce79783.tar.gz
android_dalvik-a5e5f6eb3ecb7950812a4718b8e795299ce79783.tar.bz2
android_dalvik-a5e5f6eb3ecb7950812a4718b8e795299ce79783.zip
Merge "Clean up how primitive types are handled." into dalvik-dev
Diffstat (limited to 'vm')
-rw-r--r--vm/CheckJni.c56
-rw-r--r--vm/Globals.h16
-rw-r--r--vm/alloc/Visit.c30
-rw-r--r--vm/analysis/CodeVerify.c37
-rw-r--r--vm/native/java_lang_reflect_Array.c5
-rw-r--r--vm/native/java_lang_reflect_Field.c63
-rw-r--r--vm/oo/Array.c115
-rw-r--r--vm/oo/Array.h6
-rw-r--r--vm/oo/Class.c105
-rw-r--r--vm/oo/Class.h7
-rw-r--r--vm/oo/Object.h25
-rw-r--r--vm/reflect/Reflect.c176
12 files changed, 310 insertions, 331 deletions
diff --git a/vm/CheckJni.c b/vm/CheckJni.c
index 922646eab..5b9ea1211 100644
--- a/vm/CheckJni.c
+++ b/vm/CheckJni.c
@@ -403,6 +403,25 @@ static void checkThread(JNIEnv* env, int flags, const char* func)
}
/*
+ * Get a human-oriented name for a given primitive type.
+ */
+static const char* primitiveTypeToName(PrimitiveType primType) {
+ switch (primType) {
+ case PRIM_VOID: return "void";
+ case PRIM_BOOLEAN: return "boolean";
+ case PRIM_BYTE: return "byte";
+ case PRIM_SHORT: return "short";
+ case PRIM_CHAR: return "char";
+ case PRIM_INT: return "int";
+ case PRIM_LONG: return "long";
+ case PRIM_FLOAT: return "float";
+ case PRIM_DOUBLE: return "double";
+ case PRIM_NOT: return "Object/Array";
+ default: return "???";
+ }
+}
+
+/*
* Verify that the field is of the appropriate type. If the field has an
* object type, "obj" is the object we're trying to assign into it.
*
@@ -411,11 +430,6 @@ static void checkThread(JNIEnv* env, int flags, const char* func)
static void checkFieldType(JNIEnv* env, jobject jobj, jfieldID fieldID,
PrimitiveType prim, bool isStatic, const char* func)
{
- static const char* primNameList[] = {
- "Object/Array", "boolean", "char", "float", "double",
- "byte", "short", "int", "long", "void"
- };
- const char** primNames = &primNameList[1]; // shift up for PRIM_NOT
Field* field = (Field*) fieldID;
bool printWarn = false;
@@ -440,9 +454,9 @@ static void checkFieldType(JNIEnv* env, jobject jobj, jfieldID fieldID,
printWarn = true;
}
}
- } else if (field->signature[0] != PRIM_TYPE_TO_LETTER[prim]) {
+ } else if (dexGetPrimitiveTypeFromDescriptorChar(field->signature[0]) != prim) {
LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)",
- field->name, field->signature, primNames[prim]);
+ field->name, field->signature, primitiveTypeToName(prim));
printWarn = true;
} else if (isStatic && !dvmIsStaticField(field)) {
if (isStatic)
@@ -1087,19 +1101,21 @@ static size_t getGuardedCopyOriginalLen(const void* dataBuf)
*/
static int dvmPrimitiveTypeWidth(PrimitiveType primType)
{
- static const int lengths[PRIM_MAX] = {
- 1, // boolean
- 2, // char
- 4, // float
- 8, // double
- 1, // byte
- 2, // short
- 4, // int
- 8, // long
- -1, // void
- };
- assert(primType >= 0 && primType < PRIM_MAX);
- return lengths[primType];
+ switch (primType) {
+ case PRIM_BOOLEAN: return 1;
+ case PRIM_BYTE: return 1;
+ case PRIM_SHORT: return 2;
+ case PRIM_CHAR: return 2;
+ case PRIM_INT: return 4;
+ case PRIM_LONG: return 8;
+ case PRIM_FLOAT: return 4;
+ case PRIM_DOUBLE: return 8;
+ case PRIM_VOID:
+ default: {
+ assert(false);
+ return -1;
+ }
+ }
}
/*
diff --git a/vm/Globals.h b/vm/Globals.h
index 28cd17317..813373cc5 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -306,6 +306,17 @@ struct DvmGlobals {
ClassObject* exVerifyError;
ClassObject* exVirtualMachineError;
+ /* synthetic classes representing primitive types */
+ ClassObject* typeVoid;
+ ClassObject* typeBoolean;
+ ClassObject* typeByte;
+ ClassObject* typeShort;
+ ClassObject* typeChar;
+ ClassObject* typeInt;
+ ClassObject* typeLong;
+ ClassObject* typeFloat;
+ ClassObject* typeDouble;
+
/* synthetic classes for arrays of primitives */
ClassObject* classArrayBoolean;
ClassObject* classArrayChar;
@@ -399,11 +410,6 @@ struct DvmGlobals {
int offJavaNioBuffer_effectiveDirectAddress;
/*
- * VM-synthesized primitive classes, for arrays and reflection
- */
- ClassObject* volatile primitiveClass[PRIM_MAX];
-
- /*
* Thread list. This always has at least one element in it (main),
* and main is always the first entry.
*
diff --git a/vm/alloc/Visit.c b/vm/alloc/Visit.c
index 7e44198f7..1961fc9a7 100644
--- a/vm/alloc/Visit.c
+++ b/vm/alloc/Visit.c
@@ -51,21 +51,6 @@ static void visitHashTable(RootVisitor *visitor, HashTable *table,
}
/*
- * Applies a verification function to all elements in the array.
- */
-static void visitArray(RootVisitor *visitor, Object **array, size_t length,
- RootType type, void *arg)
-{
- size_t i;
-
- assert(visitor != NULL);
- assert(array != NULL);
- for (i = 0; i < length; ++i) {
- (*visitor)(&array[i], 0, type, arg);
- }
-}
-
-/*
* Visits all entries in the reference table.
*/
static void visitReferenceTable(RootVisitor *visitor, ReferenceTable *table,
@@ -232,6 +217,19 @@ static void visitThreads(RootVisitor *visitor, void *arg)
dvmUnlockThreadList();
}
+static void visitPrimitiveTypes(RootVisitor *visitor, void *arg)
+{
+ (*visitor)(&gDvm.typeVoid, 0, ROOT_STICKY_CLASS, arg);
+ (*visitor)(&gDvm.typeBoolean, 0, ROOT_STICKY_CLASS, arg);
+ (*visitor)(&gDvm.typeByte, 0, ROOT_STICKY_CLASS, arg);
+ (*visitor)(&gDvm.typeShort, 0, ROOT_STICKY_CLASS, arg);
+ (*visitor)(&gDvm.typeChar, 0, ROOT_STICKY_CLASS, arg);
+ (*visitor)(&gDvm.typeInt, 0, ROOT_STICKY_CLASS, arg);
+ (*visitor)(&gDvm.typeLong, 0, ROOT_STICKY_CLASS, arg);
+ (*visitor)(&gDvm.typeFloat, 0, ROOT_STICKY_CLASS, arg);
+ (*visitor)(&gDvm.typeDouble, 0, ROOT_STICKY_CLASS, arg);
+}
+
/*
* Visits roots. TODO: visit cached global references.
*/
@@ -239,7 +237,7 @@ void dvmVisitRoots(RootVisitor *visitor, void *arg)
{
assert(visitor != NULL);
visitHashTable(visitor, gDvm.loadedClasses, ROOT_STICKY_CLASS, arg);
- visitArray(visitor, (Object **)gDvm.primitiveClass, NELEM(gDvm.primitiveClass), ROOT_STICKY_CLASS, arg);
+ visitPrimitiveTypes(visitor, arg);
if (gDvm.dbgRegistry != NULL) {
visitHashTable(visitor, gDvm.dbgRegistry, ROOT_DEBUGGER, arg);
}
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 37a895180..2d00ebd85 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -320,30 +320,21 @@ static bool checkFieldArrayStore1nr(RegType instrType, RegType targetType)
*/
static RegType primitiveTypeToRegType(PrimitiveType primType)
{
- static const struct {
- RegType regType; /* type equivalent */
- PrimitiveType primType; /* verification */
- } convTab[] = {
- /* must match order of enum in Object.h */
- { kRegTypeBoolean, PRIM_BOOLEAN },
- { kRegTypeChar, PRIM_CHAR },
- { kRegTypeFloat, PRIM_FLOAT },
- { kRegTypeDoubleLo, PRIM_DOUBLE },
- { kRegTypeByte, PRIM_BYTE },
- { kRegTypeShort, PRIM_SHORT },
- { kRegTypeInteger, PRIM_INT },
- { kRegTypeLongLo, PRIM_LONG },
- // PRIM_VOID
- };
-
- if (primType < 0 || primType > (int) (sizeof(convTab) / sizeof(convTab[0])))
- {
- assert(false);
- return kRegTypeUnknown;
+ switch (primType) {
+ case PRIM_BOOLEAN: return kRegTypeBoolean;
+ case PRIM_BYTE: return kRegTypeByte;
+ case PRIM_SHORT: return kRegTypeShort;
+ case PRIM_CHAR: return kRegTypeChar;
+ case PRIM_INT: return kRegTypeInteger;
+ case PRIM_LONG: return kRegTypeLongLo;
+ case PRIM_FLOAT: return kRegTypeFloat;
+ case PRIM_DOUBLE: return kRegTypeDoubleLo;
+ case PRIM_VOID:
+ default: {
+ assert(false);
+ return kRegTypeUnknown;
+ }
}
-
- assert(convTab[primType].primType == primType);
- return convTab[primType].regType;
}
/*
diff --git a/vm/native/java_lang_reflect_Array.c b/vm/native/java_lang_reflect_Array.c
index bc7e5eca2..fe6647cdd 100644
--- a/vm/native/java_lang_reflect_Array.c
+++ b/vm/native/java_lang_reflect_Array.c
@@ -64,7 +64,6 @@ static void Dalvik_java_lang_reflect_Array_createObjectArray(const u4* args,
static void Dalvik_java_lang_reflect_Array_createMultiArray(const u4* args,
JValue* pResult)
{
- static const char kPrimLetter[] = PRIM_TYPE_TO_LETTER;
ClassObject* elementClass = (ClassObject*) args[0];
ArrayObject* dimArray = (ArrayObject*) args[1];
ClassObject* arrayClass;
@@ -106,8 +105,8 @@ static void Dalvik_java_lang_reflect_Array_createMultiArray(const u4* args,
LOGVV("#### element name = '%s'\n", elementClass->descriptor);
if (dvmIsPrimitiveClass(elementClass)) {
- assert(elementClass->primitiveType >= 0);
- acDescriptor[numDim] = kPrimLetter[elementClass->primitiveType];
+ assert(elementClass->primitiveType != PRIM_NOT);
+ acDescriptor[numDim] = dexGetPrimitiveTypeDescriptorChar(elementClass->primitiveType);
acDescriptor[numDim+1] = '\0';
} else {
strcpy(acDescriptor+numDim, elementClass->descriptor);
diff --git a/vm/native/java_lang_reflect_Field.c b/vm/native/java_lang_reflect_Field.c
index 2713d8c0b..eb5d4e26e 100644
--- a/vm/native/java_lang_reflect_Field.c
+++ b/vm/native/java_lang_reflect_Field.c
@@ -515,26 +515,9 @@ static void Dalvik_java_lang_reflect_Field_setField(const u4* args,
}
/*
- * Convert a reflection primitive type ordinal (inherited from the previous
- * VM's reflection classes) to our value.
- */
-static PrimitiveType convPrimType(int typeNum)
-{
- static const PrimitiveType conv[PRIM_MAX] = {
- PRIM_NOT, PRIM_BOOLEAN, PRIM_BYTE, PRIM_CHAR, PRIM_SHORT,
- PRIM_INT, PRIM_FLOAT, PRIM_LONG, PRIM_DOUBLE
- };
- if (typeNum <= 0 || typeNum > 8)
- return PRIM_NOT;
- return conv[typeNum];
-}
-
-/*
* Primitive field getters, e.g.:
* private double getIField(Object o, Class declaringClass,
- * Class type, int slot, boolean noAccessCheck, int type_no)
- *
- * The "type_no" is defined by the java.lang.reflect.Field class.
+ * Class type, int slot, boolean noAccessCheck, char descriptor)
*/
static void Dalvik_java_lang_reflect_Field_getPrimitiveField(const u4* args,
JValue* pResult)
@@ -545,8 +528,8 @@ static void Dalvik_java_lang_reflect_Field_getPrimitiveField(const u4* args,
ClassObject* fieldType = (ClassObject*) args[3];
int slot = args[4];
bool noAccessCheck = (args[5] != 0);
- int typeNum = args[6];
- PrimitiveType targetType = convPrimType(typeNum);
+ jchar descriptor = args[6];
+ PrimitiveType targetType = dexGetPrimitiveTypeFromDescriptorChar(descriptor);
const Field* field;
JValue value;
@@ -574,9 +557,7 @@ static void Dalvik_java_lang_reflect_Field_getPrimitiveField(const u4* args,
/*
* Primitive field setters, e.g.:
* private void setIField(Object o, Class declaringClass,
- * Class type, int slot, boolean noAccessCheck, int type_no, int value)
- *
- * The "type_no" is defined by the java.lang.reflect.Field class.
+ * Class type, int slot, boolean noAccessCheck, char descriptor, int value)
*/
static void Dalvik_java_lang_reflect_Field_setPrimitiveField(const u4* args,
JValue* pResult)
@@ -587,9 +568,9 @@ static void Dalvik_java_lang_reflect_Field_setPrimitiveField(const u4* args,
ClassObject* fieldType = (ClassObject*) args[3];
int slot = args[4];
bool noAccessCheck = (args[5] != 0);
- int typeNum = args[6];
+ jchar descriptor = args[6];
const s4* valuePtr = (s4*) &args[7]; /* 64-bit vars spill into args[8] */
- PrimitiveType srcType = convPrimType(typeNum);
+ PrimitiveType srcType = dexGetPrimitiveTypeFromDescriptorChar(descriptor);
Field* field;
JValue value;
@@ -662,39 +643,39 @@ const DalvikNativeMethod dvm_java_lang_reflect_Field[] = {
Dalvik_java_lang_reflect_Field_getFieldModifiers },
{ "getField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;",
Dalvik_java_lang_reflect_Field_getField },
- { "getBField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZI)B",
+ { "getBField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)B",
Dalvik_java_lang_reflect_Field_getPrimitiveField },
- { "getCField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZI)C",
+ { "getCField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)C",
Dalvik_java_lang_reflect_Field_getPrimitiveField },
- { "getDField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZI)D",
+ { "getDField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)D",
Dalvik_java_lang_reflect_Field_getPrimitiveField },
- { "getFField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZI)F",
+ { "getFField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)F",
Dalvik_java_lang_reflect_Field_getPrimitiveField },
- { "getIField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZI)I",
+ { "getIField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)I",
Dalvik_java_lang_reflect_Field_getPrimitiveField },
- { "getJField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZI)J",
+ { "getJField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)J",
Dalvik_java_lang_reflect_Field_getPrimitiveField },
- { "getSField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZI)S",
+ { "getSField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)S",
Dalvik_java_lang_reflect_Field_getPrimitiveField },
- { "getZField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZI)Z",
+ { "getZField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)Z",
Dalvik_java_lang_reflect_Field_getPrimitiveField },
{ "setField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZLjava/lang/Object;)V",
Dalvik_java_lang_reflect_Field_setField },
- { "setBField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZIB)V",
+ { "setBField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCB)V",
Dalvik_java_lang_reflect_Field_setPrimitiveField },
- { "setCField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZIC)V",
+ { "setCField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCC)V",
Dalvik_java_lang_reflect_Field_setPrimitiveField },
- { "setDField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZID)V",
+ { "setDField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCD)V",
Dalvik_java_lang_reflect_Field_setPrimitiveField },
- { "setFField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZIF)V",
+ { "setFField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCF)V",
Dalvik_java_lang_reflect_Field_setPrimitiveField },
- { "setIField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZII)V",
+ { "setIField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCI)V",
Dalvik_java_lang_reflect_Field_setPrimitiveField },
- { "setJField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZIJ)V",
+ { "setJField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCJ)V",
Dalvik_java_lang_reflect_Field_setPrimitiveField },
- { "setSField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZIS)V",
+ { "setSField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCS)V",
Dalvik_java_lang_reflect_Field_setPrimitiveField },
- { "setZField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZIZ)V",
+ { "setZField", "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCZ)V",
Dalvik_java_lang_reflect_Field_setPrimitiveField },
{ "getDeclaredAnnotations", "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;",
Dalvik_java_lang_reflect_Field_getDeclaredAnnotations },
diff --git a/vm/oo/Array.c b/vm/oo/Array.c
index 99630cad0..48602d1e8 100644
--- a/vm/oo/Array.c
+++ b/vm/oo/Array.c
@@ -23,9 +23,6 @@
#include <limits.h>
static ClassObject* createArrayClass(const char* descriptor, Object* loader);
-static ClassObject* createPrimitiveClass(int idx);
-
-static const char gPrimLetter[] = PRIM_TYPE_TO_LETTER;
/*
* Allocate space for a new array object. This is the lowest-level array
@@ -218,7 +215,7 @@ ArrayObject* dvmAllocMultiArray(ClassObject* arrayClass, int curDim,
LOGVV(" end: array class (prim) is '%s'\n",
arrayClass->descriptor);
newArray = dvmAllocPrimitiveArray(
- gPrimLetter[arrayClass->elementClass->primitiveType],
+ dexGetPrimitiveTypeDescriptorChar(arrayClass->elementClass->primitiveType),
*dimensions, ALLOC_DEFAULT);
}
} else {
@@ -517,116 +514,6 @@ static ClassObject* createArrayClass(const char* descriptor, Object* loader)
}
/*
- * Get a class we generated for the primitive types.
- *
- * These correspond to e.g. Integer.TYPE, and are used as the element
- * class in arrays of primitives.
- *
- * "type" should be 'I', 'J', 'Z', etc.
- *
- * Returns NULL if the type doesn't correspond to a known primitive type.
- */
-ClassObject* dvmFindPrimitiveClass(char type)
-{
- int idx;
-
- switch (type) {
- case 'Z':
- idx = PRIM_BOOLEAN;
- break;
- case 'C':
- idx = PRIM_CHAR;
- break;
- case 'F':
- idx = PRIM_FLOAT;
- break;
- case 'D':
- idx = PRIM_DOUBLE;
- break;
- case 'B':
- idx = PRIM_BYTE;
- break;
- case 'S':
- idx = PRIM_SHORT;
- break;
- case 'I':
- idx = PRIM_INT;
- break;
- case 'J':
- idx = PRIM_LONG;
- break;
- case 'V':
- idx = PRIM_VOID;
- break;
- default:
- LOGW("Unknown primitive type '%c'\n", type);
- return NULL;
- }
-
- /*
- * Create the primitive class if it hasn't already been, and add it
- * to the table.
- */
- if (gDvm.primitiveClass[idx] == NULL) {
- ClassObject* primClass = createPrimitiveClass(idx);
- dvmReleaseTrackedAlloc((Object*) primClass, NULL);
-
- if (android_atomic_release_cas(0, (int) primClass,
- (int*) &gDvm.primitiveClass[idx]) != 0)
- {
- /*
- * Looks like somebody beat us to it. Free up the one we
- * just created and use the other one.
- */
- dvmFreeClassInnards(primClass);
- }
- }
-
- return gDvm.primitiveClass[idx];
-}
-
-/*
- * Synthesize a primitive class.
- *
- * Just creates the class and returns it (does not add it to the class list).
- */
-static ClassObject* createPrimitiveClass(int idx)
-{
- ClassObject* newClass;
- static const char* kClassDescriptors[PRIM_MAX] = {
- "Z", "C", "F", "D", "B", "S", "I", "J", "V"
- };
-
- assert(gDvm.classJavaLangClass != NULL);
- assert(idx >= 0 && idx < PRIM_MAX);
-
- /*
- * Fill out a few fields in the ClassObject.
- *
- * Note that primitive classes do not sub-class java/lang/Object. This
- * matters for "instanceof" checks. Also, we assume that the primitive
- * class does not override finalize().
- */
- newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_DEFAULT);
- if (newClass == NULL)
- return NULL;
- DVM_OBJECT_INIT(&newClass->obj, gDvm.classJavaLangClass);
- dvmSetClassSerialNumber(newClass);
- newClass->accessFlags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
- newClass->primitiveType = idx;
- newClass->descriptorAlloc = NULL;
- newClass->descriptor = kClassDescriptors[idx];
- //newClass->super = gDvm.classJavaLangObject;
- newClass->status = CLASS_INITIALIZED;
-
- /* don't need to set newClass->objectSize */
-
- LOGVV("Created primitive class '%s'\n", kClassDescriptors[idx]);
-
- return newClass;
-}
-
-/*
* Copy the entire contents of one array of objects to another. If the copy
* is impossible because of a type clash, we fail and return "false".
*/
diff --git a/vm/oo/Array.h b/vm/oo/Array.h
index 9cd79968b..9a873e6b9 100644
--- a/vm/oo/Array.h
+++ b/vm/oo/Array.h
@@ -97,12 +97,6 @@ ArrayObject* dvmAllocMultiArray(ClassObject* arrayClass, int curDim,
const int* dimensions);
/*
- * Find the synthesized object for the primitive class, generating it
- * if this is the first reference.
- */
-ClassObject* dvmFindPrimitiveClass(char type);
-
-/*
* Verify that the object is actually an array.
*
* Does not verify that the object is actually a non-NULL object.
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index 45f101693..c2f666a58 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -301,6 +301,89 @@ size_t dvmClassObjectSize(const ClassObject *clazz)
return classObjectSize(clazz->sfieldCount);
}
+/* (documented in header) */
+ClassObject* dvmFindPrimitiveClass(char type)
+{
+ PrimitiveType primitiveType = dexGetPrimitiveTypeFromDescriptorChar(type);
+
+ switch (primitiveType) {
+ case PRIM_VOID: return gDvm.typeVoid;
+ case PRIM_BOOLEAN: return gDvm.typeBoolean;
+ case PRIM_BYTE: return gDvm.typeByte;
+ case PRIM_SHORT: return gDvm.typeShort;
+ case PRIM_CHAR: return gDvm.typeChar;
+ case PRIM_INT: return gDvm.typeInt;
+ case PRIM_LONG: return gDvm.typeLong;
+ case PRIM_FLOAT: return gDvm.typeFloat;
+ case PRIM_DOUBLE: return gDvm.typeDouble;
+ default: {
+ LOGW("Unknown primitive type '%c'\n", type);
+ return NULL;
+ }
+ }
+}
+
+/*
+ * Synthesize a primitive class.
+ *
+ * Just creates the class and returns it (does not add it to the class list).
+ */
+static bool createPrimitiveType(PrimitiveType primitiveType, ClassObject** pClass)
+{
+ /*
+ * Fill out a few fields in the ClassObject.
+ *
+ * Note that primitive classes do not sub-class the class Object.
+ * This matters for "instanceof" checks. Also, we assume that the
+ * primitive class does not override finalize().
+ */
+
+ const char* descriptor = dexGetPrimitiveTypeDescriptor(primitiveType);
+ assert(descriptor != NULL);
+
+ ClassObject* newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_DEFAULT);
+ if (newClass == NULL) {
+ return false;
+ }
+
+ DVM_OBJECT_INIT(&newClass->obj, gDvm.classJavaLangClass);
+ dvmSetClassSerialNumber(newClass);
+ newClass->accessFlags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
+ newClass->primitiveType = primitiveType;
+ newClass->descriptorAlloc = NULL;
+ newClass->descriptor = descriptor;
+ newClass->super = NULL;
+ newClass->status = CLASS_INITIALIZED;
+
+ /* don't need to set newClass->objectSize */
+
+ LOGVV("Created class for primitive type '%s'\n", newClass->descriptor);
+
+ *pClass = newClass;
+ dvmReleaseTrackedAlloc((Object*) newClass, NULL);
+
+ return true;
+}
+
+/*
+ * Create the classes representing primitive types.
+ */
+static bool createPrimitiveTypes(void) {
+ bool ok = true;
+
+ ok &= createPrimitiveType(PRIM_VOID, &gDvm.typeVoid);
+ ok &= createPrimitiveType(PRIM_BOOLEAN, &gDvm.typeBoolean);
+ ok &= createPrimitiveType(PRIM_BYTE, &gDvm.typeByte);
+ ok &= createPrimitiveType(PRIM_SHORT, &gDvm.typeShort);
+ ok &= createPrimitiveType(PRIM_CHAR, &gDvm.typeChar);
+ ok &= createPrimitiveType(PRIM_INT, &gDvm.typeInt);
+ ok &= createPrimitiveType(PRIM_LONG, &gDvm.typeLong);
+ ok &= createPrimitiveType(PRIM_FLOAT, &gDvm.typeFloat);
+ ok &= createPrimitiveType(PRIM_DOUBLE, &gDvm.typeDouble);
+
+ return ok;
+}
+
/*
* Initialize the bootstrap class loader.
*
@@ -350,6 +433,15 @@ bool dvmClassStartup(void)
gDvm.classJavaLangClass->descriptor = "Ljava/lang/Class;";
/*
+ * Initialize the classes representing primitive types. These are
+ * instances of the class Class, but other than that they're fairly
+ * different from regular classes.
+ */
+ if (!createPrimitiveTypes()) {
+ return false;
+ }
+
+ /*
* Process the bootstrap class path. This means opening the specified
* DEX or Jar files and possibly running them through the optimizer.
*/
@@ -367,15 +459,20 @@ bool dvmClassStartup(void)
*/
void dvmClassShutdown(void)
{
- int i;
-
/* discard all system-loaded classes */
dvmHashTableFree(gDvm.loadedClasses);
gDvm.loadedClasses = NULL;
/* discard primitive classes created for arrays */
- for (i = 0; i < PRIM_MAX; i++)
- dvmFreeClassInnards(gDvm.primitiveClass[i]);
+ dvmFreeClassInnards(gDvm.typeVoid);
+ dvmFreeClassInnards(gDvm.typeBoolean);
+ dvmFreeClassInnards(gDvm.typeByte);
+ dvmFreeClassInnards(gDvm.typeShort);
+ dvmFreeClassInnards(gDvm.typeChar);
+ dvmFreeClassInnards(gDvm.typeInt);
+ dvmFreeClassInnards(gDvm.typeLong);
+ dvmFreeClassInnards(gDvm.typeFloat);
+ dvmFreeClassInnards(gDvm.typeDouble);
/* this closes DEX files, JAR files, etc. */
freeCpeArray(gDvm.bootClassPath);
diff --git a/vm/oo/Class.h b/vm/oo/Class.h
index e27ef79bc..3ad44bd5b 100644
--- a/vm/oo/Class.h
+++ b/vm/oo/Class.h
@@ -69,6 +69,13 @@ bool dvmClassPathContains(const ClassPathEntry* cpe, const char* path);
void dvmSetClassSerialNumber(ClassObject* clazz);
/*
+ * Find the class object representing the primitive type with the
+ * given descriptor. This returns NULL if the given type character
+ * is invalid.
+ */
+ClassObject* dvmFindPrimitiveClass(char type);
+
+/*
* Find the class with the given descriptor. Load it if it hasn't already
* been.
*
diff --git a/vm/oo/Object.h b/vm/oo/Object.h
index fd37da0ae..7f2fbf662 100644
--- a/vm/oo/Object.h
+++ b/vm/oo/Object.h
@@ -149,31 +149,6 @@ typedef enum ClassStatus {
} ClassStatus;
/*
- * Primitive type identifiers. We use these values as indexes into an
- * array of synthesized classes, so these start at zero and count up.
- * The order is arbitrary (mimics table in doc for newarray opcode),
- * but can't be changed without shuffling some reflection tables.
- *
- * PRIM_VOID can't be used as an array type, but we include it here for
- * other uses (e.g. Void.TYPE).
- */
-typedef enum PrimitiveType {
- PRIM_NOT = -1, /* value is not a primitive type */
- PRIM_BOOLEAN = 0,
- PRIM_CHAR = 1,
- PRIM_FLOAT = 2,
- PRIM_DOUBLE = 3,
- PRIM_BYTE = 4,
- PRIM_SHORT = 5,
- PRIM_INT = 6,
- PRIM_LONG = 7,
- PRIM_VOID = 8,
-
- PRIM_MAX
-} PrimitiveType;
-#define PRIM_TYPE_TO_LETTER "ZCFDBSIJV" /* must match order in enum */
-
-/*
* Definitions for packing refOffsets in ClassObject.
*/
/*
diff --git a/vm/reflect/Reflect.c b/vm/reflect/Reflect.c
index dd87d44fc..ae165dcc6 100644
--- a/vm/reflect/Reflect.c
+++ b/vm/reflect/Reflect.c
@@ -885,72 +885,111 @@ static PrimitiveType getBoxedType(DataObject* arg)
* float to double
* Values of types byte, char, and short are "internally" widened to int.
*
- * Returns the width in bytes of the destination primitive, or -1 if the
- * conversion is not allowed.
+ * Returns the width in 32-bit words of the destination primitive, or
+ * -1 if the conversion is not allowed.
*
* TODO? use JValue rather than u4 pointers
*/
int dvmConvertPrimitiveValue(PrimitiveType srcType,
PrimitiveType dstType, const s4* srcPtr, s4* dstPtr)
{
- enum {
- OK4, OK8, ItoJ,
- ItoD, JtoD, FtoD,
- ItoF, JtoF,
- bad, kMax
+ enum Conversion {
+ OK4, OK8, ItoJ, ItoD, JtoD, FtoD, ItoF, JtoF, bad
};
- /* [src][dst] */
- static const int kConvMode[kMax][kMax] = {
- /*FROM *TO: bool char float double byte short int long */
- /*bool */ { OK4, bad, bad, bad, bad, bad, bad, bad },
- /*char */ { bad, OK4, ItoF, ItoD, bad, bad, OK4, ItoJ },
- /*float*/ { bad, bad, OK4, FtoD, bad, bad, bad, bad },
- /*doubl*/ { bad, bad, bad, OK8, bad, bad, bad, bad },
- /*byte */ { bad, bad, ItoF, ItoD, OK4, OK4, OK4, ItoJ },
- /*short*/ { bad, bad, ItoF, ItoD, bad, OK4, OK4, ItoJ },
- /*int */ { bad, bad, ItoF, ItoD, bad, bad, OK4, ItoJ },
- /*long */ { bad, bad, JtoF, JtoD, bad, bad, bad, OK8 },
- };
- int result;
-
- assert(srcType != PRIM_NOT && dstType != PRIM_NOT &&
- srcType != PRIM_VOID && dstType != PRIM_VOID);
- result = kConvMode[srcType][dstType];
-
- //LOGV("+++ convprim: src=%d dst=%d result=%d\n", srcType, dstType, result);
-
- switch (result) {
- case OK4:
- *dstPtr = *srcPtr;
- return 1;
- case OK8:
- *(s8*)dstPtr = *(s8*)srcPtr;
- return 2;
- case ItoJ:
- *(s8*)dstPtr = (s8) (*(s4*) srcPtr);
- return 2;
- case ItoD:
- *(double*)dstPtr = (double) (*(s4*) srcPtr);
- return 2;
- case JtoD:
- *(double*)dstPtr = (double) (*(long long*) srcPtr);
- return 2;
- case FtoD:
- *(double*)dstPtr = (double) (*(float*) srcPtr);
- return 2;
- case ItoF:
- *(float*)dstPtr = (float) (*(int*) srcPtr);
- return 1;
- case JtoF:
- *(float*)dstPtr = (float) (*(long long*) srcPtr);
- return 1;
- case bad:
- LOGV("convert primitive: prim %d to %d not allowed\n",
- srcType, dstType);
- return -1;
- default:
- assert(false);
- return -1;
+
+ enum Conversion conv;
+
+ assert((srcType != PRIM_VOID) && (srcType != PRIM_NOT));
+ assert((dstType != PRIM_VOID) && (dstType != PRIM_NOT));
+
+ switch (dstType) {
+ case PRIM_BOOLEAN:
+ case PRIM_CHAR:
+ case PRIM_BYTE: {
+ conv = (srcType == dstType) ? OK4 : bad;
+ break;
+ }
+ case PRIM_SHORT: {
+ switch (srcType) {
+ case PRIM_BYTE:
+ case PRIM_SHORT: conv = OK4; break;
+ default: conv = bad; break;
+ }
+ break;
+ }
+ case PRIM_INT: {
+ switch (srcType) {
+ case PRIM_BYTE:
+ case PRIM_CHAR:
+ case PRIM_SHORT:
+ case PRIM_INT: conv = OK4; break;
+ default: conv = bad; break;
+ }
+ break;
+ }
+ case PRIM_LONG: {
+ switch (srcType) {
+ case PRIM_BYTE:
+ case PRIM_CHAR:
+ case PRIM_SHORT:
+ case PRIM_INT: conv = ItoJ; break;
+ case PRIM_LONG: conv = OK8; break;
+ default: conv = bad; break;
+ }
+ break;
+ }
+ case PRIM_FLOAT: {
+ switch (srcType) {
+ case PRIM_BYTE:
+ case PRIM_CHAR:
+ case PRIM_SHORT:
+ case PRIM_INT: conv = ItoF; break;
+ case PRIM_LONG: conv = JtoF; break;
+ case PRIM_FLOAT: conv = OK4; break;
+ default: conv = bad; break;
+ }
+ break;
+ }
+ case PRIM_DOUBLE: {
+ switch (srcType) {
+ case PRIM_BYTE:
+ case PRIM_CHAR:
+ case PRIM_SHORT:
+ case PRIM_INT: conv = ItoD; break;
+ case PRIM_LONG: conv = JtoD; break;
+ case PRIM_FLOAT: conv = FtoD; break;
+ case PRIM_DOUBLE: conv = OK8; break;
+ default: conv = bad; break;
+ }
+ break;
+ }
+ case PRIM_VOID:
+ case PRIM_NOT:
+ default: {
+ conv = bad;
+ break;
+ }
+ }
+
+ switch (conv) {
+ case OK4: *dstPtr = *srcPtr; return 1;
+ case OK8: *(s8*) dstPtr = *(s8*)srcPtr; return 2;
+ case ItoJ: *(s8*) dstPtr = (s8) (*(s4*) srcPtr); return 2;
+ case ItoD: *(double*) dstPtr = (double) (*(s4*) srcPtr); return 2;
+ case JtoD: *(double*) dstPtr = (double) (*(long long*) srcPtr); return 2;
+ case FtoD: *(double*) dstPtr = (double) (*(float*) srcPtr); return 2;
+ case ItoF: *(float*) dstPtr = (float) (*(int*) srcPtr); return 1;
+ case JtoF: *(float*) dstPtr = (float) (*(long long*) srcPtr); return 1;
+ case bad: {
+ LOGV("illegal primitive conversion: '%s' to '%s'\n",
+ dexGetPrimitiveTypeDescriptor(srcType),
+ dexGetPrimitiveTypeDescriptor(dstType));
+ return -1;
+ }
+ default: {
+ dvmAbort();
+ return -1; // Keep the compiler happy.
+ }
}
}
@@ -970,7 +1009,7 @@ int dvmConvertArgument(DataObject* arg, ClassObject* type, s4* destPtr)
s4* valuePtr;
srcType = getBoxedType(arg);
- if (srcType < 0) { // didn't pass a boxed primitive in
+ if (srcType == PRIM_NOT) { // didn't pass a boxed primitive in
LOGVV("conv arg: type '%s' not boxed primitive\n",
arg->obj.clazz->descriptor);
return -1;
@@ -1008,16 +1047,6 @@ int dvmConvertArgument(DataObject* arg, ClassObject* type, s4* destPtr)
*/
DataObject* dvmBoxPrimitive(JValue value, ClassObject* returnType)
{
- static const char* boxTypes[] = { // order from enum PrimitiveType
- "Ljava/lang/Boolean;",
- "Ljava/lang/Character;",
- "Ljava/lang/Float;",
- "Ljava/lang/Double;",
- "Ljava/lang/Byte;",
- "Ljava/lang/Short;",
- "Ljava/lang/Integer;",
- "Ljava/lang/Long;"
- };
ClassObject* wrapperClass;
DataObject* wrapperObj;
s4* dataPtr;
@@ -1031,11 +1060,10 @@ DataObject* dvmBoxPrimitive(JValue value, ClassObject* returnType)
return (DataObject*) value.l;
}
- assert(typeIndex >= 0 && typeIndex < PRIM_MAX);
- if (typeIndex == PRIM_VOID)
+ classDescriptor = dexGetBoxedTypeDescriptor(typeIndex);
+ if (classDescriptor == NULL) {
return NULL;
-
- classDescriptor = boxTypes[typeIndex];
+ }
wrapperClass = dvmFindSystemClass(classDescriptor);
if (wrapperClass == NULL) {