Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
                }
            }
        }
    }
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
Object* rvmCloneObject(Env* env, Object* obj) {
    if (CLASS_IS_ARRAY(obj->clazz)) {
        return (Object*) rvmCloneArray(env, (Array*) obj);
    }
    jint size = obj->clazz->instanceDataSize;
    Object* copy = rvmAllocateMemoryForObject(env, obj->clazz);
    if (!copy) return NULL;
    memcpy(copy, obj, size);
    copy->lock = 0;
    return copy;
}
Esempio n. 10
0
File: bc.c Progetto: SinoJerk/robovm
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;
}
Esempio n. 11
0
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;
            }
        }
    }
}
Esempio n. 12
0
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;
    }

    // This mark procedure should never be called for array instances.
    assert(!CLASS_IS_ARRAY(obj->clazz));

    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->typeInfo, mark_stack_ptr, mark_stack_limit, NULL);
        mark_stack_ptr = GC_MARK_AND_PUSH(clazz->vitable, mark_stack_ptr, mark_stack_limit, NULL);
        mark_stack_ptr = GC_MARK_AND_PUSH(clazz->itables, 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 {
        // 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);
            }

            // Some classes use longs and ints to store pointers to GC allocated memory.
            // For each such class we need to mark those fields here.
            // Note: java.lang.Thread, java.lang.reflect.Constructor, java.lang.reflect.Method, 
            // java.lang.reflect.Field also contain such fields but we don't have
            // to mark those because the Thread, Method and Field C structures those
            // point to are also referenced by other roots (the threads list, Class structures)
            // that prevent GCing.
            if (clazz == java_lang_Throwable) {
                // The 'stackState' field in java.lang.Throwable is a long but contains
                // a pointer to an address on the GCed heap.
                void** field_start = (void**) (((char*) obj) + java_lang_Throwable_stackState->offset);
                void** field_end = (void**) (((char*) field_start) + sizeof(jlong));
                mark_stack_ptr = markRegion(field_start, field_end, mark_stack_ptr, mark_stack_limit);
            } else if (clazz == org_robovm_rt_bro_Struct) {
                // The 'handle' field in org.robovm.rt.bro.Struct (actually in its
                // superclass NativeObject) is a long but contains a pointer.
                // Possibly to an address on the GCed heap.
                void** field_start = (void**) (((char*) obj) + org_robovm_rt_bro_Struct_handle->offset);
                void** field_end = (void**) (((char*) field_start) + sizeof(jlong));
                mark_stack_ptr = markRegion(field_start, field_end, mark_stack_ptr, mark_stack_limit);
            } else if (clazz == java_nio_MemoryBlock) {
                // The 'address' field in java.nio.MemoryBlock is a long but contains a pointer.
                // Possibly to an address on the GCed heap.
                void** field_start = (void**) (((char*) obj) + java_nio_MemoryBlock_address->offset);
                void** field_end = (void**) (((char*) field_start) + sizeof(jlong));
                mark_stack_ptr = markRegion(field_start, field_end, mark_stack_ptr, mark_stack_limit);
            }
            clazz = clazz->superclass;
        }
    }

    return mark_stack_ptr;
}
Esempio n. 13
0
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();
}