Ticket #1635: loopunroll3.patch
File loopunroll3.patch, 6.9 KB (added by NotFound, 12 years ago) |
---|
-
src/ops/experimental.ops
367 367 #endif 368 368 } 369 369 370 =item B<unroll>(in PMC) 371 372 Exception handling done, unroll possible inner runloops left. $1 is the 373 Exception handled or the ExceptionHandler that is handling it. 374 EXPERIMENTAL. Handle with care. 375 376 =cut 377 378 op 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 370 410 =back 371 411 372 412 =head1 COPYRIGHT -
src/pmc/continuation.pmc
294 294 295 295 /* 296 296 297 =item C<INTVAL rid()> 298 299 Experimental: 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 297 313 =item C<PMC *caller()> 298 314 299 315 Experimental: return callers PMC or PMCNULL if none. -
src/call/ops.c
35 35 /* HEADERIZER BEGIN: static */ 36 36 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 37 37 38 static void free_runloops_until(PARROT_INTERP, int id) 39 __attribute__nonnull__(1); 40 38 41 static void really_destroy_runloop_jump_points(PARROT_INTERP, 39 42 ARGFREE(Parrot_runloop *jump_point)) 40 43 __attribute__nonnull__(1); 41 44 45 #define ASSERT_ARGS_free_runloops_until __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 46 PARROT_ASSERT_ARG(interp)) 42 47 #define ASSERT_ARGS_really_destroy_runloop_jump_points \ 43 48 __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 44 49 PARROT_ASSERT_ARG(interp)) … … 61 66 ASSERT_ARGS(runops) 62 67 volatile size_t offset = offs; 63 68 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; 66 71 67 72 /* It is OK if the runloop ID overflows; we only ever test it for equality, 68 73 so the chance of collision is slight. */ … … 82 87 #endif 83 88 { 84 89 new_runloop_jump_point(interp); 90 our_runloop_id = interp->current_runloop_id; 91 our_runloop_level = interp->current_runloop_level; 85 92 reenter: 86 93 interp->current_runloop->handler_start = NULL; 87 94 switch (setjmp(interp->current_runloop->resume)) { … … 101 108 case 2: 102 109 /* Reenter the runloop from a exception thrown from C 103 110 * with a pir handler */ 111 free_runloops_until(interp, our_runloop_id); 104 112 PARROT_ASSERT(interp->current_runloop->handler_start); 105 113 offset = interp->current_runloop->handler_start - interp->code->base.data; 106 114 /* Prevent incorrect reuse */ 107 115 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; 108 122 default: 109 123 break; 110 124 } … … 121 135 fprintf(stderr, "[exiting loop %d, level %d]\n", 122 136 our_runloop_id, our_runloop_level); 123 137 #endif 124 125 interp->current_runloop_level = our_runloop_level - 1;126 interp->current_runloop_id = old_runloop_id;127 138 } 128 139 129 140 … … 158 169 else 159 170 jump_point = mem_gc_allocate_zeroed_typed(interp, Parrot_runloop); 160 171 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; 163 177 } 164 178 165 179 /* … … 178 192 { 179 193 ASSERT_ARGS(free_runloop_jump_point) 180 194 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; 182 197 jump_point->prev = interp->runloop_jmp_free_list; 183 198 interp->runloop_jmp_free_list = jump_point; 199 interp->current_runloop_id = current ? current->id : 0; 200 --interp->current_runloop_level; 184 201 } 185 202 186 203 /* … … 204 221 205 222 /* 206 223 224 =item C<static void free_runloops_until(PARROT_INTERP, int id)> 225 226 Free runloops until the one with the provided id gets current. 227 228 =cut 229 230 */ 231 232 static void 233 free_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 207 241 =item C<static void really_destroy_runloop_jump_points(PARROT_INTERP, 208 242 Parrot_runloop *jump_point)> 209 243 -
include/parrot/call.h
28 28 struct parrot_runloop_t *prev; /* interpreter's runloop 29 29 * jump buffer stack */ 30 30 opcode_t *handler_start; /* Used in exception handling */ 31 int id; /* runloop id */ 31 32 32 33 /* let the biggest element cross the cacheline boundary */ 33 34 Parrot_jump_buff resume; /* jmp_buf */