Author: jonathan Date: Mon Jan 19 07:42:50 2009 New Revision: 35759 Modified: trunk/languages/perl6/src/classes/Junction.pir trunk/languages/perl6/src/pmc/perl6multisub.pmc
Log: [rakudo] Make auto-threading work in the multi-dispatch case. Modified: trunk/languages/perl6/src/classes/Junction.pir ============================================================================== --- trunk/languages/perl6/src/classes/Junction.pir (original) +++ trunk/languages/perl6/src/classes/Junction.pir Mon Jan 19 07:42:50 2009 @@ -236,6 +236,8 @@ ## lookup a sub by name if needed $I0 = isa the_sub, 'Sub' if $I0 goto have_sub + $I0 = isa the_sub, 'MultiSub' + if $I0 goto have_sub $S0 = the_sub the_sub = find_name $S0 have_sub: @@ -349,7 +351,7 @@ pi = new 'ParrotInterpreter' sub = pi['sub'] sub = getprop 'sub', sub - .tailcall '!DISPATCH_JUNCTION'(sub, pos_args :flat, name_args :flat) + .tailcall '!DISPATCH_JUNCTION'(sub, pos_args :flat, name_args :flat :named) .end Modified: trunk/languages/perl6/src/pmc/perl6multisub.pmc ============================================================================== --- trunk/languages/perl6/src/pmc/perl6multisub.pmc (original) +++ trunk/languages/perl6/src/pmc/perl6multisub.pmc Mon Jan 19 07:42:50 2009 @@ -423,10 +423,35 @@ return result; } + +/* + +=item C<static INTVAL has_junctional_args(PARROT_INTERP, PMC *args)> + +Checks if any of the args are junctional. + +=cut + +*/ + +static INTVAL has_junctional_args(PARROT_INTERP, PMC *args) { + INTVAL num_args = VTABLE_elements(interp, args); + STRING *junction = CONST_STRING(interp, "Junction"); + INTVAL i; + for (i = 0; i < num_args; i++) { + PMC *arg = VTABLE_get_pmc_keyed_int(interp, args, i); + if (VTABLE_isa(interp, arg, junction)) + return 1; + } + return 0; +} + + /* -=item C<static PMC* do_dispatch(candidate_info **candidates, PMC *args, - int many, int num_candidates, opcode_t *next, MMD_Cache *cache)> +=item C<static PMC* do_dispatch(PARROT_INTERP, PMC *self, candidate_info **candidates, + PMC *proto, PMC *args, int many, int num_candidates, + opcode_t *next, MMD_Cache *cache)> Runs the Perl 6 MMD algorithm. If many is set to a true value, returns a ResizablePMCArray of all possible candidates, which may be empty. If many @@ -438,7 +463,7 @@ */ -static PMC* do_dispatch(PARROT_INTERP, candidate_info **candidates, PMC *proto, +static PMC* do_dispatch(PARROT_INTERP, PMC *self, candidate_info **candidates, PMC *proto, PMC *args, int many, int num_candidates, opcode_t *next, MMD_Cache *cache) { INTVAL type_mismatch; STRING *ACCEPTS = CONST_STRING(interp, "ACCEPTS"); @@ -601,6 +626,18 @@ if (possibles_count == 1) { return possibles[0]->sub; } + else if (possibles_count == 0 && has_junctional_args(interp, args)) { + /* Look up multi junction dispatcher, clone it, attach this multi-sub + * as a property and hand that back as the dispatch result. We also + * stick it in the MMD cache for next time around. */ + PMC *sub = Parrot_find_global_n(interp, Parrot_get_ctx_HLL_namespace(interp), + CONST_STRING(interp, "!DISPATCH_JUNCTION_MULTI")); + sub = VTABLE_clone(interp, sub); + VTABLE_setprop(interp, sub, CONST_STRING(interp, "sub"), self); + if (cache) + Parrot_mmd_cache_store_by_values(interp, cache, "", args, sub); + return sub; + } else if (!PMC_IS_NULL(proto)) { /* If we have a proto at this point, use that. */ return proto; @@ -819,7 +856,7 @@ /* Now do the dispatch on the args we are being invoked with; * if it can't find anything, it will throw the required exception. */ - found = do_dispatch(interp, candidates, proto, args, MMD_ONE_RESULT, + found = do_dispatch(interp, SELF, candidates, proto, args, MMD_ONE_RESULT, VTABLE_elements(interp, unsorted), (opcode_t *)next, cache); } @@ -878,7 +915,7 @@ /* Now do the dispatch on the args we have been supplied with, and * get back a PMC array of possibles. */ - results = do_dispatch(interp, candidates, proto, args, MMD_MANY_RESULTS, + results = do_dispatch(interp, SELF, candidates, proto, args, MMD_MANY_RESULTS, VTABLE_elements(interp, unsorted), NULL, NULL); /* Restore stuff that might have got overwriten by calls during the