static void callVoidMethod(Env* env, CallInfo* callInfo) { void (*f)(CallInfo*) = _call0; rvmPushGatewayFrame(env); TrycatchContext tc = {0}; tc.sel = CATCH_ALL_SEL; if (!rvmTrycatchEnter(env, &tc)) { f(callInfo); } rvmTrycatchLeave(env); rvmPopGatewayFrame(env); }
void _bcHookInstrumented(DebugEnv* debugEnv, jint lineNumber, jint lineNumberOffset, jbyte* bptable, void* pc) { Env* env = (Env*) debugEnv; // Temporarily clear any exception that has been thrown. Could be the case if we are called from a catch block. Object* throwable = rvmExceptionClear(env); // We cannot use ENTER/LEAVEV as it will raise any exception thrown in here. We just want the code to // proceed normally after we return. rvmPushGatewayFrame(env); rvmHookInstrumented(debugEnv, lineNumber, lineNumberOffset, bptable, pc); rvmPopGatewayFrame(env); // Restore the exception if one had been thrown when this function was called. env->throwable = throwable; }
static jdouble callDoubleMethod(Env* env, CallInfo* callInfo) { jdouble result = 0; jdouble (*f)(CallInfo*) = (jdouble (*)(CallInfo*)) _call0; rvmPushGatewayFrame(env); TrycatchContext tc = {0}; tc.sel = CATCH_ALL_SEL; if (!rvmTrycatchEnter(env, &tc)) { result = f(callInfo); } rvmTrycatchLeave(env); rvmPopGatewayFrame(env); return result; }
static jboolean callBooleanMethod(Env* env, CallInfo* callInfo) { jboolean result = FALSE; jboolean (*f)(CallInfo*) = (jboolean (*)(CallInfo*)) _call0; rvmPushGatewayFrame(env); TrycatchContext tc = {0}; tc.sel = CATCH_ALL_SEL; if (!rvmTrycatchEnter(env, &tc)) { result = f(callInfo); } rvmTrycatchLeave(env); rvmPopGatewayFrame(env); return result; }
static Object* callObjectMethod(Env* env, CallInfo* callInfo) { Object* result = NULL; Object* (*f)(CallInfo*) = (Object* (*)(CallInfo*)) _call0; rvmPushGatewayFrame(env); TrycatchContext tc = {0}; tc.sel = CATCH_ALL_SEL; if (!rvmTrycatchEnter(env, &tc)) { result = f(callInfo); } rvmTrycatchLeave(env); rvmPopGatewayFrame(env); return result; }
void _bcPopCallbackFrame(Env* env) { rvmPopGatewayFrame(env); }
void _bcPopNativeFrame(Env* env) { rvmPopGatewayFrame(env); }
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)); }
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(); }