Ticket #1635: loopunroll3.patch

File loopunroll3.patch, 6.9 KB (added by NotFound, 4 years ago)
  • src/ops/experimental.ops

     
    367367#endif 
    368368} 
    369369 
     370=item B<unroll>(in PMC) 
     371 
     372Exception handling done, unroll possible inner runloops left. $1 is the 
     373Exception handled or the ExceptionHandler that is handling it. 
     374EXPERIMENTAL. Handle with care. 
     375 
     376=cut 
     377 
     378op unroll(in PMC) { 
     379    /* Go to the next op after loop unrolling */ 
     380    opcode_t * const dest = expr NEXT(); 
     381    PMC *eh = PMCNULL; 
     382    if (!PMC_IS_NULL($1)) { 
     383        /* If isa ExceptionHandler, use it. If isa Exception, get its active handler */ 
     384        if (VTABLE_isa(interp, $1, Parrot_str_new_constant(interp, "ExceptionHandler"))) 
     385            eh = $1; 
     386        else if (VTABLE_isa(interp, $1, Parrot_str_new_constant(interp, "Exception"))) { 
     387            PMC *iter = VTABLE_get_attr_str(interp, $1, Parrot_str_new_constant(interp, "handler_iter")); 
     388            if (!PMC_IS_NULL(iter)) 
     389                eh = VTABLE_get_pmc_keyed_int(interp, iter, -1); 
     390        } 
     391    } 
     392    if (!PMC_IS_NULL(eh)) { 
     393        /* Get the runloop_id from the continuation and jump to it. */ 
     394        Parrot_runloop *rl = interp->current_runloop; 
     395        INTVAL rid; 
     396        Parrot_pcc_invoke_method_from_c_args(interp, eh, Parrot_str_new_constant(interp, "rid"), "->I", &rid); 
     397        while (rl && rl->id != rid) 
     398            rl = rl->prev; 
     399        if (rl) { 
     400            rl->handler_start = dest; 
     401            longjmp(rl->resume, 3); 
     402        } 
     403        else 
     404            Parrot_ex_throw_from_c_args(interp, NULL, 
     405                    EXCEPTION_INVALID_OPERATION, "missing runloop"); 
     406    } 
     407} 
     408 
     409 
    370410=back 
    371411 
    372412=head1 COPYRIGHT 
  • src/pmc/continuation.pmc

     
    294294 
    295295/* 
    296296 
     297=item C<INTVAL rid()> 
     298 
     299Experimental: return the runloop_id value. 
     300 
     301=cut 
     302 
     303*/ 
     304 
     305    METHOD rid() { 
     306        INTVAL runloop_id; 
     307        GET_ATTR_runloop_id(INTERP, SELF, runloop_id); 
     308        RETURN(INTVAL runloop_id); 
     309    } 
     310 
     311/* 
     312 
    297313=item C<PMC *caller()> 
    298314 
    299315Experimental: return callers PMC or PMCNULL if none. 
  • src/call/ops.c

     
    3535/* HEADERIZER BEGIN: static */ 
    3636/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
    3737 
     38static void free_runloops_until(PARROT_INTERP, int id) 
     39        __attribute__nonnull__(1); 
     40 
    3841static void really_destroy_runloop_jump_points(PARROT_INTERP, 
    3942    ARGFREE(Parrot_runloop *jump_point)) 
    4043        __attribute__nonnull__(1); 
    4144 
     45#define ASSERT_ARGS_free_runloops_until __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     46       PARROT_ASSERT_ARG(interp)) 
    4247#define ASSERT_ARGS_really_destroy_runloop_jump_points \ 
    4348     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    4449       PARROT_ASSERT_ARG(interp)) 
     
    6166    ASSERT_ARGS(runops) 
    6267    volatile size_t offset            = offs; 
    6368    const    int    old_runloop_id    = interp->current_runloop_id; 
    64     const    int    our_runloop_level = ++interp->current_runloop_level; 
    65     const    int    our_runloop_id    = ++runloop_id_counter; 
     69    int             our_runloop_level = interp->current_runloop_level; 
     70    int             our_runloop_id    = old_runloop_id; 
    6671 
    6772    /* It is OK if the runloop ID overflows; we only ever test it for equality, 
    6873       so the chance of collision is slight. */ 
     
    8287#endif 
    8388    { 
    8489        new_runloop_jump_point(interp); 
     90        our_runloop_id = interp->current_runloop_id; 
     91        our_runloop_level = interp->current_runloop_level; 
    8592  reenter: 
    8693        interp->current_runloop->handler_start = NULL; 
    8794        switch (setjmp(interp->current_runloop->resume)) { 
     
    101108          case 2: 
    102109            /* Reenter the runloop from a exception thrown from C 
    103110             * with a pir handler */ 
     111            free_runloops_until(interp, our_runloop_id); 
    104112            PARROT_ASSERT(interp->current_runloop->handler_start); 
    105113            offset = interp->current_runloop->handler_start - interp->code->base.data; 
    106114            /* Prevent incorrect reuse */ 
    107115            goto reenter; 
     116          case 3: 
     117            /* Reenter the runloop when finished the handling of a 
     118             * exception */ 
     119            free_runloops_until(interp, our_runloop_id); 
     120            offset = interp->current_runloop->handler_start - interp->code->base.data; 
     121            goto reenter; 
    108122          default: 
    109123            break; 
    110124        } 
     
    121135    fprintf(stderr, "[exiting loop %d, level %d]\n", 
    122136            our_runloop_id, our_runloop_level); 
    123137#endif 
    124  
    125     interp->current_runloop_level = our_runloop_level - 1; 
    126     interp->current_runloop_id    = old_runloop_id; 
    127138} 
    128139 
    129140 
     
    158169    else 
    159170        jump_point = mem_gc_allocate_zeroed_typed(interp, Parrot_runloop); 
    160171 
    161     jump_point->prev        = interp->current_runloop; 
    162     interp->current_runloop = jump_point; 
     172    jump_point->prev           = interp->current_runloop; 
     173    jump_point->id             = ++runloop_id_counter; 
     174    interp->current_runloop    = jump_point; 
     175    interp->current_runloop_id = jump_point->id; 
     176    ++interp->current_runloop_level; 
    163177} 
    164178 
    165179/* 
     
    178192{ 
    179193    ASSERT_ARGS(free_runloop_jump_point) 
    180194    Parrot_runloop * const jump_point = interp->current_runloop; 
    181     interp->current_runloop           = jump_point->prev; 
     195    Parrot_runloop * const current    = jump_point->prev; 
     196    interp->current_runloop           = current; 
    182197    jump_point->prev                  = interp->runloop_jmp_free_list; 
    183198    interp->runloop_jmp_free_list     = jump_point; 
     199    interp->current_runloop_id        = current ? current->id : 0; 
     200    --interp->current_runloop_level; 
    184201} 
    185202 
    186203/* 
     
    204221 
    205222/* 
    206223 
     224=item C<static void free_runloops_until(PARROT_INTERP, int id)> 
     225 
     226Free runloops until the one with the provided id gets current. 
     227 
     228=cut 
     229 
     230*/ 
     231 
     232static void 
     233free_runloops_until(PARROT_INTERP, int id) 
     234{ 
     235    while (interp->current_runloop && interp->current_runloop_id != id) 
     236        free_runloop_jump_point(interp); 
     237} 
     238 
     239/* 
     240 
    207241=item C<static void really_destroy_runloop_jump_points(PARROT_INTERP, 
    208242Parrot_runloop *jump_point)> 
    209243 
  • include/parrot/call.h

     
    2828    struct parrot_runloop_t *prev;          /* interpreter's runloop 
    2929                                             * jump buffer stack */ 
    3030    opcode_t                *handler_start; /* Used in exception handling */ 
     31    int                      id;            /* runloop id */ 
    3132 
    3233    /* let the biggest element cross the cacheline boundary */ 
    3334    Parrot_jump_buff         resume;        /* jmp_buf */