PARROT_WARN_UNUSED_RESULT PARROT_CANNOT_RETURN_NULL opcode_t * blizkost_return_from_invoke(PARROT_INTERP, void *next) { /* The following code is cargo culted from nci.pmc */ PMC *cont = interp->current_cont; /* * If the NCI function was tailcalled, the return result * is already passed back to the caller of this frame * - see Parrot_init_ret_nci(). We therefore invoke the * return continuation here, which gets rid of this frame * and returns the real return address */ if (cont && cont != NEED_CONTINUATION && (PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) { cont = Parrot_pcc_get_continuation(interp, CURRENT_CONTEXT(interp)); next = VTABLE_invoke(interp, cont, next); } return (opcode_t *)next; }
static PMC* find_best_candidate(PARROT_INTERP, Rakudo_md_candidate_info **candidates, INTVAL num_candidates, PMC *capture, opcode_t *next, PMC *dispatcher, INTVAL many) { Rakudo_md_candidate_info **cur_candidate = candidates; Rakudo_md_candidate_info **possibles = mem_allocate_n_typed(num_candidates + 1, Rakudo_md_candidate_info *); PMC *junctional_res = PMCNULL; PMC *many_res = many ? Parrot_pmc_new(interp, enum_class_ResizablePMCArray) : PMCNULL; const INTVAL num_args = VTABLE_elements(interp, capture); INTVAL possibles_count = 0; INTVAL pure_type_result = 1; INTVAL type_check_count; INTVAL type_mismatch; /* We expect a Parrot capture in the multi-dispatcher, always. */ struct Pcc_cell * pc_positionals = NULL; if (capture->vtable->base_type == enum_class_CallContext) { GETATTR_CallContext_positionals(interp, capture, pc_positionals); } else { mem_sys_free(possibles); Parrot_ex_throw_from_c_args(interp, next, 1, "INTERNAL ERROR: multi-dispatcher must be given a low level capture"); } /* Iterate over the candidates and collect best ones; terminate * when we see two nulls (may break out earlier). */ while (1) { INTVAL i; if (*cur_candidate == NULL) { /* We've hit the end of a tied group now. If any of them have a * bindability check requirement, we'll do any of those now. */ if (possibles_count) { Rakudo_md_candidate_info **new_possibles = NULL; INTVAL new_possibles_count = 0; INTVAL i; for (i = 0; i < possibles_count; i++) { Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), NULL); /* First, if there's a required named parameter and it was * not passed, we can very quickly eliminate this candidate * without doing a full bindability check. */ if (possibles[i]->req_named) { if (!VTABLE_exists_keyed_str(interp, capture, possibles[i]->req_named)) { /* Required named arg not passed, so we eliminate * it right here. Flag that we've built a list of * new possibles, and that this was not a pure * type-based result that we can cache. */ if (!new_possibles) new_possibles = mem_allocate_n_typed(num_candidates, Rakudo_md_candidate_info *); pure_type_result = 0; continue; } } /* Otherwise, may need full bind check. */ if (possibles[i]->bind_check) { /* We'll invoke the sub (but not re-enter the runloop) * and then attempt to bind the signature. */ PMC *cthunk, *lexpad, *sig; opcode_t *where; INTVAL bind_check_result; Rakudo_Code *code_obj = (Rakudo_Code *)PMC_data(possibles[i]->sub); cthunk = Parrot_pmc_getprop(interp, code_obj->_do, Parrot_str_new(interp, "COMPILER_THUNK", 0)); if (!PMC_IS_NULL(cthunk)) { /* We need to do the tie-break on something not yet compiled. * Get it compiled. */ Parrot_ext_call(interp, cthunk, "->"); } Parrot_pcc_reuse_continuation(interp, CURRENT_CONTEXT(interp), next); where = VTABLE_invoke(interp, possibles[i]->sub, next); lexpad = Parrot_pcc_get_lex_pad(interp, CURRENT_CONTEXT(interp)); sig = possibles[i]->signature; bind_check_result = Rakudo_binding_bind(interp, lexpad, sig, capture, 0, NULL); where = VTABLE_invoke(interp, Parrot_pcc_get_continuation(interp, CURRENT_CONTEXT(interp)), where); /* If we haven't got a possibles storage space, allocate it now. */ if (!new_possibles) new_possibles = mem_allocate_n_typed(num_candidates, Rakudo_md_candidate_info *); /* If we don't fail, need to put this one onto the list * (note that needing a junction dispatch is OK). */ if (bind_check_result != BIND_RESULT_FAIL) { new_possibles[new_possibles_count] = possibles[i]; new_possibles_count++; } /* Since we had to do a bindability check, this is not * a result we can cache on nominal type. */ pure_type_result = 0; } /* Otherwise, it's just nominal; accept it. */ else { if (!new_possibles) new_possibles = mem_allocate_n_typed(num_candidates, Rakudo_md_candidate_info *); new_possibles[new_possibles_count] = possibles[i]; new_possibles_count++; } } /* If we have an updated list of possibles, free old one and use this * new one from here on in. */ if (new_possibles) { mem_sys_free(possibles); possibles = new_possibles; possibles_count = new_possibles_count; } } /* Now we have eliminated any that fail the bindability check. * See if we need to push it onto the many list and continue. * Otherwise, we have the result we were looking for. */ if (many) { for (i = 0; i < possibles_count; i++) VTABLE_push_pmc(interp, many_res, possibles[i]->sub); possibles_count = 0; } else if (possibles_count) { break; } /* Keep looping and looking, unless we really hit the end. */ if (cur_candidate[1]) { cur_candidate++; continue; } else { break; } }