char handler(DCCallback* that, DCArgs* input, DCValue* output, void* userdata) { const char* signature = (const char*) userdata; int pos = 0; char ch; signature = SignatureSkipCallPrefix(signature); for(;;) { ch = *signature++; if (ch == DC_SIGCHAR_ENDARG) break; Args[pos].L = 0xDEADC0DECAFEBABELL; switch(ch) { case DC_SIGCHAR_BOOL: Args[pos].B = dcbArgBool (input); break; case DC_SIGCHAR_CHAR: Args[pos].c = dcbArgChar (input); break; case DC_SIGCHAR_UCHAR: Args[pos].C = dcbArgUChar (input); break; case DC_SIGCHAR_SHORT: Args[pos].s = dcbArgShort (input); break; case DC_SIGCHAR_USHORT: Args[pos].S = dcbArgUShort (input); break; case DC_SIGCHAR_INT: Args[pos].i = dcbArgInt (input); break; case DC_SIGCHAR_UINT: Args[pos].I = dcbArgUInt (input); break; case DC_SIGCHAR_LONG: Args[pos].j = dcbArgLong (input); break; case DC_SIGCHAR_ULONG: Args[pos].J = dcbArgULong (input); break; case DC_SIGCHAR_LONGLONG: Args[pos].l = dcbArgLongLong (input); break; case DC_SIGCHAR_ULONGLONG:Args[pos].L = dcbArgULongLong(input); break; case DC_SIGCHAR_FLOAT: Args[pos].f = dcbArgFloat (input); break; case DC_SIGCHAR_DOUBLE: Args[pos].d = dcbArgDouble (input); break; case DC_SIGCHAR_POINTER: Args[pos].p = dcbArgPointer (input); break; } ++pos; } ch = *signature++; /* currently, no void result is supported by the suite */ GetReferenceResult(output, ch); switch(ch) { case DC_SIGCHAR_BOOL: return 'B'; case DC_SIGCHAR_CHAR: return 'c'; case DC_SIGCHAR_UCHAR: return 'C'; case DC_SIGCHAR_SHORT: return 's'; case DC_SIGCHAR_USHORT: return 'S'; case DC_SIGCHAR_INT: return 'i'; case DC_SIGCHAR_UINT: return 'I'; case DC_SIGCHAR_LONG: return 'j'; case DC_SIGCHAR_ULONG: return 'J'; case DC_SIGCHAR_LONGLONG: return 'l'; case DC_SIGCHAR_ULONGLONG:return 'l'; case DC_SIGCHAR_FLOAT: return 'f'; case DC_SIGCHAR_DOUBLE: return 'd'; case DC_SIGCHAR_POINTER: return 'p'; default: assert(0); return 'v'; } }
static char callback_handler(DCCallback *cb, DCArgs *cb_args, DCValue *cb_result, MVMNativeCallback *data) { CallbackInvokeData cid; MVMint32 num_roots, i; MVMRegister res; /* Build a callsite and arguments buffer. */ MVMThreadContext *tc = data->tc; MVMRegister *args = MVM_malloc(data->num_types * sizeof(MVMRegister)); num_roots = 0; for (i = 1; i < data->num_types; i++) { MVMObject *type = data->types[i]; MVMint16 typeinfo = data->typeinfos[i]; switch (typeinfo & MVM_NATIVECALL_ARG_TYPE_MASK) { case MVM_NATIVECALL_ARG_CHAR: args[i - 1].i64 = dcbArgChar(cb_args); break; case MVM_NATIVECALL_ARG_SHORT: args[i - 1].i64 = dcbArgShort(cb_args); break; case MVM_NATIVECALL_ARG_INT: args[i - 1].i64 = dcbArgInt(cb_args); break; case MVM_NATIVECALL_ARG_LONG: args[i - 1].i64 = dcbArgLong(cb_args); break; case MVM_NATIVECALL_ARG_LONGLONG: args[i - 1].i64 = dcbArgLongLong(cb_args); break; case MVM_NATIVECALL_ARG_FLOAT: args[i - 1].n64 = dcbArgFloat(cb_args); break; case MVM_NATIVECALL_ARG_DOUBLE: args[i - 1].n64 = dcbArgDouble(cb_args); break; case MVM_NATIVECALL_ARG_ASCIISTR: case MVM_NATIVECALL_ARG_UTF8STR: case MVM_NATIVECALL_ARG_UTF16STR: args[i - 1].o = MVM_nativecall_make_str(tc, type, typeinfo, (char *)dcbArgPointer(cb_args)); MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o)); num_roots++; break; case MVM_NATIVECALL_ARG_CSTRUCT: args[i - 1].o = MVM_nativecall_make_cstruct(tc, type, dcbArgPointer(cb_args)); MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o)); num_roots++; break; case MVM_NATIVECALL_ARG_CPOINTER: args[i - 1].o = MVM_nativecall_make_cpointer(tc, type, dcbArgPointer(cb_args)); MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o)); num_roots++; break; case MVM_NATIVECALL_ARG_CARRAY: args[i - 1].o = MVM_nativecall_make_carray(tc, type, dcbArgPointer(cb_args)); MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o)); num_roots++; break; case MVM_NATIVECALL_ARG_CUNION: args[i - 1].o = MVM_nativecall_make_cunion(tc, type, dcbArgPointer(cb_args)); MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o)); num_roots++; break; case MVM_NATIVECALL_ARG_CALLBACK: /* TODO: A callback -return- value means that we have a C method * that needs to be wrapped similarly to a is native(...) Perl 6 * sub. */ dcbArgPointer(cb_args); args[i - 1].o = type; MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o)); num_roots++; case MVM_NATIVECALL_ARG_UCHAR: args[i - 1].i64 = dcbArgUChar(cb_args); break; case MVM_NATIVECALL_ARG_USHORT: args[i - 1].i64 = dcbArgUShort(cb_args); break; case MVM_NATIVECALL_ARG_UINT: args[i - 1].i64 = dcbArgUInt(cb_args); break; case MVM_NATIVECALL_ARG_ULONG: args[i - 1].i64 = dcbArgULong(cb_args); break; case MVM_NATIVECALL_ARG_ULONGLONG: args[i - 1].i64 = dcbArgULongLong(cb_args); break; default: MVM_exception_throw_adhoc(tc, "Internal error: unhandled dyncall callback argument type"); } } /* Call into a nested interpreter (since we already are in one). Need to * save a bunch of state around each side of this. */ cid.invokee = data->target; cid.args = args; cid.cs = data->cs; { MVMuint8 **backup_interp_cur_op = tc->interp_cur_op; MVMuint8 **backup_interp_bytecode_start = tc->interp_bytecode_start; MVMRegister **backup_interp_reg_base = tc->interp_reg_base; MVMCompUnit **backup_interp_cu = tc->interp_cu; MVMFrame *backup_cur_frame = tc->cur_frame; MVMFrame *backup_thread_entry_frame = tc->thread_entry_frame; MVMuint32 backup_mark = MVM_gc_root_temp_mark(tc); jmp_buf backup_interp_jump; memcpy(backup_interp_jump, tc->interp_jump, sizeof(jmp_buf)); tc->cur_frame->return_value = &res; tc->cur_frame->return_type = MVM_RETURN_OBJ; MVM_interp_run(tc, &callback_invoke, &cid); tc->interp_cur_op = backup_interp_cur_op; tc->interp_bytecode_start = backup_interp_bytecode_start; tc->interp_reg_base = backup_interp_reg_base; tc->interp_cu = backup_interp_cu; tc->cur_frame = backup_cur_frame; tc->thread_entry_frame = backup_thread_entry_frame; memcpy(tc->interp_jump, backup_interp_jump, sizeof(jmp_buf)); MVM_gc_root_temp_mark_reset(tc, backup_mark); } /* Handle return value. */ if (res.o) { MVMContainerSpec const *contspec = STABLE(res.o)->container_spec; if (contspec && contspec->fetch_never_invokes) contspec->fetch(data->tc, res.o, &res); } switch (data->typeinfos[0] & MVM_NATIVECALL_ARG_TYPE_MASK) { case MVM_NATIVECALL_ARG_VOID: break; case MVM_NATIVECALL_ARG_CHAR: cb_result->c = MVM_nativecall_unmarshal_char(data->tc, res.o); break; case MVM_NATIVECALL_ARG_SHORT: cb_result->s = MVM_nativecall_unmarshal_short(data->tc, res.o); break; case MVM_NATIVECALL_ARG_INT: cb_result->i = MVM_nativecall_unmarshal_int(data->tc, res.o); break; case MVM_NATIVECALL_ARG_LONG: cb_result->j = MVM_nativecall_unmarshal_long(data->tc, res.o); break; case MVM_NATIVECALL_ARG_LONGLONG: cb_result->l = MVM_nativecall_unmarshal_longlong(data->tc, res.o); break; case MVM_NATIVECALL_ARG_FLOAT: cb_result->f = MVM_nativecall_unmarshal_float(data->tc, res.o); break; case MVM_NATIVECALL_ARG_DOUBLE: cb_result->d = MVM_nativecall_unmarshal_double(data->tc, res.o); break; case MVM_NATIVECALL_ARG_ASCIISTR: case MVM_NATIVECALL_ARG_UTF8STR: case MVM_NATIVECALL_ARG_UTF16STR: cb_result->Z = MVM_nativecall_unmarshal_string(data->tc, res.o, data->typeinfos[0], NULL); break; case MVM_NATIVECALL_ARG_CSTRUCT: cb_result->p = MVM_nativecall_unmarshal_cstruct(data->tc, res.o); break; case MVM_NATIVECALL_ARG_CPOINTER: cb_result->p = MVM_nativecall_unmarshal_cpointer(data->tc, res.o); break; case MVM_NATIVECALL_ARG_CARRAY: cb_result->p = MVM_nativecall_unmarshal_carray(data->tc, res.o); break; case MVM_NATIVECALL_ARG_CUNION: cb_result->p = MVM_nativecall_unmarshal_cunion(data->tc, res.o); break; case MVM_NATIVECALL_ARG_VMARRAY: cb_result->p = MVM_nativecall_unmarshal_vmarray(data->tc, res.o); break; case MVM_NATIVECALL_ARG_CALLBACK: cb_result->p = unmarshal_callback(data->tc, res.o, data->types[0]); break; case MVM_NATIVECALL_ARG_UCHAR: cb_result->c = MVM_nativecall_unmarshal_uchar(data->tc, res.o); break; case MVM_NATIVECALL_ARG_USHORT: cb_result->s = MVM_nativecall_unmarshal_ushort(data->tc, res.o); break; case MVM_NATIVECALL_ARG_UINT: cb_result->i = MVM_nativecall_unmarshal_uint(data->tc, res.o); break; case MVM_NATIVECALL_ARG_ULONG: cb_result->j = MVM_nativecall_unmarshal_ulong(data->tc, res.o); break; case MVM_NATIVECALL_ARG_ULONGLONG: cb_result->l = MVM_nativecall_unmarshal_ulonglong(data->tc, res.o); break; default: MVM_exception_throw_adhoc(data->tc, "Internal error: unhandled dyncall callback return type"); } /* Clean up. */ MVM_gc_root_temp_pop_n(tc, num_roots); MVM_free(args); /* Indicate what we're producing as a result. */ return get_signature_char(data->typeinfos[0]); }
DCpointer dcbArgPointer (DCArgs* p) { return (DCpointer) dcbArgLong(p); }
DCulong dcbArgULong (DCArgs* p) { return (DCulong) dcbArgLong(p); }
DCbool dcbArgBool (DCArgs* p) { return (dcbArgLong(p) == 0) ? 0 : 1; }
DCshort dcbArgShort (DCArgs* p) { return (DCshort) dcbArgLong(p); }
DCchar dcbArgChar (DCArgs* p) { return (DCchar) dcbArgLong(p); }
DCint dcbArgInt (DCArgs* p) { return (DCint) dcbArgLong(p); }
jboolean followArgsGenericJavaCallback(CallTempStruct* call, DCArgs* args, int nTypes, ValueType* pTypes) { JNIEnv* env = call->env; int iParam; jobjectArray arr = (*env)->NewObjectArray(env, nTypes, gObjectClass, NULL); for (iParam = 0; iParam < nTypes; iParam++) { ValueType type = pTypes[iParam]; jobject arg = NULL; switch (type) { case eIntFlagSet: arg = BoxInt(env, (jint)getFlagValue(env, (jobject)dcbArgPointer(args))); break; case eIntValue: arg = BoxInt(env, dcbArgInt(args)); break; case eCLongValue: { jlong v; if (sizeof(long) == 4) v = dcbArgLong(args); else v = dcbArgLongLong(args); arg = BoxCLong(env, v); break; } case eSizeTValue: { jlong v; if (sizeof(size_t) == 4) v = dcbArgInt(args); else v = dcbArgLongLong(args); arg = BoxSizeT(env, v); break; } case eLongValue: arg = BoxLong(env, dcbArgLongLong(args)); break; case eShortValue: arg = BoxShort(env, dcbArgShort(args)); break; case eBooleanValue: case eByteValue: arg = BoxByte(env, dcbArgChar(args)); break; case eFloatValue: arg = BoxFloat(env, dcbArgFloat(args)); break; case eDoubleValue: arg = BoxDouble(env, dcbArgDouble(args)); break; case ePointerValue: { jobject callIO = call && call->pCallIOs ? *(call->pCallIOs++) : NULL; void* ptr = dcbArgPointer(args); arg = createPointerFromIO(env, ptr, callIO); } break; case eWCharValue: switch (sizeof(wchar_t)) { case 1: arg = BoxChar(env, dcbArgChar(args)); break; case 2: arg = BoxChar(env, dcbArgShort(args)); break; case 4: arg = BoxInt(env, dcbArgInt(args)); break; default: throwException(env, "Invalid wchar_t size for argument !"); return JNI_FALSE; } break; default: throwException(env, "Invalid argument value type !"); return JNI_FALSE; } (*env)->SetObjectArrayElement(env, arr, iParam, arg); } dcArgPointer(call->vm, arr); if ((*env)->ExceptionCheck(env)) return JNI_FALSE; return JNI_TRUE; }