/* Container for arguments being passed to something to invoke it. */ struct MVMArgs { /* The callsite that describes the arguments. */ MVMCallsite *callsite; /* A buffer we can obtain the arguments from. This is not a contiguous * list of arguments (at least, not in the common case!) In most cases, * it is the work area of the caller. */ MVMRegister *source; /* A mapping array from argument number (according to flag index in the * callsite) to index in the source. Typically, this is a pointer into * the register list in the `dispatch` instruction. Thus to access arg 0 * we'd do source[map[0]]. */ MVMuint16 *map; }; #define MVM_ARGS_SMALL_IDENTITY_MAP_SIZE 256 #define MVM_ARGS_LIMIT 0xFFFF /* Argument processing context. */ struct MVMArgProcContext { /* The incoming arguments to bind. */ MVMArgs arg_info; /* Indexes of used nameds. If named_used_size is less than or equal to * 64, it will be a bit field. Otherwise, it will be a pointer to a * byte array. */ union { MVMuint8 *byte_array; MVMuint64 bit_field; } named_used; MVMuint16 named_used_size; }; /* Expected return type flags. */ typedef MVMuint8 MVMReturnType; #define MVM_RETURN_VOID 0 #define MVM_RETURN_OBJ 1 #define MVM_RETURN_INT 2 #define MVM_RETURN_NUM 4 #define MVM_RETURN_STR 8 #define MVM_RETURN_UINT 32 /* When the thing returned to is "smart", like the debugserver, * set not only the return value but also the type depending on * which return_* op was used. */ #define MVM_RETURN_ALLOMORPH 16 /* Struct used for returning information about an argument. */ struct MVMArgInfo { MVMRegister arg; MVMCallsiteEntry flags; MVMuint8 exists; MVMuint16 arg_idx; /* Set only for nameds, obvious for pos */ }; /* Initialize arguments processing context. */ MVM_STATIC_INLINE void MVM_args_proc_setup(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMArgs arg_info) { ctx->arg_info = arg_info; MVMuint16 num_nameds = arg_info.callsite->flag_count - arg_info.callsite->num_pos; ctx->named_used_size = num_nameds; if (MVM_UNLIKELY(num_nameds > 64)) ctx->named_used.byte_array = MVM_calloc(1, num_nameds); else ctx->named_used.bit_field = 0; } /* Clean up an arguments processing context. */ MVM_STATIC_INLINE void MVM_args_proc_cleanup(MVMThreadContext *tc, MVMArgProcContext *ctx) { if (ctx->named_used_size > 64) { MVM_free(ctx->named_used.byte_array); ctx->named_used_size = 0; } } /* Argument processing context handling. */ void MVM_args_setup_identity_map(MVMThreadContext *tc); void MVM_args_grow_identity_map(MVMThreadContext *tc, MVMCallsite *callsite); MVM_STATIC_INLINE MVMuint16 * MVM_args_identity_map(MVMThreadContext *tc, MVMCallsite *callsite) { if (callsite->flag_count > tc->instance->identity_arg_map_alloc) MVM_args_grow_identity_map(tc, callsite); return tc->instance->identity_arg_map; } void MVM_args_destroy_identity_map(MVMThreadContext *tc); MVMCallStackFlattening * MVM_args_perform_flattening(MVMThreadContext *tc, MVMCallsite *cs, MVMRegister *source, MVMuint16 *map); /* Arity checking and named handling. */ void MVM_args_checkarity(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint16 min, MVMuint16 max); void MVM_args_checkarity_for_jit(MVMThreadContext *tc, MVMuint16 min, MVMuint16 max); void MVM_args_marked_named_used(MVMThreadContext *tc, MVMuint32 idx); void MVM_args_throw_named_unused_error(MVMThreadContext *tc, MVMString *name); /* Argument access by position. */ MVMObject * MVM_args_get_required_pos_obj(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMArgInfo MVM_args_get_optional_pos_obj(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMint64 MVM_args_get_required_pos_int(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMArgInfo MVM_args_get_optional_pos_int(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMnum64 MVM_args_get_required_pos_num(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMArgInfo MVM_args_get_optional_pos_num(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMString * MVM_args_get_required_pos_str(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMArgInfo MVM_args_get_optional_pos_str(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMuint64 MVM_args_get_required_pos_uint(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMArgInfo MVM_args_get_optional_pos_uint(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint32 pos); MVMObject * MVM_args_slurpy_positional(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint16 pos); /* Argument access by name. */ MVMArgInfo MVM_args_get_named_obj(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMString *name, MVMuint8 required); MVMArgInfo MVM_args_get_named_int(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMString *name, MVMuint8 required); MVMArgInfo MVM_args_get_named_num(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMString *name, MVMuint8 required); MVMArgInfo MVM_args_get_named_str(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMString *name, MVMuint8 required); MVMArgInfo MVM_args_get_named_uint(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMString *name, MVMuint8 required); MVMObject * MVM_args_slurpy_named(MVMThreadContext *tc, MVMArgProcContext *ctx); MVMint64 MVM_args_has_named(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMString *name); void MVM_args_assert_nameds_used(MVMThreadContext *tc, MVMArgProcContext *ctx); /* Result setting. */ void MVM_args_set_result_obj(MVMThreadContext *tc, MVMObject *result, MVMint32 frameless); void MVM_args_set_result_int(MVMThreadContext *tc, MVMint64 result, MVMint32 frameless); void MVM_args_set_result_uint(MVMThreadContext *tc, MVMuint64 result, MVMint32 frameless); void MVM_args_set_result_num(MVMThreadContext *tc, MVMnum64 result, MVMint32 frameless); void MVM_args_set_result_str(MVMThreadContext *tc, MVMString *result, MVMint32 frameless); void MVM_args_assert_void_return_ok(MVMThreadContext *tc, MVMint32 frameless); void MVM_args_set_dispatch_result_obj(MVMThreadContext *tc, MVMFrame *target, MVMObject *result); void MVM_args_set_dispatch_result_int(MVMThreadContext *tc, MVMFrame *target, MVMint64 result); void MVM_args_set_dispatch_result_uint(MVMThreadContext *tc, MVMFrame *target, MVMuint64 result); void MVM_args_set_dispatch_result_num(MVMThreadContext *tc, MVMFrame *target, MVMnum64 result); void MVM_args_set_dispatch_result_str(MVMThreadContext *tc, MVMFrame *target, MVMString *result); /* Capture handling. */ MVMCallsite * MVM_args_copy_callsite(MVMThreadContext *tc, MVMArgProcContext *ctx); MVM_PUBLIC MVMObject * MVM_args_use_capture(MVMThreadContext *tc, MVMFrame *f); MVM_PUBLIC MVMObject * MVM_args_save_capture(MVMThreadContext *tc, MVMFrame *f); /* Custom bind failure/success handling. */ void MVM_args_bind_failed(MVMThreadContext *tc, MVMDispInlineCacheEntry **ice_ptr); void MVM_args_bind_succeeded(MVMThreadContext *tc, MVMDispInlineCacheEntry **ice_ptr); /* Result setting frame constants. */ #define MVM_RETURN_CALLER_FRAME 0 #define MVM_RETURN_CURRENT_FRAME 1 /* Required/optional constants. */ #define MVM_ARG_OPTIONAL 0 #define MVM_ARG_REQUIRED 1