Ticket #1396: tt1396.patch
File tt1396.patch, 18.2 KB (added by jimmy, 12 years ago) |
---|
-
src/pmc/continuation.pmc
64 64 */ 65 65 66 66 VTABLE void init() { 67 P arrot_Continuation_attributes * const attrs = PARROT_CONTINUATION(SELF);67 PMC * const to_ctx = CURRENT_CONTEXT(INTERP); 68 68 69 attrs->to_ctx = CURRENT_CONTEXT(interp);70 attrs->to_call_object = Parrot_pcc_get_signature(INTERP, attrs->to_ctx);71 attrs->from_ctx = CURRENT_CONTEXT(interp);72 attrs->runloop_id = 0;73 attrs->seg = interp->code;74 attrs->address = NULL;69 SET_ATTR_to_ctx(INTERP, SELF, to_ctx); 70 SET_ATTR_to_call_object(INTERP, SELF, Parrot_pcc_get_signature(INTERP, to_ctx)); 71 SET_ATTR_from_ctx(INTERP, SELF, CURRENT_CONTEXT(INTERP)); 72 SET_ATTR_runloop_id(INTERP, SELF, 0); 73 SET_ATTR_seg(INTERP, SELF, INTERP->code); 74 SET_ATTR_address(INTERP, SELF, NULL); 75 75 76 76 PObj_custom_mark_SET(SELF); 77 77 … … 87 87 88 88 /*if they pass in a PMC to initialize with*/ 89 89 VTABLE void init_pmc(PMC *values) { 90 Parrot_Continuation_attributes * const attrs = PARROT_CONTINUATION(SELF); 91 Parrot_Continuation_attributes * const theirs = PARROT_CONTINUATION(values); 90 PMC *to_ctx; 91 opcode_t *address; 92 PackFile_ByteCode *seg; 92 93 93 attrs->to_ctx = theirs->to_ctx; 94 attrs->to_call_object = Parrot_pcc_get_signature(INTERP, attrs->to_ctx); 95 attrs->from_ctx = CURRENT_CONTEXT(interp); 96 attrs->runloop_id = 0; 97 attrs->seg = theirs->seg; 98 attrs->address = theirs->address; 94 GET_ATTR_to_ctx(INTERP, values, to_ctx); 95 SET_ATTR_to_ctx(INTERP, SELF, to_ctx); 96 SET_ATTR_to_call_object(INTERP, SELF, Parrot_pcc_get_signature(INTERP, to_ctx)); 99 97 98 SET_ATTR_from_ctx(INTERP, SELF, CURRENT_CONTEXT(INTERP)); 99 SET_ATTR_runloop_id(INTERP, SELF, 0); 100 101 GET_ATTR_seg(INTERP, values, seg); 102 SET_ATTR_seg(INTERP, SELF, seg); 103 104 GET_ATTR_address(INTERP, values, address); 105 SET_ATTR_address(INTERP, SELF, address); 106 100 107 PObj_custom_mark_SET(SELF); 101 108 102 109 /* PANIC("don't do that"); */ … … 122 129 */ 123 130 124 131 VTABLE void mark() { 125 P arrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF);132 PMC *tmp; 126 133 127 134 /* If Continuation wasn't fully constructed yet */ 128 if (! cc)135 if (!PMC_data(SELF)) 129 136 return; 130 137 131 Parrot_gc_mark_PMC_alive(INTERP, cc->to_ctx); 132 Parrot_gc_mark_PMC_alive(INTERP, cc->to_call_object); 133 Parrot_gc_mark_PMC_alive(INTERP, cc->from_ctx); 138 GET_ATTR_to_ctx(INTERP, SELF, tmp); 139 Parrot_gc_mark_PMC_alive(INTERP, tmp); 140 141 GET_ATTR_to_call_object(INTERP, SELF, tmp); 142 Parrot_gc_mark_PMC_alive(INTERP, tmp); 143 144 GET_ATTR_from_ctx(INTERP, SELF, tmp); 145 Parrot_gc_mark_PMC_alive(INTERP, tmp); 134 146 } 135 147 136 148 /* … … 145 157 146 158 VTABLE PMC *clone() { 147 159 /* Start to prepare for subclassable continuations */ 148 INTVAL type = SELF->vtable->base_type; 149 PMC * ret = pmc_new_init(interp, type, SELF); 150 return ret; 160 return pmc_new_init(INTERP, SELF->vtable->base_type, SELF); 151 161 } 152 162 153 163 /* … … 160 170 161 171 */ 162 172 VTABLE void set_pmc(PMC *src) { 163 Parrot_Continuation_attributes * const cc_self = PARROT_CONTINUATION(SELF); 164 Parrot_Continuation_attributes * const cc_src = PARROT_CONTINUATION(src); 165 166 STRUCT_COPY(cc_self, cc_src); 173 STRUCT_COPY((Parrot_Continuation_attributes *)PMC_data(SELF), 174 (Parrot_Continuation_attributes *)PMC_data(src)); 167 175 } 168 176 /* 169 177 … … 177 185 */ 178 186 179 187 VTABLE void set_pointer(void *value) { 180 opcode_t * const pos = (opcode_t *)value; 181 Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF); 182 183 cc->address = pos; 184 cc->runloop_id = INTERP->current_runloop_id; 188 SET_ATTR_address(INTERP, SELF, (opcode_t *)value); 189 SET_ATTR_runloop_id(INTERP, SELF, INTERP->current_runloop_id); 185 190 } 186 191 187 192 /* … … 195 200 */ 196 201 197 202 VTABLE void *get_pointer() { 198 return PARROT_CONTINUATION(SELF)->address; 203 opcode_t *address; 204 205 GET_ATTR_address(INTERP, SELF, address); 206 207 return address; 199 208 } 200 209 201 210 /* … … 211 220 */ 212 221 213 222 VTABLE INTVAL defined() { 214 return PARROT_CONTINUATION(SELF)->address != NULL; 223 opcode_t *address; 224 225 GET_ATTR_address(INTERP, SELF, address); 226 227 return address != NULL; 215 228 } 216 229 217 230 VTABLE INTVAL get_bool() { 218 return PARROT_CONTINUATION(SELF)->address != NULL; 231 opcode_t *address; 232 233 GET_ATTR_address(INTERP, SELF, address); 234 235 return address != NULL; 219 236 } 220 237 221 238 /* … … 230 247 */ 231 248 232 249 VTABLE opcode_t *invoke(void *next) { 233 Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF); 234 PMC *from_ctx = CURRENT_CONTEXT(interp); 235 PMC *to_ctx = cc->to_ctx; 236 opcode_t *pc = cc->address; 237 PMC *call_obj = cc->to_call_object; 238 PMC *from_obj = Parrot_pcc_get_signature(interp, from_ctx); 250 PMC * const from_obj = Parrot_pcc_get_signature(INTERP, CURRENT_CONTEXT(INTERP)); 251 PMC *to_ctx, *call_obj; 252 opcode_t *pc; 253 PackFile_ByteCode *seg; 239 254 UNUSED(next) 240 255 241 Parrot_continuation_check(interp, SELF); 242 Parrot_continuation_rewind_environment(interp, SELF); 256 GET_ATTR_seg(INTERP, SELF, seg); 257 GET_ATTR_address(INTERP, SELF, pc); 258 GET_ATTR_to_ctx(INTERP, SELF, to_ctx); 259 GET_ATTR_to_call_object(INTERP, SELF, call_obj); 243 260 261 Parrot_continuation_check(INTERP, SELF); 262 Parrot_continuation_rewind_environment(INTERP, SELF); 263 244 264 if (!PMC_IS_NULL(from_obj)) { 245 STRING * string_sig = VTABLE_get_string(INTERP, from_obj);265 STRING * const string_sig = VTABLE_get_string(INTERP, from_obj); 246 266 /* If there is no string - there is no args */ 247 267 if (string_sig) { 248 268 PMC *raw_sig, *invalid_sig; … … 253 273 call_obj = Parrot_pcc_build_sig_object_returns_from_op(INTERP, call_obj, 254 274 Parrot_pcc_get_pmc_constant(INTERP, to_ctx, pc[1]), pc); 255 275 256 Parrot_pcc_fill_returns_from_continuation( interp, call_obj, raw_sig, from_obj);276 Parrot_pcc_fill_returns_from_continuation(INTERP, call_obj, raw_sig, from_obj); 257 277 } 258 278 } 259 279 260 280 /* switch segment */ 261 if (INTERP->code != cc->seg)262 Parrot_switch_to_cs(INTERP, cc->seg, 1);281 if (INTERP->code != seg) 282 Parrot_switch_to_cs(INTERP, seg, 1); 263 283 264 284 return pc; 265 285 } … … 275 295 */ 276 296 277 297 VTABLE STRING *get_string() { 278 return Parrot_Context_infostr(INTERP, PARROT_CONTINUATION(SELF)->to_ctx); 298 PMC *to_ctx; 299 300 GET_ATTR_to_ctx(INTERP, SELF, to_ctx); 301 302 return Parrot_Context_infostr(INTERP, to_ctx); 279 303 } 280 304 281 305 /* … … 289 313 */ 290 314 291 315 METHOD caller() { 292 Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF); 293 PMC *caller = Parrot_pcc_get_sub(interp, cc->to_ctx); 316 PMC *to_ctx, *caller; 294 317 318 GET_ATTR_to_ctx(INTERP, SELF, to_ctx); 319 320 caller = Parrot_pcc_get_sub(INTERP, to_ctx); 321 295 322 if (!caller) 296 323 caller = PMCNULL; 297 324 else { … … 315 342 */ 316 343 317 344 METHOD continuation() { 318 Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF); 319 PMC * const cont = Parrot_pcc_get_continuation(interp, cc->to_ctx); 345 PMC *to_ctx, *cont; 320 346 347 GET_ATTR_to_ctx(INTERP, SELF, to_ctx); 348 349 cont = Parrot_pcc_get_continuation(INTERP, to_ctx); 350 321 351 if (cont) 322 352 RETURN(PMC *cont); 323 353 -
src/pmc/coroutine.pmc
35 35 static void 36 36 print_sub_name(PARROT_INTERP, PMC *sub_pmc) 37 37 { 38 /* It's actually a Parrot_coro , but this avoids casting warnings. */39 P arrot_Sub_attributes *co = PARROT_SUB(sub_pmc);40 Interp 41 interp->pdb->debugger :42 interp;38 /* It's actually a Parrot_coroutine, but this avoids casting warnings. */ 39 PMC *ctx; 40 Interp * const tracer = (interp->pdb && interp->pdb->debugger) ? 41 interp->pdb->debugger : 42 interp; 43 43 44 Parrot_io_eprintf(tracer, "# %s coro '%Ss'", 44 GETATTR_Coroutine_ctx(interp, sub_pmc, ctx); 45 46 Parrot_io_eprintf(tracer, "# %s coroutine '%Ss'", 45 47 !(PObj_get_FLAGS(sub_pmc) & SUB_FLAG_CORO_FF) ? 46 48 "Calling" : "yielding from", 47 49 Parrot_full_sub_name(interp, sub_pmc)); 48 50 49 if (c o->ctx && (PObj_get_FLAGS(sub_pmc) & SUB_FLAG_CORO_FF)) {51 if (ctx && (PObj_get_FLAGS(sub_pmc) & SUB_FLAG_CORO_FF)) { 50 52 Parrot_io_eprintf(tracer, " to '%Ss'", 51 53 Parrot_full_sub_name(interp, 52 Parrot_pcc_get_sub(interp, Parrot_pcc_get_caller_ctx(interp, c o->ctx))));54 Parrot_pcc_get_sub(interp, Parrot_pcc_get_caller_ctx(interp, ctx)))); 53 55 } 54 56 55 57 Parrot_io_eprintf(tracer, "\n# "); … … 57 59 } 58 60 59 61 pmclass Coroutine extends Sub auto_attrs { 62 ATTR INTVAL yield; /* yield in process */ 63 ATTR opcode_t *address; /* next address to run - toggled each time */ 60 64 ATTR PackFile_ByteCode *caller_seg; /* bytecode segment */ 61 ATTR opcode_t *address; /* next address to run - toggled each time */62 ATTR INTVAL yield; /* yield in process */63 65 64 66 /* 65 67 … … 76 78 */ 77 79 78 80 VTABLE void init() { 79 Parrot_Coroutine_attributes *attrs = PARROT_COROUTINE(SELF); 81 SET_ATTR_seg(INTERP, SELF, INTERP->code); 82 SET_ATTR_ctx(INTERP, SELF, PMCNULL); 80 83 81 attrs->seg = INTERP->code;82 attrs->ctx = PMCNULL;83 84 84 PObj_custom_mark_destroy_SETALL(SELF); 85 85 } 86 86 … … 96 96 */ 97 97 98 98 VTABLE PMC *clone() { 99 STRING *name; 99 100 PMC * const ret = pmc_new(INTERP, SELF->vtable->base_type); 100 Parrot_Coroutine_attributes * const sub = PARROT_COROUTINE(SELF);101 Parrot_Coroutine_attributes * const coro_sub = PARROT_COROUTINE(ret);102 101 103 102 PObj_custom_mark_destroy_SETALL(ret); 104 103 105 memcpy(coro_sub, sub, sizeof (Parrot_Coroutine_attributes)); 104 memcpy((Parrot_Coroutine_attributes *)PMC_data(ret), 105 (Parrot_Coroutine_attributes *)PMC_data(SELF), 106 sizeof (Parrot_Coroutine_attributes)); 106 107 107 coro_sub->name = Parrot_str_copy(INTERP, coro_sub->name); 108 GET_ATTR_name(INTERP, ret, name); 109 SET_ATTR_name(INTERP, ret, Parrot_str_copy(INTERP, name)); 108 110 109 111 return ret; 110 112 } … … 134 136 */ 135 137 136 138 VTABLE opcode_t *invoke(void *next) { 139 PMC *ctx; 140 opcode_t *dest; 137 141 PackFile_ByteCode *wanted_seg; 138 Parrot_Coroutine_attributes * const co = PARROT_COROUTINE(SELF); 139 opcode_t * dest = co->address; 140 opcode_t * const next_op = (opcode_t *)next; 141 142 opcode_t * const next_op = (opcode_t *)next; 143 142 144 if (Interp_trace_TEST(INTERP, PARROT_TRACE_SUB_CALL_FLAG)) 143 145 print_sub_name(INTERP, SELF); 144 146 145 if (PMC_IS_NULL(co->ctx)) { 146 PMC * const caller_ctx = CURRENT_CONTEXT(interp); 147 PMC *ctx; 148 PMC *ccont = INTERP->current_cont; 147 GET_ATTR_ctx(INTERP, SELF, ctx); 149 148 149 if (PMC_IS_NULL(ctx)) { 150 PackFile_ByteCode *seg; 151 size_t start_offs; 152 const INTVAL *n_regs_used; 153 PMC *lex_info; 154 PMC * const caller_ctx = CURRENT_CONTEXT(INTERP); 155 PMC *ctx = Parrot_pcc_get_signature(INTERP, caller_ctx); 156 PMC *ccont = INTERP->current_cont; 157 150 158 if (ccont == NEED_CONTINUATION) 151 ccont = (PMC *)new_ret_continuation_pmc( interp, next_op);159 ccont = (PMC *)new_ret_continuation_pmc(INTERP, next_op); 152 160 153 161 if (PObj_get_FLAGS(ccont) & SUB_FLAG_TAILCALL) 154 162 Parrot_ex_throw_from_c_args(INTERP, NULL, CONTROL_ERROR, 155 "tail call to coro not allowed");163 "tail call to coroutine not allowed"); 156 164 157 165 /* first time set current sub, cont, object */ 158 ctx = Parrot_pcc_get_signature(INTERP, caller_ctx);159 166 if (PMC_IS_NULL(ctx)) 160 167 ctx = pmc_new(INTERP, enum_class_CallContext); 168 161 169 CURRENT_CONTEXT(INTERP) = ctx; 162 Parrot_pcc_allocate_registers(INTERP, ctx, co->n_regs_used); 170 171 GET_ATTR_n_regs_used(INTERP, SELF, n_regs_used); 172 Parrot_pcc_allocate_registers(INTERP, ctx, n_regs_used); 163 173 Parrot_pcc_set_caller_ctx(INTERP, ctx, caller_ctx); 164 174 Parrot_pcc_init_context(INTERP, ctx, caller_ctx); 165 175 166 co->ctx = ctx;176 SET_ATTR_ctx(INTERP, SELF, ctx); 167 177 168 PARROT_CONTINUATION(ccont)->from_ctx = ctx; 178 SETATTR_Continuation_from_ctx(INTERP, ccont, ctx); 179 169 180 Parrot_pcc_set_sub(INTERP, ctx, SELF); 170 181 Parrot_pcc_set_continuation(INTERP, ctx, ccont); 171 Parrot_pcc_set_object(interp, ctx, PMCNULL); 182 Parrot_pcc_set_object(INTERP, ctx, PMCNULL); 183 172 184 INTERP->current_object = PMCNULL; 173 185 INTERP->current_cont = PMCNULL; 174 186 187 GET_ATTR_lex_info(INTERP, SELF, lex_info); 188 175 189 /* create pad if needed */ 176 if (!PMC_IS_NULL( co->lex_info)) {177 const INTVAL hlltype = Parrot_get_ctx_HLL_type( interp, enum_class_LexPad);178 PMC * const lexpad = pmc_new_init(INTERP, hlltype, co->lex_info);190 if (!PMC_IS_NULL(lex_info)) { 191 const INTVAL hlltype = Parrot_get_ctx_HLL_type(INTERP, enum_class_LexPad); 192 PMC * const lexpad = pmc_new_init(INTERP, hlltype, lex_info); 179 193 Parrot_pcc_set_lex_pad(INTERP, ctx, lexpad); 180 194 VTABLE_set_pointer(INTERP, lexpad, ctx); 181 195 } 182 196 197 GET_ATTR_seg(INTERP, SELF, seg); 183 198 PObj_get_FLAGS(SELF) |= SUB_FLAG_CORO_FF; 184 wanted_seg = co->seg; 185 co->caller_seg = INTERP->code; 186 co->address = co->seg->base.data + co->start_offs; 199 wanted_seg = seg; 200 201 GET_ATTR_start_offs(INTERP, SELF, start_offs); 202 SET_ATTR_caller_seg(INTERP, SELF, INTERP->code); 203 SET_ATTR_address(INTERP, SELF, seg->base.data + start_offs); 187 204 } 188 205 189 206 /* if calling the Coro we need the segment of the Coro */ 190 207 else if (!(PObj_get_FLAGS(SELF) & SUB_FLAG_CORO_FF)) { 191 PMC * const ctx = co->ctx; 192 PMC * const ccont = Parrot_pcc_get_continuation(INTERP, ctx); 208 PackFile_ByteCode *seg; 209 PMC *ctx; 210 PMC *ccont; 193 211 212 GET_ATTR_ctx(INTERP, SELF, ctx); 213 ccont = Parrot_pcc_get_continuation(INTERP, ctx); 214 194 215 PObj_get_FLAGS(SELF) |= SUB_FLAG_CORO_FF; 195 wanted_seg = co->seg;196 216 217 GET_ATTR_seg(INTERP, SELF, seg); 218 wanted_seg = seg; 219 197 220 /* remember segment of caller */ 198 co->caller_seg = INTERP->code;221 SET_ATTR_caller_seg(INTERP, SELF, INTERP->code); 199 222 223 224 200 225 /* and the recent call context */ 201 PARROT_CONTINUATION(ccont)->to_ctx = CURRENT_CONTEXT(interp);202 Parrot_pcc_set_caller_ctx( interp, ctx, CURRENT_CONTEXT(interp));226 SETATTR_Continuation_to_ctx(INTERP, ccont, CURRENT_CONTEXT(INTERP)); 227 Parrot_pcc_set_caller_ctx(INTERP, ctx, CURRENT_CONTEXT(INTERP)); 203 228 204 /* set context to coro context */205 CURRENT_CONTEXT( interp) = ctx;229 /* set context to coroutine context */ 230 CURRENT_CONTEXT(INTERP) = ctx; 206 231 } 207 232 else { 208 PMC * const ccont = Parrot_pcc_get_continuation(INTERP, co->ctx); 209 PMC * const ctx = PARROT_CONTINUATION(ccont)->to_ctx; 210 INTVAL yield; 233 INTVAL yield; 234 PMC *ccont, *ctx, *to_ctx; 235 PackFile_ByteCode *caller_seg; 236 211 237 GET_ATTR_yield(INTERP, SELF, yield); 212 if (! yield) 238 239 if (!yield) 213 240 Parrot_ex_throw_from_c_args(INTERP, NULL, CONTROL_ERROR, 214 241 "Cannot resume dead coroutine."); 242 215 243 SET_ATTR_yield(INTERP, SELF, 0); 216 244 245 GET_ATTR_ctx(INTERP, SELF, ctx); 246 ccont = Parrot_pcc_get_continuation(INTERP, ctx); 247 248 GETATTR_Continuation_to_ctx(INTERP, ccont, to_ctx); 249 217 250 PObj_get_FLAGS(SELF) &= ~SUB_FLAG_CORO_FF; 251 GET_ATTR_caller_seg(INTERP, SELF, caller_seg); 252 218 253 /* switch back to last remembered code seg and context */ 254 wanted_seg = caller_seg; 219 255 220 wanted_seg = co->caller_seg; 221 222 if (PMC_IS_NULL(ctx)) { 256 if (PMC_IS_NULL(to_ctx)) { 223 257 /* This still isn't quite right, but it beats segfaulting. See 224 258 the "Call an exited coroutine" case in t/pmc/coroutine.t; the 225 259 problem is that the defunct coroutine yields up one more … … 230 264 "Cannot resume dead coroutine."); 231 265 } 232 266 233 CURRENT_CONTEXT( interp) =ctx;267 CURRENT_CONTEXT(INTERP) = to_ctx; 234 268 } 235 269 236 270 /* toggle address */ 237 dest = co->address;238 co->address = (opcode_t *)next;271 GET_ATTR_address(INTERP, SELF, dest); 272 SET_ATTR_address(INTERP, SELF, (opcode_t *)next); 239 273 240 274 if (INTERP->code != wanted_seg) 241 275 Parrot_switch_to_cs(INTERP, wanted_seg, 1);