MVMCallsite *MVM_callsite_copy(MVMThreadContext *tc, const MVMCallsite *cs) { MVMCallsite *copy = MVM_malloc(sizeof(MVMCallsite)); if (cs->flag_count) { copy->arg_flags = MVM_malloc(cs->flag_count); memcpy(copy->arg_flags, cs->arg_flags, cs->flag_count); } if (cs->arg_names) { MVMint32 num_named = MVM_callsite_num_nameds(tc, cs); copy->arg_names = MVM_malloc(num_named * sizeof(MVMString *)); memcpy(copy->arg_names, cs->arg_names, num_named * sizeof(MVMString *)); } else { copy->arg_names = NULL; } if (cs->with_invocant) { copy->with_invocant = MVM_callsite_copy(tc, cs->with_invocant); } else { copy->with_invocant = NULL; } copy->flag_count = cs->flag_count; copy->arg_count = cs->arg_count; copy->num_pos = cs->num_pos; copy->has_flattening = cs->has_flattening; copy->is_interned = cs->is_interned; return copy; }
/* Initialize arguments processing context. */ void MVM_args_proc_init(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMCallsite *callsite, MVMRegister *args) { /* Stash callsite and argument counts/pointers. */ ctx->callsite = callsite; /* initial counts and values; can be altered by flatteners */ init_named_used(tc, ctx, MVM_callsite_num_nameds(tc, callsite)); ctx->args = args; ctx->num_pos = callsite->num_pos; ctx->arg_count = callsite->arg_count; ctx->arg_flags = NULL; /* will be populated by flattener if needed */ }
/* Tries to intern the callsite, freeing and updating the one passed in and * replacing it with an already interned one if we find it. */ MVM_PUBLIC void MVM_callsite_try_intern(MVMThreadContext *tc, MVMCallsite **cs_ptr) { MVMCallsiteInterns *interns = tc->instance->callsite_interns; MVMCallsite *cs = *cs_ptr; MVMint32 num_flags = cs->flag_count; MVMint32 num_nameds = MVM_callsite_num_nameds(tc, cs); MVMint32 i, found; /* Can't intern anything with flattening. */ if (cs->has_flattening) return; /* Also can't intern past the max arity. */ if (num_flags >= MVM_INTERN_ARITY_LIMIT) return; /* Can intern things with nameds, provided we know the names. */ if (num_nameds > 0 && !cs->arg_names) return; /* Obtain mutex protecting interns store. */ uv_mutex_lock(&tc->instance->mutex_callsite_interns); /* Search for a match. */ found = 0; for (i = 0; i < interns->num_by_arity[num_flags]; i++) { if (callsites_equal(tc, interns->by_arity[num_flags][i], cs, num_flags, num_nameds)) { /* Got a match! Free the one we were passed and replace it with * the interned one. */ if (num_flags) MVM_free(cs->arg_flags); MVM_free(cs->arg_names); MVM_free(cs); *cs_ptr = interns->by_arity[num_flags][i]; found = 1; break; } } /* If it wasn't found, store it for the future. */ if (!found) { if (interns->num_by_arity[num_flags] % 8 == 0) { if (interns->num_by_arity[num_flags]) interns->by_arity[num_flags] = MVM_realloc( interns->by_arity[num_flags], sizeof(MVMCallsite *) * (interns->num_by_arity[num_flags] + 8)); else interns->by_arity[num_flags] = MVM_malloc(sizeof(MVMCallsite *) * 8); } interns->by_arity[num_flags][interns->num_by_arity[num_flags]++] = cs; cs->is_interned = 1; } /* Finally, release mutex. */ uv_mutex_unlock(&tc->instance->mutex_callsite_interns); }