Skip to content

Commit

Permalink
Avoid boxing native call results if native type is requested
Browse files Browse the repository at this point in the history
  • Loading branch information
niner authored and nwc10 committed Nov 6, 2021
1 parent 6b6eb9a commit de63d17
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 78 deletions.
5 changes: 2 additions & 3 deletions src/core/interp.c
Expand Up @@ -6539,10 +6539,9 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
MVMObject *result_type = GET_REG(cur_op, 12).o;
tc->cur_frame->return_value = &GET_REG(cur_op, 0);
tc->cur_frame->return_type = MVM_RETURN_OBJ;
ptrdiff_t opcode_length = 12 + 2 * args.callsite->flag_count;
cur_op += opcode_length;
cur_op += 12 + 2 * args.callsite->flag_count;
tc->cur_frame->return_address = cur_op;
GET_REG(cur_op, -opcode_length).o = MVM_nativecall_dispatch(tc, result_type, site, args);
MVM_nativecall_dispatch(tc, result_type, site, args);
goto NEXT;
}
OP(sp_resumption):
Expand Down
2 changes: 1 addition & 1 deletion src/core/nativecall.h
Expand Up @@ -96,7 +96,7 @@ void MVM_nativecall_setup(MVMThreadContext *tc, MVMNativeCallBody *body, unsigne
void MVM_nativecall_restore_library(MVMThreadContext *tc, MVMNativeCallBody *body, MVMObject *root);
MVMObject * MVM_nativecall_invoke(MVMThreadContext *tc, MVMObject *res_type,
MVMObject *site, MVMObject *args);
MVMObject * MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
void MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
MVMObject *site, MVMArgs args);
void MVM_nativecall_invoke_jit(MVMThreadContext *tc, MVMObject *site);
MVMObject * MVM_nativecall_global(MVMThreadContext *tc, MVMString *lib, MVMString *sym,
Expand Down
168 changes: 99 additions & 69 deletions src/core/nativecall_dyncall.c
Expand Up @@ -821,7 +821,65 @@ MVMObject * MVM_nativecall_invoke(MVMThreadContext *tc, MVMObject *res_type,
return result;
}

MVMObject * MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
static void update_rws(MVMThreadContext *tc, void **free_rws, MVMint16 num_args, MVMint16 *arg_types, MVMArgs args, unsigned int interval_id) {
MVMint16 i, num_rws = 0;
for (i = 0; i < num_args; i++) {
MVMObject *value = args.source[args.map[i + 1]].o;
if ((arg_types[i] & MVM_NATIVECALL_ARG_RW_MASK) == MVM_NATIVECALL_ARG_RW) {
switch (arg_types[i] & MVM_NATIVECALL_ARG_TYPE_MASK) {
case MVM_NATIVECALL_ARG_CHAR:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCchar *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_SHORT:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCshort *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_INT:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCint *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_LONG:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DClong *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_LONGLONG:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DClonglong *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_FLOAT:
MVM_6model_container_assign_n(tc, value, (MVMnum64)*(DCfloat *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_DOUBLE:
MVM_6model_container_assign_n(tc, value, (MVMnum64)*(DCdouble *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_UCHAR:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCuchar *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_USHORT:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCushort *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_UINT:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCuint *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_ULONG:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCulong *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_ULONGLONG:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCulonglong *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_CPOINTER:
REPR(value)->box_funcs.set_int(tc, STABLE(value), value, OBJECT_BODY(value),
(MVMint64)*(DCpointer *)free_rws[num_rws]);
break;
default:
MVM_telemetry_interval_stop(tc, interval_id, "nativecall invoke failed");
MVM_exception_throw_adhoc(tc, "Internal error: unhandled dyncall argument type");
}
num_rws++;
}
/* Perform CArray/CStruct write barriers. */
if (args.callsite->arg_flags[i + 1] & MVM_CALLSITE_ARG_OBJ)
MVM_nativecall_refresh(tc, value);
}
}

void MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
MVMObject *site, MVMArgs args) {
MVMObject *result = NULL;
char **free_strs = NULL;
Expand Down Expand Up @@ -1059,6 +1117,7 @@ MVMObject * MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
/* We are calling a C++ constructor so we hand back the invocant (THIS) we recorded earlier. */
dcCallVoid(vm, body->entry_point);
MVM_gc_mark_thread_unblocked(tc);
MVM_args_set_dispatch_result_obj(tc, tc->cur_frame, result);
}
else {
/* Call and process return values. */
Expand All @@ -1067,47 +1126,55 @@ MVMObject * MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
dcCallVoid(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = res_type;
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
break;
case MVM_NATIVECALL_ARG_CHAR: {
MVMint64 native_result = (signed char)dcCallChar(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_int(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_SHORT: {
MVMint64 native_result = dcCallShort(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_int(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_INT: {
MVMint64 native_result = dcCallInt(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_int(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_LONG: {
MVMint64 native_result = dcCallLong(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_int(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_LONGLONG: {
MVMint64 native_result = dcCallLongLong(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_int(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_FLOAT: {
MVMnum64 native_result = dcCallFloat(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_num(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_num(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_DOUBLE: {
MVMnum64 native_result = dcCallDouble(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_num(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_num(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_ASCIISTR:
Expand All @@ -1117,36 +1184,48 @@ MVMObject * MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_str(tc, res_type, body->ret_type,
native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_obj(tc, tc->cur_frame, result);
break;
}
case MVM_NATIVECALL_ARG_CSTRUCT: {
void *native_result = dcCallPointer(vm, body->entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_cstruct(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_obj(tc, tc->cur_frame, result);
break;
}
case MVM_NATIVECALL_ARG_CPPSTRUCT: {
void *native_result = dcCallPointer(vm, body->entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_cppstruct(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_obj(tc, tc->cur_frame, result);
break;
}
case MVM_NATIVECALL_ARG_CPOINTER: {
void *native_result = dcCallPointer(vm, body->entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_cpointer(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_obj(tc, tc->cur_frame, result);
break;
}
case MVM_NATIVECALL_ARG_CARRAY: {
void *native_result = dcCallPointer(vm, body->entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_carray(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_obj(tc, tc->cur_frame, result);
break;
}
case MVM_NATIVECALL_ARG_CUNION: {
void *native_result = dcCallPointer(vm, body->entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_cunion(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_obj(tc, tc->cur_frame, result);
break;
}
case MVM_NATIVECALL_ARG_CALLBACK:
Expand All @@ -1156,35 +1235,42 @@ MVMObject * MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
dcCallPointer(vm, body->entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = res_type;
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_obj(tc, tc->cur_frame, result);
break;
case MVM_NATIVECALL_ARG_UCHAR: {
MVMuint64 native_result = (DCuchar)dcCallChar(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_uint(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_USHORT: {
MVMuint64 native_result = (DCushort)dcCallShort(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_uint(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_UINT: {
MVMuint64 native_result = (DCuint)dcCallInt(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_uint(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_ULONG: {
MVMuint64 native_result = (DCulong)dcCallLong(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_uint(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
case MVM_NATIVECALL_ARG_ULONGLONG: {
MVMuint64 native_result = (DCulonglong)dcCallLongLong(vm, entry_point);
MVM_gc_mark_thread_unblocked(tc);
result = MVM_nativecall_make_uint(tc, res_type, native_result);
update_rws(tc, free_rws, num_args, arg_types, args, interval_id);
MVM_args_set_dispatch_result_int(tc, tc->cur_frame, native_result);
break;
}
default:
Expand All @@ -1195,61 +1281,6 @@ MVMObject * MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
}
});

num_rws = 0;
for (i = 0; i < num_args; i++) {
MVMObject *value = args.source[args.map[i + 1]].o;
if ((arg_types[i] & MVM_NATIVECALL_ARG_RW_MASK) == MVM_NATIVECALL_ARG_RW) {
switch (arg_types[i] & MVM_NATIVECALL_ARG_TYPE_MASK) {
case MVM_NATIVECALL_ARG_CHAR:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCchar *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_SHORT:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCshort *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_INT:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCint *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_LONG:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DClong *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_LONGLONG:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DClonglong *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_FLOAT:
MVM_6model_container_assign_n(tc, value, (MVMnum64)*(DCfloat *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_DOUBLE:
MVM_6model_container_assign_n(tc, value, (MVMnum64)*(DCdouble *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_UCHAR:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCuchar *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_USHORT:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCushort *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_UINT:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCuint *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_ULONG:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCulong *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_ULONGLONG:
MVM_6model_container_assign_i(tc, value, (MVMint64)*(DCulonglong *)free_rws[num_rws]);
break;
case MVM_NATIVECALL_ARG_CPOINTER:
REPR(value)->box_funcs.set_int(tc, STABLE(value), value, OBJECT_BODY(value),
(MVMint64)*(DCpointer *)free_rws[num_rws]);
break;
default:
MVM_telemetry_interval_stop(tc, interval_id, "nativecall invoke failed");
MVM_exception_throw_adhoc(tc, "Internal error: unhandled dyncall argument type");
}
num_rws++;
}
/* Perform CArray/CStruct write barriers. */
if (args.callsite->arg_flags[i + 1] & MVM_CALLSITE_ARG_OBJ)
MVM_nativecall_refresh(tc, value);
}

/* Free any memory that we need to. */
if (free_strs) {
Expand All @@ -1268,5 +1299,4 @@ MVMObject * MVM_nativecall_dispatch(MVMThreadContext *tc, MVMObject *res_type,
dcFree(vm);

MVM_telemetry_interval_stop(tc, interval_id, "nativecall invoke");
return result;
}

0 comments on commit de63d17

Please sign in to comment.