ObjectArray* Java_java_lang_Class_getDeclaredMethods0(Env* env, Class* clazz, jboolean publicOnly) { if (CLASS_IS_PRIMITIVE(clazz) || CLASS_IS_ARRAY(clazz)) return NULL; Method* methods = rvmGetMethods(env, clazz); if (rvmExceptionCheck(env)) return NULL; Method* method; jint length = 0; for (method = methods; method != NULL; method = method->next) { if (!METHOD_IS_CONSTRUCTOR(method) && !METHOD_IS_CLASS_INITIALIZER(method)) { if (!publicOnly || METHOD_IS_PUBLIC(method)) { length++; } } } ObjectArray* result = NULL; jint i = 0; for (method = methods; method != NULL; method = method->next) { if (!METHOD_IS_CONSTRUCTOR(method) && !METHOD_IS_CLASS_INITIALIZER(method)) { if (!publicOnly || METHOD_IS_PUBLIC(method)) { Object* c = createMethodObject(env, method); if (!c) return NULL; if (!result) { result = rvmNewObjectArray(env, length, c->clazz, NULL, NULL); if (!result) return NULL; } result->values[i++] = c; } } } return result; }
Array* rvmAllocateMemoryForArray(Env* env, Class* arrayClass, jint length) { jint elementSize = rvmGetArrayElementSize(env, arrayClass); if (elementSize == 0) { return NULL; } jlong size = (jlong) sizeof(Array) + (jlong) length * (jlong) elementSize; if (size > (jlong) (size_t) -1) { rvmThrowOutOfMemoryError(env); return NULL; } Array* m = NULL; if (CLASS_IS_PRIMITIVE(arrayClass->componentType)) { // Primitive array objects contain no pointers except for the Class // pointer and possibly a fat monitor. Those are allocated uncollectably // and will be reachable even if we alocate this atomically. m = (Array*) gcAllocateKind((size_t) size, atomicObjectGCKind); } else if (length < 30) { // TODO: Use GC bitmap descriptor for small Object arrays. m = (Array*) gcAllocateKind((size_t) size, objectGCKind); } else { // Large Object array. Conservatively scanned. Only the lock (if thin) // and the length fields could become a problem if they look like // pointers into the heap. m = (Array*) gcAllocateKind((size_t) size, largeArrayGCKind); } if (!m) { rvmThrowOutOfMemoryError(env); return NULL; } return m; }
ObjectArray* Java_java_lang_Class_getDeclaredFields0(Env* env, Class* clazz, jboolean publicOnly) { if (CLASS_IS_PRIMITIVE(clazz) || CLASS_IS_ARRAY(clazz)) return NULL; Field* fields = rvmGetFields(env, clazz); if (rvmExceptionCheck(env)) return NULL; Field* field; jint length = 0; for (field = fields; field != NULL; field = field->next) { if (!publicOnly || FIELD_IS_PUBLIC(field)) { length++; } } ObjectArray* result = NULL; jint i = 0; for (field = fields; field != NULL; field = field->next) { if (!publicOnly || FIELD_IS_PUBLIC(field)) { Object* c = createFieldObject(env, field); if (!c) return NULL; if (!result) { result = rvmNewObjectArray(env, length, c->clazz, NULL, NULL); if (!result) return NULL; } result->values[i++] = c; } } return result; }
static Class* createArrayClass(Env* env, Class* componentType) { jint length = strlen(componentType->name); char* desc = NULL; if (CLASS_IS_ARRAY(componentType) || CLASS_IS_PRIMITIVE(componentType)) { desc = rvmAllocateMemoryAtomic(env, length + 2); if (!desc) return NULL; desc[0] = '['; strcat(desc, componentType->name); } else { desc = rvmAllocateMemoryAtomic(env, length + 4); if (!desc) return NULL; desc[0] = '['; desc[1] = 'L'; strcat(desc, componentType->name); desc[length + 2] = ';'; } // TODO: Add clone() method. Class* clazz = rvmAllocateClass(env, desc, java_lang_Object, componentType->classLoader, CLASS_TYPE_ARRAY | CLASS_STATE_INITIALIZED | ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT, sizeof(Class), sizeof(Object), sizeof(Object), 0, 0, NULL, NULL); if (!clazz) return NULL; clazz->componentType = componentType; // Initialize methods to NULL to prevent rvmGetMethods() from trying to load the methods if called with this array class clazz->_methods = NULL; if (!rvmAddInterface(env, clazz, java_lang_Cloneable)) return NULL; if (!rvmAddInterface(env, clazz, java_io_Serializable)) return NULL; if (!rvmRegisterClass(env, clazz)) return NULL; return clazz; }
static jboolean parseElementValue(Env* env, void** attributes, Class* type, Object* classLoader, jvalue* result) { if (CLASS_IS_PRIMITIVE(type)) { switch (type->name[0]) { case 'Z': return parseBooleanElementValue(env, attributes, result); case 'B': return parseByteElementValue(env, attributes, result); case 'S': return parseShortElementValue(env, attributes, result); case 'C': return parseCharElementValue(env, attributes, result); case 'I': return parseIntElementValue(env, attributes, result); case 'J': return parseLongElementValue(env, attributes, result); case 'F': return parseFloatElementValue(env, attributes, result); case 'D': return parseDoubleElementValue(env, attributes, result); } } else if (CLASS_IS_ARRAY(type)) { return parseArrayElementValue(env, attributes, type, classLoader, result); } else if (type == java_lang_Class) { return parseClassElementValue(env, attributes, classLoader, result); } else if (type == java_lang_String) { return parseStringElementValue(env, attributes, result); } else if (CLASS_IS_ENUM(type) && type->superclass == java_lang_Enum) { return parseEnumElementValue(env, attributes, classLoader, result); } else if (CLASS_IS_ANNOTATION(type) && CLASS_IS_INTERFACE(type)) { return parseAnnotationElementValue(env, attributes, type, classLoader, result); } return FALSE; }
ObjectArray* Java_java_lang_Class_getDeclaredClasses0(Env* env, Class* clazz, jboolean publicOnly) { if (CLASS_IS_PRIMITIVE(clazz) || CLASS_IS_ARRAY(clazz)) return NULL; ObjectArray* result = rvmAttributeGetDeclaredClasses(env, clazz); if (!result || result->length == 0 || !publicOnly) { return result; } jint length = 0; jint i; for (i = 0; i < result->length; i++) { Class* c = (Class*) result->values[i]; if (CLASS_IS_PUBLIC(c)) { length++; } } if (length == 0) return NULL; ObjectArray* publicResult = rvmNewObjectArray(env, length, java_lang_Class, NULL, NULL); if (!publicResult) return NULL; jint index = 0; for (i = 0; i < result->length; i++) { Class* c = (Class*) result->values[i]; if (CLASS_IS_PUBLIC(c)) { publicResult->values[index++] = (Object*) c; } } return publicResult; }
static void heapDumpCallback(void* ptr, unsigned char kind, size_t sz, void* data) { if ((kind == GC_gcj_kind || kind == objectArrayGCKind) && ptr) { Object* obj = (Object*) ptr; if (obj->clazz) { if (obj->clazz == java_lang_Class) { Class* clazz = (Class*) obj; fprintf(stderr, " n%p [label=\"Class %s]\n", clazz, clazz->name); //, clazz->classDataSize); if (clazz->_data) { fprintf(stderr, " n%p -> n%p\n", clazz, clazz->_data); } void** start = (void**) (((char*) clazz) + offsetof(Class, data)); void** end = (void**) (((char*) start) + clazz->classRefCount * sizeof(Object*)); dumpRefs(clazz, start, end); } else if (CLASS_IS_ARRAY(obj->clazz)) { if (obj->clazz->name[1] == 'C') { // Array of chars. Include the 29 first characters in the dump. char s[30]; memset(s, 0, sizeof(s)); jint length = ((Array*) obj)->length; length = length > sizeof(s) - 1 ? sizeof(s) - 1 : length; for (jint i = 0; i < length; i++) { s[i] = (char) ((CharArray*) obj)->values[i]; } fprintf(stderr, " n%p [label=\"%s[%d] = %s\"]\n", obj, obj->clazz->name, ((Array*) obj)->length, s); } else { fprintf(stderr, " n%p [label=\"%s[%d]\"]\n", obj, obj->clazz->name, ((Array*) obj)->length); if (!CLASS_IS_PRIMITIVE(obj->clazz->componentType)) { ObjectArray* array = (ObjectArray*) obj; void** start = (void**) (((char*) array) + offsetof(ObjectArray, values)); void** end = (void**) (((char*) start) + sizeof(Object*) * array->length); dumpRefs(array, start, end); } } } else { Class* clazz = obj->clazz; fprintf(stderr, " n%p [label=\"Instance %s\"]\n", obj, obj->clazz->name); while (clazz != NULL) { void** start = (void**) (((char*) obj) + clazz->instanceDataOffset); void** end = (void**) (((char*) start) + clazz->instanceRefCount * sizeof(Object*)); if (clazz == java_lang_ref_Reference) { void** referent_start = (void**) (((char*) obj) + java_lang_ref_Reference_referent->offset); void** referent_end = (void**) (((char*) referent_start) + sizeof(Object*)); //if (*referent_start) { //fprintf(stderr, "\t%p (weak)\n", *referent_start); //} dumpRefs(obj, start, referent_start); dumpRefs(obj, referent_end, end); } else { dumpRefs(obj, start, end); } clazz = clazz->superclass; } } } } }
static struct GC_ms_entry* markObject(GC_word* addr, struct GC_ms_entry* mark_stack_ptr, struct GC_ms_entry* mark_stack_limit, GC_word env) { Object* obj = (Object*) addr; if (obj == NULL || obj->clazz == NULL || obj->clazz->object.clazz != java_lang_Class) { // According to the comments in gc_mark.h the GC sometimes calls the mark_proc with unused objects. // Such objects have been cleared except for the first word which points to a free list link field. // A valid RovoVM Object must point to a Class and the Class of the Object's Class must be java.lang.Class. return mark_stack_ptr; } mark_stack_ptr = GC_MARK_AND_PUSH(obj->clazz, mark_stack_ptr, mark_stack_limit, NULL); if (obj->clazz == java_lang_Class) { // Class* Class* clazz = (Class*) obj; mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_data, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH((void*) clazz->name, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->classLoader, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->superclass, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->componentType, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_interfaces, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_fields, mark_stack_ptr, mark_stack_limit, NULL); mark_stack_ptr = GC_MARK_AND_PUSH(clazz->_methods, mark_stack_ptr, mark_stack_limit, NULL); void** start = (void**) (((char*) clazz) + offsetof(Class, data)); void** end = (void**) (((char*) start) + clazz->classRefCount * sizeof(Object*)); mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } else if (CLASS_IS_ARRAY(obj->clazz)) { if (!CLASS_IS_PRIMITIVE(obj->clazz->componentType)) { // Array of objects. Mark all values in the array. ObjectArray* array = (ObjectArray*) obj; void** start = (void**) (((char*) array) + offsetof(ObjectArray, values)); void** end = (void**) (((char*) start) + sizeof(Object*) * array->length); mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } } else { // Object* - for each Class in the hierarchy of obj's Class we mark the first instanceRefCount*sizeof(Object*) bytes Class* clazz = obj->clazz; while (clazz != NULL) { void** start = (void**) (((char*) obj) + clazz->instanceDataOffset); void** end = (void**) (((char*) start) + clazz->instanceRefCount * sizeof(Object*)); if (clazz == java_lang_ref_Reference) { // Don't mark the referent field void** referent_start = (void**) (((char*) obj) + java_lang_ref_Reference_referent->offset); void** referent_end = (void**) (((char*) referent_start) + sizeof(Object*)); mark_stack_ptr = markRegion(start, referent_start, mark_stack_ptr, mark_stack_limit); mark_stack_ptr = markRegion(referent_end, end, mark_stack_ptr, mark_stack_limit); } else { mark_stack_ptr = markRegion(start, end, mark_stack_ptr, mark_stack_limit); } clazz = clazz->superclass; } } return mark_stack_ptr; }
static ObjectArray* listClasses(Env* env, Class* instanceofClazz, ClassLoader* classLoader, void* hash) { if (instanceofClazz && (CLASS_IS_ARRAY(instanceofClazz) || CLASS_IS_PRIMITIVE(instanceofClazz))) { return NULL; } ClassInfoHeader** base = getClassInfosBase(hash); uint32_t count = getClassInfosCount(hash); uint32_t i = 0; jint matches = count; TypeInfo* instanceofTypeInfo = instanceofClazz ? instanceofClazz->typeInfo : NULL; if (instanceofTypeInfo) { matches = 0; for (i = 0; i < count; i++) { ClassInfoHeader* header = base[i]; if ((header->flags & CI_ERROR) == 0) { if ((!CLASS_IS_INTERFACE(instanceofClazz) && rvmIsClassTypeInfoAssignable(env, header->typeInfo, instanceofTypeInfo)) || (CLASS_IS_INTERFACE(instanceofClazz) && rvmIsInterfaceTypeInfoAssignable(env, header->typeInfo, instanceofTypeInfo))) { matches++; } } } } if (matches == 0) return NULL; ObjectArray* result = rvmNewObjectArray(env, matches, java_lang_Class, NULL, NULL); if (!result) return NULL; jint j = 0; for (i = 0; i < count; i++) { ClassInfoHeader* header = base[i]; if ((header->flags & CI_ERROR) == 0) { if (!instanceofTypeInfo || ((!CLASS_IS_INTERFACE(instanceofClazz) && rvmIsClassTypeInfoAssignable(env, header->typeInfo, instanceofTypeInfo)) || (CLASS_IS_INTERFACE(instanceofClazz) && rvmIsInterfaceTypeInfoAssignable(env, header->typeInfo, instanceofTypeInfo)))) { result->values[j++] = (Object*) (header->clazz ? header->clazz : createClass(env, header, classLoader)); if (rvmExceptionOccurred(env)) return NULL; } } } return result; }
jboolean rvmIsAssignableFrom(Env* env, Class* s, Class* t) { // TODO: What if s or t are NULL? if (s == t || t == java_lang_Object) { return TRUE; } if (CLASS_IS_ARRAY(s)) { if (t == java_io_Serializable) { return TRUE; } if (t == java_lang_Cloneable) { return TRUE; } if (!CLASS_IS_ARRAY(t)) { return FALSE; } Class* componentType = s->componentType; if (CLASS_IS_PRIMITIVE(componentType)) { // s is a primitive array and can only be assigned to // class t if s == t or t == (Object|Serializable|Cloneable). But we // already know that s != t and t != (Object|Serializable|Cloneable) return FALSE; } return rvmIsAssignableFrom(env, componentType, t->componentType); } if (CLASS_IS_INTERFACE(t)) { // s or any of its parents must implement the interface t for (; s; s = s->superclass) { Interface* interface = rvmGetInterfaces(env, s); if (rvmExceptionCheck(env)) return FALSE; for (; interface != NULL; interface = interface->next) { if (rvmIsAssignableFrom(env, interface->interface, t)) { return TRUE; } } } return FALSE; } while (s && s != t) { s = s->superclass; } return s ? TRUE : FALSE; }
jvalue* validateAndUnwrapArgs(Env* env, ObjectArray* parameterTypes, ObjectArray* args) { jint length = args->length; jvalue* jvalueArgs = length > 0 ? (jvalue*) rvmAllocateMemory(env, sizeof(jvalue) * length) : emptyJValueArgs; if (!jvalueArgs) return NULL; jint i; for (i = 0; i < length; i++) { Object* arg = args->values[i]; Class* type = (Class*) parameterTypes->values[i]; if (CLASS_IS_PRIMITIVE(type)) { if (arg == NULL) { const char* typeName = rvmGetHumanReadableClassName(env, type); if (typeName) { rvmThrowNewf(env, java_lang_IllegalArgumentException, "argument %d should have type %s, got null", i + 1, typeName); } return NULL; } if (!rvmUnbox(env, arg, type, &jvalueArgs[i])) { if (rvmExceptionOccurred(env)->clazz == java_lang_ClassCastException) { rvmExceptionClear(env); const char* argTypeName = rvmGetHumanReadableClassName(env, arg->clazz); const char* typeName = argTypeName ? rvmGetHumanReadableClassName(env, type) : NULL; if (argTypeName && typeName) { rvmThrowNewf(env, java_lang_IllegalArgumentException, "argument %d should have type %s, got %s", i + 1, typeName, argTypeName); } } return NULL; } } else { if (arg && !rvmIsInstanceOf(env, arg, type)) { const char* argTypeName = rvmGetHumanReadableClassName(env, arg->clazz); const char* typeName = argTypeName ? rvmGetHumanReadableClassName(env, type) : NULL; if (argTypeName && typeName) { rvmThrowNewf(env, java_lang_IllegalArgumentException, "argument %d should have type %s, got %s", i + 1, typeName, argTypeName); } return NULL; } jvalueArgs[i].l = (jobject) arg; } } return jvalueArgs; }
static void heapDumpCallback(void* ptr, unsigned char kind, size_t sz, void* data) { if (kind == objectGCKind || kind == largeArrayGCKind || kind == atomicObjectGCKind) { Object* obj = (Object*) ptr; if (obj->clazz == java_lang_Class) { Class* clazz = (Class*) obj; fprintf(stderr, "%p (class %s of size %d bytes)\n", clazz, clazz->name, clazz->classDataSize); if (clazz->_data) { fprintf(stderr, "\t%p\n", clazz->_data); } void** start = (void**) (((char*) clazz) + offsetof(Class, data)); void** end = (void**) (((char*) start) + clazz->classRefCount * sizeof(Object*)); dumpRefs(start, end); } else if (CLASS_IS_ARRAY(obj->clazz)) { fprintf(stderr, "%p (array of type %s of length %d elements)\n", obj, obj->clazz->name, ((Array*) obj)->length); if (!CLASS_IS_PRIMITIVE(obj->clazz->componentType)) { ObjectArray* array = (ObjectArray*) obj; void** start = (void**) (((char*) array) + offsetof(ObjectArray, values)); void** end = (void**) (((char*) start) + sizeof(Object*) * array->length); dumpRefs(start, end); } } else { Class* clazz = obj->clazz; fprintf(stderr, "%p (object of type %s of size %d bytes)\n", obj, clazz->name, clazz->instanceDataSize); while (clazz != NULL) { void** start = (void**) (((char*) obj) + clazz->instanceDataOffset); void** end = (void**) (((char*) start) + clazz->instanceRefCount * sizeof(Object*)); if (clazz == java_lang_ref_Reference) { void** referent_start = (void**) (((char*) obj) + java_lang_ref_Reference_referent->offset); void** referent_end = (void**) (((char*) referent_start) + sizeof(Object*)); if (*referent_start) { fprintf(stderr, "\t%p (weak)\n", *referent_start); } dumpRefs(start, referent_start); dumpRefs(referent_end, end); } else { dumpRefs(start, end); } clazz = clazz->superclass; } } } }
Object* rvmBox(Env* env, Class* type, jvalue* value) { if (CLASS_IS_PRIMITIVE(type)) { switch (type->name[0]) { case 'Z': return (Object*) rvmBoxBoolean(env, value->z); case 'B': return (Object*) rvmBoxByte(env, value->b); case 'S': return (Object*) rvmBoxShort(env, value->s); case 'C': return (Object*) rvmBoxChar(env, value->c); case 'I': return (Object*) rvmBoxInt(env, value->i); case 'J': return (Object*) rvmBoxLong(env, value->j); case 'F': return (Object*) rvmBoxFloat(env, value->f); case 'D': return (Object*) rvmBoxDouble(env, value->d); } } return (Object*) value->l; }
* Destroy a class object. */ static void /* ARGSUSED */ destroyClass(Collector *collector, void* c) { int i; unsigned int idx; Hjava_lang_Class* clazz = c; constants* pool; DBG(CLASSGC, dprintf("destroying class %s @ %p\n", clazz->name ? clazz->name->data : "newborn", c); ); assert(!CLASS_IS_PRIMITIVE(clazz)); /* NB: Make sure that we don't unload fully loaded classes without * classloaders. This is wrong and indicate of a bug. * * NB: Note that this function must destroy any partially * initialized class. Class processing may fail at any * state, and the discarded class objects destroyed. */ assert(clazz->state != CSTATE_COMPLETE || clazz->loader != 0); #if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_CLASS_UNLOAD) && clazz->state >= CSTATE_PREPARED) { JVMPI_Event ev;
static jboolean parseArrayElementValue(Env* env, void** attributes, Class* arrayClass, Object* classLoader, jvalue* result) { jbyte tag = getByte(attributes); if (tag != '[') return throwFormatError(env, "Array"); Class* componentType = arrayClass->componentType; jint length = getChar(attributes); Array* array = NULL; if (CLASS_IS_PRIMITIVE(componentType)) { switch (componentType->name[0]) { case 'Z': array = (Array*) rvmNewBooleanArray(env, length); break; case 'B': array = (Array*) rvmNewByteArray(env, length); break; case 'S': array = (Array*) rvmNewShortArray(env, length); break; case 'C': array = (Array*) rvmNewCharArray(env, length); break; case 'I': array = (Array*) rvmNewIntArray(env, length); break; case 'J': array = (Array*) rvmNewLongArray(env, length); break; case 'F': array = (Array*) rvmNewFloatArray(env, length); break; case 'D': array = (Array*) rvmNewDoubleArray(env, length); break; } } else { array = (Array*) rvmNewObjectArray(env, length, NULL, arrayClass, NULL); } if (!array) return FALSE; jint i = 0; for (i = 0; i < length; i++) { jvalue v; if (!parseElementValue(env, attributes, componentType, classLoader, &v)) return FALSE; if (CLASS_IS_PRIMITIVE(componentType)) { switch (componentType->name[0]) { case 'Z': ((BooleanArray*) array)->values[i] = v.z; break; case 'B': ((ByteArray*) array)->values[i] = v.b; break; case 'S': ((ShortArray*) array)->values[i] = v.s; break; case 'C': ((CharArray*) array)->values[i] = v.c; break; case 'I': ((IntArray*) array)->values[i] = v.i; break; case 'J': ((LongArray*) array)->values[i] = v.j; break; case 'F': ((FloatArray*) array)->values[i] = v.f; break; case 'D': ((DoubleArray*) array)->values[i] = v.d; break; } } else { ((ObjectArray*) array)->values[i] = (Object*) v.l; } } result->l = (jobject) array; return result->l ? TRUE : FALSE; }
jboolean Java_java_lang_Class_isPrimitive(Env* env, Class* thiz) { return CLASS_IS_PRIMITIVE(thiz) ? TRUE : FALSE; }
void rvmInitialize(Env* env, Class* clazz) { obtainClassLock(); // TODO: Throw java.lang.NoClassDefFoundError if state == CLASS_ERROR? if (CLASS_IS_STATE_ERROR(clazz)) { // TODO: Add the class' binary name in the message rvmThrowNew(env, java_lang_NoClassDefFoundError, "Could not initialize class ??"); releaseClassLock(); return; } if (!CLASS_IS_STATE_INITIALIZED(clazz) && !CLASS_IS_STATE_INITIALIZING(clazz)) { jint oldState = clazz->flags & CLASS_STATE_MASK; clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | CLASS_STATE_INITIALIZING; if (clazz->superclass) { rvmInitialize(env, clazz->superclass); if (rvmExceptionOccurred(env)) { clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | oldState; releaseClassLock(); return; } } TRACEF("Initializing class %s", clazz->name); void* initializer = clazz->initializer; if (!initializer) { if (!CLASS_IS_ARRAY(clazz) && !CLASS_IS_PROXY(clazz) && !CLASS_IS_PRIMITIVE(clazz)) { env->vm->options->classInitialized(env, clazz); } clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | CLASS_STATE_INITIALIZED; releaseClassLock(); return; } CallInfo* callInfo = call0AllocateCallInfo(env, initializer, 1, 0, 0, 0, 0); call0AddPtr(callInfo, env); void (*f)(CallInfo*) = (void (*)(CallInfo*)) _call0; rvmPushGatewayFrame(env); TrycatchContext tc = {0}; tc.sel = CATCH_ALL_SEL; if (!rvmTrycatchEnter(env, &tc)) { f(callInfo); } rvmTrycatchLeave(env); rvmPopGatewayFrame(env); Object* exception = rvmExceptionClear(env); if (exception) { clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | CLASS_STATE_ERROR; if (!rvmIsInstanceOf(env, exception, java_lang_Error)) { // If exception isn't an instance of java.lang.Error // we must wrap it in a java.lang.ExceptionInInitializerError Method* constructor = rvmGetInstanceMethod(env, java_lang_ExceptionInInitializerError, "<init>", "(Ljava/lang/Throwable;)V"); if (!constructor) return; Object* wrappedException = rvmNewObject(env, java_lang_ExceptionInInitializerError, constructor, exception); if (!wrappedException) return; exception = wrappedException; } rvmThrow(env, exception); releaseClassLock(); return; } if (!CLASS_IS_ARRAY(clazz) && !CLASS_IS_PROXY(clazz) && !CLASS_IS_PRIMITIVE(clazz)) { env->vm->options->classInitialized(env, clazz); } clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | CLASS_STATE_INITIALIZED; } releaseClassLock(); }
void java_lang_VMSystem_arraycopy0(struct Hjava_lang_Object* src, jint srcpos, struct Hjava_lang_Object* dst, jint dstpos, jint len) { char* in; char* out; int elemsz; Hjava_lang_Class* sclass; Hjava_lang_Class* dclass; sclass = OBJECT_CLASS(src); dclass = OBJECT_CLASS(dst); sclass = Kaffe_get_array_element_type(sclass); dclass = Kaffe_get_array_element_type(dclass); elemsz = TYPE_SIZE(sclass); len *= elemsz; srcpos *= elemsz; dstpos *= elemsz; in = &((char*)ARRAY_DATA(src))[srcpos]; out = &((char*)ARRAY_DATA(dst))[dstpos]; if (sclass == dclass) { #if defined(HAVE_MEMMOVE) memmove((void*)out, (void*)in, (size_t)len); #else /* Do it ourself */ #if defined(HAVE_MEMCPY) if (src != dst) { memcpy((void*)out, (void*)in, (size_t)len); } else #endif if (out < in) { /* Copy forwards */ for (; len > 0; len--) { *out++ = *in++; } } else { /* Copy backwards */ out += len; in += len; for (; len > 0; len--) { *--out = *--in; } } #endif } else { if (CLASS_IS_PRIMITIVE(sclass) || CLASS_IS_PRIMITIVE(dclass)) { Hjava_lang_Throwable* asexc; const char *stype = CLASS_CNAME(sclass); const char *dtype = CLASS_CNAME(dclass); char *b; #define _FORMAT "incompatible array types `%s' and `%s'" b = checkPtr(KMALLOC(strlen(stype)+strlen(dtype)+strlen(_FORMAT))); sprintf(b, _FORMAT, stype, dtype); #undef _FORMAT asexc = ArrayStoreException(b); KFREE(b); throwException(asexc); } for (; len > 0; len -= sizeof(Hjava_lang_Object*)) { Hjava_lang_Object* val = *(Hjava_lang_Object**)in; if (val != 0 && !instanceof(dclass, OBJECT_CLASS(val))) { Hjava_lang_Throwable* asexc; const char *vtype = CLASS_CNAME(OBJECT_CLASS(val)); const char *atype = CLASS_CNAME(dclass); char *b; #define _FORMAT "can't store `%s' in array of type `%s'" b = checkPtr(KMALLOC(strlen(vtype)+strlen(atype)+strlen(_FORMAT))); sprintf(b, _FORMAT, vtype, atype); #undef _FORMAT asexc = ArrayStoreException(b); KFREE(b); throwException(asexc); } *(Hjava_lang_Object**)out = val; in += sizeof(Hjava_lang_Object*); out += sizeof(Hjava_lang_Object*); } } }