Exemple #1
0
void rvmRegisterReference(Env* env, Object* reference, Object* referent) {
    if (referent) {
        // Add 'reference' to the references list for 'referent' in the referents hashtable
        rvmLockMutex(&referentsLock);

        ReferenceList* l = rvmAllocateMemory(env, sizeof(ReferenceList));
        if (!l) goto done; // OOM thrown
        l->reference = reference;

        void* key = (void*) GC_HIDE_POINTER(referent); // Hide the pointer from the GC so that it doesn't prevent the referent from being GCed.
        ReferentEntry* referentEntry;
        HASH_FIND_PTR(referents, &key, referentEntry);
        if (!referentEntry) {
            // referent is not in the hashtable. Add it.
            referentEntry = rvmAllocateMemory(env, sizeof(ReferentEntry));
            if (!referentEntry) goto done; // OOM thrown
            referentEntry->key = key;
            HASH_ADD_PTR(referents, key, referentEntry);
        }

        // Add the reference to the referent's list of references
        LL_PREPEND(referentEntry->references, l);

        // Register the referent for finalization
        GC_REGISTER_FINALIZER_NO_ORDER(referent, _finalizeObject, NULL, NULL, NULL);

done:
        rvmUnlockMutex(&referentsLock);
    }
}
Exemple #2
0
/**
 * Implements all abstract methods in {@code proxyClass}. This should be called after
 * {@link #addProxyMethods()} which will override all methods defined by the proxy's
 * ancestor classes (abstract or concrete).
 */
static jboolean implementAbstractInterfaceMethods(Env* env, Class* proxyClass, Interface* interface, ProxyClassData* proxyClassData) {
    if (!interface) return TRUE;

    Method* method = rvmGetMethods(env, interface->interface);
    if (rvmExceptionOccurred(env)) return FALSE;
    for (; method != NULL; method = method->next) {
        if (!METHOD_IS_CLASS_INITIALIZER(method)) {
            ProxyMethod* proxyMethod = hasMethod(env, proxyClass, method->name, method->desc);
            if (rvmExceptionOccurred(env)) return FALSE;
            if (!proxyMethod) { 
                jint access = (method->access & (~ACC_ABSTRACT)) | ACC_FINAL;
                proxyMethod = addProxyMethod(env, proxyClass, method, access, _proxy0);
                if (!proxyMethod) return FALSE;
            }
            // Record the lookup function in proxyClassData
            LookupEntry* entry = rvmAllocateMemory(env, sizeof(LookupEntry));
            if (!entry) return FALSE;
            entry->key.name = method->name;
            entry->key.desc = method->desc;
            entry->method = proxyMethod;
            HASH_ADD(hh, proxyClassData->lookupsHash, key, sizeof(LookupKey), entry);
        }
    }

    if (!implementAbstractInterfaceMethods(env, proxyClass, interface->next, proxyClassData)) return FALSE;
    Interface* interfaceInterfaces = rvmGetInterfaces(env, interface->interface);
    if (rvmExceptionCheck(env)) return FALSE;
    if (!implementAbstractInterfaceMethods(env, proxyClass, interfaceInterfaces, proxyClassData)) return FALSE;

    return TRUE;
}
Exemple #3
0
void rvmPushShadowFrame(Env* env, void* functionAddress) {
    ShadowFrame* frame = rvmAllocateMemory(env, sizeof(ShadowFrame));
    frame->functionAddress = functionAddress;

    frame->prev = env->shadowFrame;
    env->shadowFrame = frame;
}
Exemple #4
0
static jboolean addLoadedClass(Env* env, Class* clazz) {
    LoadedClassEntry* entry = rvmAllocateMemory(env, sizeof(LoadedClassEntry));
    if (!entry) return FALSE;
    entry->key = clazz->name;
    entry->clazz = clazz;
    HASH_ADD_KEYPTR(hh, loadedClasses, entry->key, strlen(entry->key), entry);
    return TRUE;
}
Exemple #5
0
static jboolean initClasspathEntries(Env* env, char* basePath, char** raw, ClasspathEntry** first) {
    jint i = 0;
    while (raw[i]) {
        ClasspathEntry* entry = rvmAllocateMemory(env, sizeof(ClasspathEntry));
        if (!entry) return FALSE;
        absolutize(basePath, raw[i], entry->jarPath);
        LL_APPEND(*first, entry);
        i++;
    }

    return TRUE;
}
Exemple #6
0
jboolean rvmAddInterface(Env* env, Class* clazz, Class* interf) {
    if (!CLASS_IS_INTERFACE(interf)) {
        // TODO: Message should look like ?
        rvmThrowIncompatibleClassChangeError(env, "");
        return FALSE;
    }
    Interface* interface = rvmAllocateMemory(env, sizeof(Interface));
    if (!interface) return FALSE;
    interface->interface = interf;
    if (clazz->_interfaces == &INTERFACES_NOT_LOADED) {
        clazz->_interfaces = NULL;
    }
    LL_APPEND(clazz->_interfaces, interface);
    return TRUE;
}
Exemple #7
0
void registerCleanupHandler(Env* env, Object* object, CleanupHandler handler) {
    rvmLockMutex(&referentsLock);
    CleanupHandlerList* l = rvmAllocateMemory(env, sizeof(CleanupHandlerList));
    if (!l) goto done; // OOM thrown
    l->handler = handler;
    ReferentEntry* referentEntry = getReferentEntryForObject(env, object);
    if (!referentEntry) goto done;
    // Add the handler to the object's list of cleanup handlers
    LL_PREPEND(referentEntry->cleanupHandlers, l);
    // Register the referent for finalization
    GC_REGISTER_FINALIZER_NO_ORDER(object, _finalizeObject, NULL, NULL, NULL);

done:
    rvmUnlockMutex(&referentsLock);
}
Exemple #8
0
static jvalue* va_list2jargs(Env* env, Method* method, va_list args) {
    jint argsCount = rvmGetParameterCount(method);

    if (argsCount == 0) {
        return emptyJValueArgs;
    }

    jvalue *jvalueArgs = (jvalue*) rvmAllocateMemory(env, sizeof(jvalue) * argsCount);
    if (!jvalueArgs) return NULL;

    const char* desc = method->desc;
    const char* c;
    jint i = 0;
    while ((c = rvmGetNextParameterType(&desc))) {
        switch (c[0]) {
        case 'B':
            jvalueArgs[i++].b = (jbyte) va_arg(args, jint);
            break;
        case 'Z':
            jvalueArgs[i++].z = (jboolean) va_arg(args, jint);
            break;
        case 'S':
            jvalueArgs[i++].s = (jshort) va_arg(args, jint);
            break;
        case 'C':
            jvalueArgs[i++].c = (jchar) va_arg(args, jint);
            break;
        case 'I':
            jvalueArgs[i++].i = va_arg(args, jint);
            break;
        case 'J':
            jvalueArgs[i++].j = va_arg(args, jlong);
            break;
        case 'F':
            jvalueArgs[i++].f = (jfloat) va_arg(args, jdouble);
            break;
        case 'D':
            jvalueArgs[i++].d = va_arg(args, jdouble);
            break;
        case '[':
        case 'L':
            jvalueArgs[i++].l = va_arg(args, jobject);
            break;
        }
    }

    return jvalueArgs;
}
Exemple #9
0
static AddressClassLookup* getAddressClassLookups(Env* env) {
    if (!addressClassLookups) {
        jint count = 0;
        iterateClassInfos(env, countClassesWithConcreteMethodsCallback, _bcBootClassesHash, &count);
        iterateClassInfos(env, countClassesWithConcreteMethodsCallback, _bcClassesHash, &count);
        AddressClassLookup* lookups = rvmAllocateMemory(env, sizeof(AddressClassLookup) * count);
        if (!lookups) return NULL;
        AddressClassLookup* _lookups = lookups;
        iterateClassInfos(env, initAddressClassLookupsCallback, _bcBootClassesHash, &_lookups);
        iterateClassInfos(env, initAddressClassLookupsCallback, _bcClassesHash, &_lookups);
        qsort(lookups, count, sizeof(AddressClassLookup), addressClassLookupCompareQSort);
        addressClassLookupsCount = count;
        addressClassLookups = lookups;
    }
    return addressClassLookups;
}
Exemple #10
0
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;
}
Exemple #11
0
static jboolean addProxyMethods(Env* env, Class* proxyClass, Class* clazz, ProxyClassData* proxyClassData) {
    // Add constructors from the super class and override all overridable methods. Constructors will use 
    // the same impl as the superclass. Overridden methods will have _rvmProxy0 as its impl.

    if (clazz->superclass) {
        if (!addProxyMethods(env, proxyClass, clazz->superclass, proxyClassData)) return FALSE;
    }

    Method* method = rvmGetMethods(env, clazz);
    if (rvmExceptionOccurred(env)) return FALSE;
    for (; method != NULL; method = method->next) {
        if (!METHOD_IS_STATIC(method) && !METHOD_IS_PRIVATE(method) && !METHOD_IS_FINAL(method)
                && (!METHOD_IS_CONSTRUCTOR(method) || clazz == proxyClass->superclass)) {

            void* impl = NULL;
            jint access = (method->access & (~ACC_ABSTRACT & ~ACC_NATIVE)) | ACC_FINAL;
            if (METHOD_IS_CONSTRUCTOR(method)) {
                impl = method->impl;
                // TODO: For now we make all constructors public to satisfy java.lang.reflect.Proxy. 
                access = ACC_PUBLIC;
                if (!addProxyMethod(env, proxyClass, method, access, impl)) return FALSE;
            } else {
                impl = _proxy0;
                if (METHOD_IS_PUBLIC(method)) { 
                    ProxyMethod* proxyMethod = hasMethod(env, proxyClass, method->name, method->desc);
                    if (rvmExceptionOccurred(env)) return FALSE;
                    if (!proxyMethod) {
                        proxyMethod = addProxyMethod(env, proxyClass, method, access, impl);
                        if (!proxyMethod) return FALSE;
                    }
                    // Record the lookup function in proxyClassData
                    LookupEntry* entry = rvmAllocateMemory(env, sizeof(LookupEntry));
                    if (!entry) return FALSE;
                    entry->key.name = method->name;
                    entry->key.desc = method->desc;
                    entry->method = proxyMethod;
                    HASH_ADD(hh, proxyClassData->lookupsHash, key, sizeof(LookupKey), entry);
                }
            }
        }
    }

    return TRUE;
}
Exemple #12
0
void rvmRegisterReference(Env* env, Object* reference, Object* referent) {
    if (referent) {
        // Add 'reference' to the references list for 'referent' in the referents hashtable
        rvmLockMutex(&referentsLock);

        ReferenceList* l = rvmAllocateMemory(env, sizeof(ReferenceList));
        if (!l) goto done; // OOM thrown
        l->reference = reference;
        ReferentEntry* referentEntry = getReferentEntryForObject(env, referent);
        if (!referentEntry) goto done;
        // Add the reference to the referent's list of references
        LL_PREPEND(referentEntry->references, l);
        // Register the referent for finalization
        GC_REGISTER_FINALIZER_NO_ORDER(referent, _finalizeObject, NULL, NULL, NULL);

done:
        rvmUnlockMutex(&referentsLock);
    }
}
Exemple #13
0
ProxyMethod* addProxyMethod(Env* env, Class* clazz, Method* proxiedMethod, jint access, void* impl) {
    ProxyMethod* method = rvmAllocateMemory(env, sizeof(ProxyMethod));
    if (!method) return NULL;
    method->method.clazz = clazz;
    method->method.name = proxiedMethod->name;
    method->method.desc = proxiedMethod->desc;
    method->method.access = access | METHOD_TYPE_PROXY;
    method->method.impl = impl;
    method->method.synchronizedImpl = NULL;
    method->proxiedMethod = proxiedMethod;

    if (clazz->_methods == &METHODS_NOT_LOADED) {
        clazz->_methods = NULL;
    }

    method->method.next = clazz->_methods;
    clazz->_methods = (Method*) method;

    return method;
}
Exemple #14
0
Method* rvmAddMethod(Env* env, Class* clazz, const char* name, const char* desc, jint access, jint size, void* impl, void* synchronizedImpl, void* attributes) {
    Method* method = rvmAllocateMemory(env, IS_NATIVE(access) ? sizeof(NativeMethod) : sizeof(Method));
    if (!method) return NULL;
    method->clazz = clazz;
    method->name = name;
    method->desc = desc;
    method->access = access;
    method->size = size;
    method->impl = impl;
    method->synchronizedImpl = synchronizedImpl;
    method->attributes = attributes;

    if (clazz->_methods == &METHODS_NOT_LOADED) {
        clazz->_methods = NULL;
    }

    method->next = clazz->_methods;
    clazz->_methods = method;

    return method;
}
Exemple #15
0
DynamicLib* rvmOpenDynamicLib(Env* env, const char* file, char** errorMsg) {
    *errorMsg = NULL;
    DynamicLib* dlib = NULL;

    void* handle = dlopen(file, RTLD_LOCAL | RTLD_LAZY);
    if (!handle) {
        *errorMsg = dlerror();
        TRACEF("Failed to load dynamic library '%s': %s", file, *errorMsg);
        return NULL;
    }

    TRACEF("Opening dynamic library '%s'", file);

    dlib = rvmAllocateMemory(env, sizeof(DynamicLib));
    if (!dlib) {
        dlclose(handle);
        return NULL;
    }

    dlib->handle = handle;

    return dlib;
}
Exemple #16
0
Field* rvmAddField(Env* env, Class* clazz, const char* name, const char* desc, jint access, jint offset, void* attributes) {
    Field* field = rvmAllocateMemory(env, IS_STATIC(access) ? sizeof(ClassField) : sizeof(InstanceField));
    if (!field) return NULL;
    field->clazz = clazz;
    field->name = name;
    field->desc = desc;
    field->access = access;
    field->attributes = attributes;

    if (clazz->_fields == &FIELDS_NOT_LOADED) {
        clazz->_fields = NULL;
    }

    field->next = clazz->_fields;
    clazz->_fields = field;

    if (access & ACC_STATIC) {
        ((ClassField*) field)->address = ((jbyte*) clazz) + offset;
    } else {
        ((InstanceField*) field)->offset = offset;
    }
    return field;
}
Exemple #17
0
BridgeMethod* rvmAddBridgeMethod(Env* env, Class* clazz, const char* name, const char* desc, jint access, jint size, void* impl, 
        void* synchronizedImpl, void** targetFnPtr, void* attributes) {
    
    BridgeMethod* method = rvmAllocateMemory(env, sizeof(BridgeMethod));
    if (!method) return NULL;
    method->method.clazz = clazz;
    method->method.name = name;
    method->method.desc = desc;
    method->method.access = access | METHOD_TYPE_BRIDGE;
    method->method.size = size;
    method->method.impl = impl;
    method->method.synchronizedImpl = synchronizedImpl;
    method->method.attributes = attributes;
    method->targetFnPtr = targetFnPtr;

    if (clazz->_methods == &METHODS_NOT_LOADED) {
        clazz->_methods = NULL;
    }

    method->method.next = clazz->_methods;
    clazz->_methods = (Method*) method;

    return method;
}
Exemple #18
0
CallbackMethod* rvmAddCallbackMethod(Env* env, Class* clazz, const char* name, const char* desc, jint access, jint size, void* impl, 
        void* synchronizedImpl, void* callbackImpl, void* attributes) {
    
    CallbackMethod* method = rvmAllocateMemory(env, sizeof(CallbackMethod));
    if (!method) return NULL;
    method->method.clazz = clazz;
    method->method.name = name;
    method->method.desc = desc;
    method->method.access = access | METHOD_TYPE_CALLBACK;
    method->method.size = size;
    method->method.impl = impl;
    method->method.synchronizedImpl = synchronizedImpl;
    method->method.attributes = attributes;
    method->callbackImpl = callbackImpl;

    if (clazz->_methods == &METHODS_NOT_LOADED) {
        clazz->_methods = NULL;
    }

    method->method.next = clazz->_methods;
    clazz->_methods = (Method*) method;

    return method;
}
Exemple #19
0
jlong Java_aura_rt_VM_allocateMemory(Env* env, Class* c, jint size) {
    return PTR_TO_LONG(rvmAllocateMemory(env, size));
}
Exemple #20
0
void _rvmProxyHandler(CallInfo* callInfo) {
    Env* env = (Env*) proxy0NextPtr(callInfo);
    Object* receiver = (Object*) proxy0NextPtr(callInfo);
    Class* proxyClass = receiver->clazz;
    ProxyClassData* proxyClassData = (ProxyClassData*) proxyClass->data;

    LookupKey key;
    memset(&key, 0, sizeof(LookupKey));
    key.name = (char*) env->reserved0;
    key.desc = (char*) env->reserved1;
    LookupEntry* entry;
    HASH_FIND(hh, proxyClassData->lookupsHash, &key, sizeof(LookupKey), entry);
    if (!entry) {
        rvmThrowNoSuchMethodError(env, "Failed to determine which method was called on proxy class");
        goto error;
    }

    ProxyMethod* method = entry->method;

    rvmPushGatewayFrameProxy(env, method);

    jint argsCount = rvmGetParameterCount((Method*) method);
    jvalue *jvalueArgs = NULL;
    if (argsCount > 0) {
        jvalueArgs = (jvalue*) rvmAllocateMemory(env, sizeof(jvalue) * argsCount);
        if (!jvalueArgs) goto errorPop;

        const char* desc = method->method.desc;
        const char* c;
        jint i = 0;
        while ((c = rvmGetNextParameterType(&desc))) {
            switch (c[0]) {
            case 'B':
                jvalueArgs[i++].b = (jbyte) proxy0NextInt(callInfo);
                break;
            case 'Z':
                jvalueArgs[i++].z = (jboolean) proxy0NextInt(callInfo);
                break;
            case 'S':
                jvalueArgs[i++].s = (jshort) proxy0NextInt(callInfo);
                break;
            case 'C':
                jvalueArgs[i++].c = (jchar) proxy0NextInt(callInfo);
                break;
            case 'I':
                jvalueArgs[i++].i = proxy0NextInt(callInfo);
                break;
            case 'J':
                jvalueArgs[i++].j = proxy0NextLong(callInfo);
                break;
            case 'F':
                jvalueArgs[i++].f = proxy0NextFloat(callInfo);
                break;
            case 'D':
                jvalueArgs[i++].d = proxy0NextDouble(callInfo);
                break;
            case '[':
            case 'L':
                jvalueArgs[i++].l = (jobject) proxy0NextPtr(callInfo);
                break;
            }
        }
    }

    jvalue returnValue;
    proxyClassData->handler(env, receiver, method, jvalueArgs, &returnValue);

    rvmPopGatewayFrame(env);

    if (rvmExceptionCheck(env)) goto error;

    proxy0ReturnInt(callInfo, 0);
    switch (rvmGetReturnType(method->method.desc)[0]) {
    case 'B':
        proxy0ReturnInt(callInfo, (jint) returnValue.b);
        break;
    case 'Z':
        proxy0ReturnInt(callInfo, (jint) returnValue.z);
        break;
    case 'S':
        proxy0ReturnInt(callInfo, (jint) returnValue.s);
        break;
    case 'C':
        proxy0ReturnInt(callInfo, (jint) returnValue.c);
        break;
    case 'I':
        proxy0ReturnInt(callInfo, returnValue.i);
        break;
    case 'J':
        proxy0ReturnLong(callInfo, returnValue.j);
        break;
    case 'F':
        proxy0ReturnFloat(callInfo, returnValue.f);
        break;
    case 'D':
        proxy0ReturnDouble(callInfo, returnValue.d);
        break;
    case '[':
    case 'L':
        proxy0ReturnPtr(callInfo, returnValue.l);
        break;
    }

    return;

errorPop:
    rvmPopGatewayFrame(env);
error:
    rvmRaiseException(env, rvmExceptionOccurred(env));
}
Exemple #21
0
void* rvmCopyMemory(Env* env, const void* src, jint size) {
    void* dest = rvmAllocateMemory(env, size);
    if (!dest) return NULL;
    memcpy(dest, src, size);
    return dest;
}
Exemple #22
0
static Thread* allocThread(Env* env) {
    Thread* thread = (Thread*) rvmAllocateMemory(env, sizeof(Thread));
    if (!thread) return NULL;
    thread->status = THREAD_INITIALIZING;
    return thread;
}