Index: src/pmc/continuation.pmc =================================================================== --- src/pmc/continuation.pmc (版本 43268) +++ src/pmc/continuation.pmc (工作副本) @@ -64,14 +64,14 @@ */ VTABLE void init() { - Parrot_Continuation_attributes * const attrs = PARROT_CONTINUATION(SELF); + PMC * const to_ctx = CURRENT_CONTEXT(INTERP); - attrs->to_ctx = CURRENT_CONTEXT(interp); - attrs->to_call_object = Parrot_pcc_get_signature(INTERP, attrs->to_ctx); - attrs->from_ctx = CURRENT_CONTEXT(interp); - attrs->runloop_id = 0; - attrs->seg = interp->code; - attrs->address = NULL; + SET_ATTR_to_ctx(INTERP, SELF, to_ctx); + SET_ATTR_to_call_object(INTERP, SELF, Parrot_pcc_get_signature(INTERP, to_ctx)); + SET_ATTR_from_ctx(INTERP, SELF, CURRENT_CONTEXT(INTERP)); + SET_ATTR_runloop_id(INTERP, SELF, 0); + SET_ATTR_seg(INTERP, SELF, INTERP->code); + SET_ATTR_address(INTERP, SELF, NULL); PObj_custom_mark_SET(SELF); @@ -87,16 +87,23 @@ /*if they pass in a PMC to initialize with*/ VTABLE void init_pmc(PMC *values) { - Parrot_Continuation_attributes * const attrs = PARROT_CONTINUATION(SELF); - Parrot_Continuation_attributes * const theirs = PARROT_CONTINUATION(values); + PMC *to_ctx; + opcode_t *address; + PackFile_ByteCode *seg; - attrs->to_ctx = theirs->to_ctx; - attrs->to_call_object = Parrot_pcc_get_signature(INTERP, attrs->to_ctx); - attrs->from_ctx = CURRENT_CONTEXT(interp); - attrs->runloop_id = 0; - attrs->seg = theirs->seg; - attrs->address = theirs->address; + GET_ATTR_to_ctx(INTERP, values, to_ctx); + SET_ATTR_to_ctx(INTERP, SELF, to_ctx); + SET_ATTR_to_call_object(INTERP, SELF, Parrot_pcc_get_signature(INTERP, to_ctx)); + SET_ATTR_from_ctx(INTERP, SELF, CURRENT_CONTEXT(INTERP)); + SET_ATTR_runloop_id(INTERP, SELF, 0); + + GET_ATTR_seg(INTERP, values, seg); + SET_ATTR_seg(INTERP, SELF, seg); + + GET_ATTR_address(INTERP, values, address); + SET_ATTR_address(INTERP, SELF, address); + PObj_custom_mark_SET(SELF); /* PANIC("don't do that"); */ @@ -122,15 +129,20 @@ */ VTABLE void mark() { - Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF); + PMC *tmp; /* If Continuation wasn't fully constructed yet */ - if (!cc) + if (!PMC_data(SELF)) return; - Parrot_gc_mark_PMC_alive(INTERP, cc->to_ctx); - Parrot_gc_mark_PMC_alive(INTERP, cc->to_call_object); - Parrot_gc_mark_PMC_alive(INTERP, cc->from_ctx); + GET_ATTR_to_ctx(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_to_call_object(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); + + GET_ATTR_from_ctx(INTERP, SELF, tmp); + Parrot_gc_mark_PMC_alive(INTERP, tmp); } /* @@ -145,9 +157,7 @@ VTABLE PMC *clone() { /* Start to prepare for subclassable continuations */ - INTVAL type = SELF->vtable->base_type; - PMC * ret = pmc_new_init(interp, type, SELF); - return ret; + return pmc_new_init(INTERP, SELF->vtable->base_type, SELF); } /* @@ -160,10 +170,8 @@ */ VTABLE void set_pmc(PMC *src) { - Parrot_Continuation_attributes * const cc_self = PARROT_CONTINUATION(SELF); - Parrot_Continuation_attributes * const cc_src = PARROT_CONTINUATION(src); - - STRUCT_COPY(cc_self, cc_src); + STRUCT_COPY((Parrot_Continuation_attributes *)PMC_data(SELF), + (Parrot_Continuation_attributes *)PMC_data(src)); } /* @@ -177,11 +185,8 @@ */ VTABLE void set_pointer(void *value) { - opcode_t * const pos = (opcode_t *)value; - Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF); - - cc->address = pos; - cc->runloop_id = INTERP->current_runloop_id; + SET_ATTR_address(INTERP, SELF, (opcode_t *)value); + SET_ATTR_runloop_id(INTERP, SELF, INTERP->current_runloop_id); } /* @@ -195,7 +200,11 @@ */ VTABLE void *get_pointer() { - return PARROT_CONTINUATION(SELF)->address; + opcode_t *address; + + GET_ATTR_address(INTERP, SELF, address); + + return address; } /* @@ -211,11 +220,19 @@ */ VTABLE INTVAL defined() { - return PARROT_CONTINUATION(SELF)->address != NULL; + opcode_t *address; + + GET_ATTR_address(INTERP, SELF, address); + + return address != NULL; } VTABLE INTVAL get_bool() { - return PARROT_CONTINUATION(SELF)->address != NULL; + opcode_t *address; + + GET_ATTR_address(INTERP, SELF, address); + + return address != NULL; } /* @@ -230,19 +247,22 @@ */ VTABLE opcode_t *invoke(void *next) { - Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF); - PMC *from_ctx = CURRENT_CONTEXT(interp); - PMC *to_ctx = cc->to_ctx; - opcode_t *pc = cc->address; - PMC *call_obj = cc->to_call_object; - PMC *from_obj = Parrot_pcc_get_signature(interp, from_ctx); + PMC * const from_obj = Parrot_pcc_get_signature(INTERP, CURRENT_CONTEXT(INTERP)); + PMC *to_ctx, *call_obj; + opcode_t *pc; + PackFile_ByteCode *seg; UNUSED(next) - Parrot_continuation_check(interp, SELF); - Parrot_continuation_rewind_environment(interp, SELF); + GET_ATTR_seg(INTERP, SELF, seg); + GET_ATTR_address(INTERP, SELF, pc); + GET_ATTR_to_ctx(INTERP, SELF, to_ctx); + GET_ATTR_to_call_object(INTERP, SELF, call_obj); + Parrot_continuation_check(INTERP, SELF); + Parrot_continuation_rewind_environment(INTERP, SELF); + if (!PMC_IS_NULL(from_obj)) { - STRING *string_sig = VTABLE_get_string(INTERP, from_obj); + STRING * const string_sig = VTABLE_get_string(INTERP, from_obj); /* If there is no string - there is no args */ if (string_sig) { PMC *raw_sig, *invalid_sig; @@ -253,13 +273,13 @@ call_obj = Parrot_pcc_build_sig_object_returns_from_op(INTERP, call_obj, Parrot_pcc_get_pmc_constant(INTERP, to_ctx, pc[1]), pc); - Parrot_pcc_fill_returns_from_continuation(interp, call_obj, raw_sig, from_obj); + Parrot_pcc_fill_returns_from_continuation(INTERP, call_obj, raw_sig, from_obj); } } /* switch segment */ - if (INTERP->code != cc->seg) - Parrot_switch_to_cs(INTERP, cc->seg, 1); + if (INTERP->code != seg) + Parrot_switch_to_cs(INTERP, seg, 1); return pc; } @@ -275,7 +295,11 @@ */ VTABLE STRING *get_string() { - return Parrot_Context_infostr(INTERP, PARROT_CONTINUATION(SELF)->to_ctx); + PMC *to_ctx; + + GET_ATTR_to_ctx(INTERP, SELF, to_ctx); + + return Parrot_Context_infostr(INTERP, to_ctx); } /* @@ -289,9 +313,12 @@ */ METHOD caller() { - Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF); - PMC *caller = Parrot_pcc_get_sub(interp, cc->to_ctx); + PMC *to_ctx, *caller; + GET_ATTR_to_ctx(INTERP, SELF, to_ctx); + + caller = Parrot_pcc_get_sub(INTERP, to_ctx); + if (!caller) caller = PMCNULL; else { @@ -315,9 +342,12 @@ */ METHOD continuation() { - Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(SELF); - PMC * const cont = Parrot_pcc_get_continuation(interp, cc->to_ctx); + PMC *to_ctx, *cont; + GET_ATTR_to_ctx(INTERP, SELF, to_ctx); + + cont = Parrot_pcc_get_continuation(INTERP, to_ctx); + if (cont) RETURN(PMC *cont); Index: src/pmc/coroutine.pmc =================================================================== --- src/pmc/coroutine.pmc (版本 43268) +++ src/pmc/coroutine.pmc (工作副本) @@ -35,21 +35,23 @@ static void print_sub_name(PARROT_INTERP, PMC *sub_pmc) { - /* It's actually a Parrot_coro, but this avoids casting warnings. */ - Parrot_Sub_attributes *co = PARROT_SUB(sub_pmc); - Interp * const tracer = (interp->pdb && interp->pdb->debugger) ? - interp->pdb->debugger : - interp; + /* It's actually a Parrot_coroutine, but this avoids casting warnings. */ + PMC *ctx; + Interp * const tracer = (interp->pdb && interp->pdb->debugger) ? + interp->pdb->debugger : + interp; - Parrot_io_eprintf(tracer, "# %s coro '%Ss'", + GETATTR_Coroutine_ctx(interp, sub_pmc, ctx); + + Parrot_io_eprintf(tracer, "# %s coroutine '%Ss'", !(PObj_get_FLAGS(sub_pmc) & SUB_FLAG_CORO_FF) ? "Calling" : "yielding from", Parrot_full_sub_name(interp, sub_pmc)); - if (co->ctx && (PObj_get_FLAGS(sub_pmc) & SUB_FLAG_CORO_FF)) { + if (ctx && (PObj_get_FLAGS(sub_pmc) & SUB_FLAG_CORO_FF)) { Parrot_io_eprintf(tracer, " to '%Ss'", Parrot_full_sub_name(interp, - Parrot_pcc_get_sub(interp, Parrot_pcc_get_caller_ctx(interp, co->ctx)))); + Parrot_pcc_get_sub(interp, Parrot_pcc_get_caller_ctx(interp, ctx)))); } Parrot_io_eprintf(tracer, "\n# "); @@ -57,9 +59,9 @@ } pmclass Coroutine extends Sub auto_attrs { + ATTR INTVAL yield; /* yield in process */ + ATTR opcode_t *address; /* next address to run - toggled each time */ ATTR PackFile_ByteCode *caller_seg; /* bytecode segment */ - ATTR opcode_t *address; /* next address to run - toggled each time */ - ATTR INTVAL yield; /* yield in process */ /* @@ -76,11 +78,9 @@ */ VTABLE void init() { - Parrot_Coroutine_attributes *attrs = PARROT_COROUTINE(SELF); + SET_ATTR_seg(INTERP, SELF, INTERP->code); + SET_ATTR_ctx(INTERP, SELF, PMCNULL); - attrs->seg = INTERP->code; - attrs->ctx = PMCNULL; - PObj_custom_mark_destroy_SETALL(SELF); } @@ -96,15 +96,17 @@ */ VTABLE PMC *clone() { + STRING *name; PMC * const ret = pmc_new(INTERP, SELF->vtable->base_type); - Parrot_Coroutine_attributes * const sub = PARROT_COROUTINE(SELF); - Parrot_Coroutine_attributes * const coro_sub = PARROT_COROUTINE(ret); PObj_custom_mark_destroy_SETALL(ret); - memcpy(coro_sub, sub, sizeof (Parrot_Coroutine_attributes)); + memcpy((Parrot_Coroutine_attributes *)PMC_data(ret), + (Parrot_Coroutine_attributes *)PMC_data(SELF), + sizeof (Parrot_Coroutine_attributes)); - coro_sub->name = Parrot_str_copy(INTERP, coro_sub->name); + GET_ATTR_name(INTERP, ret, name); + SET_ATTR_name(INTERP, ret, Parrot_str_copy(INTERP, name)); return ret; } @@ -134,92 +136,124 @@ */ VTABLE opcode_t *invoke(void *next) { + PMC *ctx; + opcode_t *dest; PackFile_ByteCode *wanted_seg; - Parrot_Coroutine_attributes * const co = PARROT_COROUTINE(SELF); - opcode_t * dest = co->address; - opcode_t * const next_op = (opcode_t *)next; - + opcode_t * const next_op = (opcode_t *)next; + if (Interp_trace_TEST(INTERP, PARROT_TRACE_SUB_CALL_FLAG)) print_sub_name(INTERP, SELF); - if (PMC_IS_NULL(co->ctx)) { - PMC * const caller_ctx = CURRENT_CONTEXT(interp); - PMC *ctx; - PMC *ccont = INTERP->current_cont; + GET_ATTR_ctx(INTERP, SELF, ctx); + if (PMC_IS_NULL(ctx)) { + PackFile_ByteCode *seg; + size_t start_offs; + const INTVAL *n_regs_used; + PMC *lex_info; + PMC * const caller_ctx = CURRENT_CONTEXT(INTERP); + PMC *ctx = Parrot_pcc_get_signature(INTERP, caller_ctx); + PMC *ccont = INTERP->current_cont; + if (ccont == NEED_CONTINUATION) - ccont = (PMC *)new_ret_continuation_pmc(interp, next_op); + ccont = (PMC *)new_ret_continuation_pmc(INTERP, next_op); if (PObj_get_FLAGS(ccont) & SUB_FLAG_TAILCALL) Parrot_ex_throw_from_c_args(INTERP, NULL, CONTROL_ERROR, - "tail call to coro not allowed"); + "tail call to coroutine not allowed"); /* first time set current sub, cont, object */ - ctx = Parrot_pcc_get_signature(INTERP, caller_ctx); if (PMC_IS_NULL(ctx)) ctx = pmc_new(INTERP, enum_class_CallContext); + CURRENT_CONTEXT(INTERP) = ctx; - Parrot_pcc_allocate_registers(INTERP, ctx, co->n_regs_used); + + GET_ATTR_n_regs_used(INTERP, SELF, n_regs_used); + Parrot_pcc_allocate_registers(INTERP, ctx, n_regs_used); Parrot_pcc_set_caller_ctx(INTERP, ctx, caller_ctx); Parrot_pcc_init_context(INTERP, ctx, caller_ctx); - co->ctx = ctx; + SET_ATTR_ctx(INTERP, SELF, ctx); - PARROT_CONTINUATION(ccont)->from_ctx = ctx; + SETATTR_Continuation_from_ctx(INTERP, ccont, ctx); + Parrot_pcc_set_sub(INTERP, ctx, SELF); Parrot_pcc_set_continuation(INTERP, ctx, ccont); - Parrot_pcc_set_object(interp, ctx, PMCNULL); + Parrot_pcc_set_object(INTERP, ctx, PMCNULL); + INTERP->current_object = PMCNULL; INTERP->current_cont = PMCNULL; + GET_ATTR_lex_info(INTERP, SELF, lex_info); + /* create pad if needed */ - if (!PMC_IS_NULL(co->lex_info)) { - const INTVAL hlltype = Parrot_get_ctx_HLL_type(interp, enum_class_LexPad); - PMC * const lexpad = pmc_new_init(INTERP, hlltype, co->lex_info); + if (!PMC_IS_NULL(lex_info)) { + const INTVAL hlltype = Parrot_get_ctx_HLL_type(INTERP, enum_class_LexPad); + PMC * const lexpad = pmc_new_init(INTERP, hlltype, lex_info); Parrot_pcc_set_lex_pad(INTERP, ctx, lexpad); VTABLE_set_pointer(INTERP, lexpad, ctx); } + GET_ATTR_seg(INTERP, SELF, seg); PObj_get_FLAGS(SELF) |= SUB_FLAG_CORO_FF; - wanted_seg = co->seg; - co->caller_seg = INTERP->code; - co->address = co->seg->base.data + co->start_offs; + wanted_seg = seg; + + GET_ATTR_start_offs(INTERP, SELF, start_offs); + SET_ATTR_caller_seg(INTERP, SELF, INTERP->code); + SET_ATTR_address(INTERP, SELF, seg->base.data + start_offs); } /* if calling the Coro we need the segment of the Coro */ else if (!(PObj_get_FLAGS(SELF) & SUB_FLAG_CORO_FF)) { - PMC * const ctx = co->ctx; - PMC * const ccont = Parrot_pcc_get_continuation(INTERP, ctx); + PackFile_ByteCode *seg; + PMC *ctx; + PMC *ccont; + GET_ATTR_ctx(INTERP, SELF, ctx); + ccont = Parrot_pcc_get_continuation(INTERP, ctx); + PObj_get_FLAGS(SELF) |= SUB_FLAG_CORO_FF; - wanted_seg = co->seg; + GET_ATTR_seg(INTERP, SELF, seg); + wanted_seg = seg; + /* remember segment of caller */ - co->caller_seg = INTERP->code; + SET_ATTR_caller_seg(INTERP, SELF, INTERP->code); + + /* and the recent call context */ - PARROT_CONTINUATION(ccont)->to_ctx = CURRENT_CONTEXT(interp); - Parrot_pcc_set_caller_ctx(interp, ctx, CURRENT_CONTEXT(interp)); + SETATTR_Continuation_to_ctx(INTERP, ccont, CURRENT_CONTEXT(INTERP)); + Parrot_pcc_set_caller_ctx(INTERP, ctx, CURRENT_CONTEXT(INTERP)); - /* set context to coro context */ - CURRENT_CONTEXT(interp) = ctx; + /* set context to coroutine context */ + CURRENT_CONTEXT(INTERP) = ctx; } else { - PMC * const ccont = Parrot_pcc_get_continuation(INTERP, co->ctx); - PMC * const ctx = PARROT_CONTINUATION(ccont)->to_ctx; - INTVAL yield; + INTVAL yield; + PMC *ccont, *ctx, *to_ctx; + PackFile_ByteCode *caller_seg; + GET_ATTR_yield(INTERP, SELF, yield); - if (! yield) + + if (!yield) Parrot_ex_throw_from_c_args(INTERP, NULL, CONTROL_ERROR, "Cannot resume dead coroutine."); + SET_ATTR_yield(INTERP, SELF, 0); + GET_ATTR_ctx(INTERP, SELF, ctx); + ccont = Parrot_pcc_get_continuation(INTERP, ctx); + + GETATTR_Continuation_to_ctx(INTERP, ccont, to_ctx); + PObj_get_FLAGS(SELF) &= ~SUB_FLAG_CORO_FF; + GET_ATTR_caller_seg(INTERP, SELF, caller_seg); + /* switch back to last remembered code seg and context */ + wanted_seg = caller_seg; - wanted_seg = co->caller_seg; - - if (PMC_IS_NULL(ctx)) { + if (PMC_IS_NULL(to_ctx)) { /* This still isn't quite right, but it beats segfaulting. See the "Call an exited coroutine" case in t/pmc/coroutine.t; the problem is that the defunct coroutine yields up one more @@ -230,12 +264,12 @@ "Cannot resume dead coroutine."); } - CURRENT_CONTEXT(interp) = ctx; + CURRENT_CONTEXT(INTERP) = to_ctx; } /* toggle address */ - dest = co->address; - co->address = (opcode_t *)next; + GET_ATTR_address(INTERP, SELF, dest); + SET_ATTR_address(INTERP, SELF, (opcode_t *)next); if (INTERP->code != wanted_seg) Parrot_switch_to_cs(INTERP, wanted_seg, 1);