Index: src/exit.c =================================================================== --- src/exit.c (revision 8478) +++ src/exit.c (working copy) @@ -73,6 +73,18 @@ /* Must write the loop this way to protect against an exit handler calling exit and re-entering this function. */ + + /* we are well "below" the runloop now, where lo_var_ptr + * is set usually - exit handlers may run some resource-hungry + * stuff like printing profile stats - a DOD run would kill + * resources - reset stacktop + * + * ARGH --leo: this damned function doesn't have an interpreter arg + * XXX FIXME - API + * + * XXX FIXME - and what about multiple interpreters - the first exit + * call would run all exit handlers + */ while (exit_handler_list) { handler_node_t *node = exit_handler_list; exit_handler_list = exit_handler_list->next; Index: src/embed.c =================================================================== --- src/embed.c (revision 8478) +++ src/embed.c (working copy) @@ -142,7 +142,7 @@ Parrot_set_trace(Interp *interpreter, UINTVAL flag) { - interpreter->ctx.trace_flags |= flag; + CONTEXT(interpreter->ctx)->trace_flags |= flag; Interp_core_SET(interpreter, PARROT_SLOW_CORE); } @@ -175,7 +175,7 @@ void Parrot_clear_trace(Interp *interpreter, UINTVAL flag) { - interpreter->ctx.trace_flags &= ~flag; + CONTEXT(interpreter->ctx)->trace_flags &= ~flag; } /* @@ -210,7 +210,7 @@ UINTVAL Parrot_test_trace(Interp *interpreter, UINTVAL flag) { - return interpreter->ctx.trace_flags & flag; + return CONTEXT(interpreter->ctx)->trace_flags & flag; } /* @@ -486,10 +486,10 @@ * XXX for now still place in P1 until return opcodes are everywhere */ REG_PMC(1) = - interpreter->ctx.current_cont = + CONTEXT(interpreter->ctx)->current_cont = new_ret_continuation_pmc(interpreter, NULL); /* clear segment to denote the end of chain */ - PMC_cont(interpreter->ctx.current_cont)->seg = NULL; + PMC_cont(CONTEXT(interpreter->ctx)->current_cont)->seg = NULL; REG_INT(3) = 1; /* pdd03 - one PMC arg, if code really inspects that */ } @@ -727,8 +727,8 @@ code_start = (opcode_t*) sub->seg->base.data; offs = sub->address - code_start; if (offs == interpreter->resume_offset) { - interpreter->ctx.current_sub = sub_pmc; - interpreter->ctx.current_HLL = sub->HLL_id; + CONTEXT(interpreter->ctx)->current_sub = sub_pmc; + CONTEXT(interpreter->ctx)->current_HLL = sub->HLL_id; return; } break; @@ -738,7 +738,7 @@ * if we didn't find anything put an Undef PMC into current_sub */ sub_pmc = pmc_new(interpreter, enum_class_Undef); - interpreter->ctx.current_sub = sub_pmc; + CONTEXT(interpreter->ctx)->current_sub = sub_pmc; } /* Index: src/hll.c =================================================================== --- src/hll.c (revision 8478) +++ src/hll.c (working copy) @@ -163,7 +163,7 @@ INTVAL hll_id, n; hll_info = interpreter->HLL_info; - hll_id = interpreter->ctx.current_HLL; + hll_id = CONTEXT(interpreter->ctx)->current_HLL; if (hll_id <= 0) return core_type; n = VTABLE_elements(interpreter, hll_info); Index: src/runops_cores.c =================================================================== --- src/runops_cores.c (revision 8478) +++ src/runops_cores.c (working copy) @@ -148,7 +148,7 @@ trace_op(interpreter, code_start, code_end, pc); } while (pc) {/* && pc >= code_start && pc < code_end) {*/ - interpreter->ctx.current_pc = pc; + CONTEXT(interpreter->ctx)->current_pc = pc; DO_OP(pc, interpreter); @@ -219,7 +219,7 @@ } while (pc) {/* && pc >= code_start && pc < code_end) */ - interpreter->ctx.current_pc = pc; + CONTEXT(interpreter->ctx)->current_pc = pc; profile->cur_op = cur_op = *pc + PARROT_PROF_EXTRA; profile->data[cur_op].numcalls++; profile->starttime = Parrot_floatval_time(); Index: src/lexical.c =================================================================== --- src/lexical.c (revision 8478) +++ src/lexical.c (working copy) @@ -66,7 +66,7 @@ PMC * scratchpad_get_current(Interp * interp) { - return (PMC *)stack_peek(interp, interp->ctx.pad_stack, NULL); + return (PMC *)stack_peek(interp, CONTEXT(interp->ctx)->pad_stack, NULL); } /* Index: src/register.c =================================================================== --- src/register.c (revision 8478) +++ src/register.c (working copy) @@ -44,25 +44,19 @@ */ void -setup_register_stacks(Parrot_Interp interpreter, struct Parrot_Context *ctx) +setup_register_stacks(Parrot_Interp interpreter) { - ctx->int_reg_stack = register_new_stack(interpreter, + CONTEXT(interpreter->ctx)->int_reg_stack = register_new_stack(interpreter, "IntReg_", sizeof(struct IRegFrame)); - ctx->string_reg_stack = register_new_stack(interpreter, + CONTEXT(interpreter->ctx)->string_reg_stack = register_new_stack(interpreter, "StringReg_", sizeof(struct SRegFrame)); - ctx->num_reg_stack = register_new_stack(interpreter, + CONTEXT(interpreter->ctx)->num_reg_stack = register_new_stack(interpreter, "NumReg_", sizeof(struct NRegFrame)); - ctx->pmc_reg_stack = register_new_stack(interpreter, + CONTEXT(interpreter->ctx)->pmc_reg_stack = register_new_stack(interpreter, "PMCReg_", sizeof(struct PRegFrame)); - - ctx->reg_stack = register_new_stack(interpreter, - "Register_", sizeof(struct parrot_regs_t)); - - ctx->bp = (struct parrot_regs_t *)STACK_DATAP(ctx->reg_stack); - } Index: src/debug.c =================================================================== --- src/debug.c (revision 8478) +++ src/debug.c (working copy) @@ -2181,7 +2181,7 @@ PDB_print_stack_int(Interp *interpreter, const char *command) { unsigned long depth = 0, i = 0; - Stack_Chunk_t *chunk = interpreter->ctx.int_reg_stack; + Stack_Chunk_t *chunk = CONTEXT(interpreter->ctx)->int_reg_stack; valid_chunk(interpreter, command, chunk, depth, i); @@ -2206,7 +2206,7 @@ PDB_print_stack_num(Interp *interpreter, const char *command) { unsigned long depth = 0, i = 0; - Stack_Chunk_t *chunk = interpreter->ctx.num_reg_stack; + Stack_Chunk_t *chunk = CONTEXT(interpreter->ctx)->num_reg_stack; valid_chunk(interpreter, command, chunk, depth, i); @@ -2231,7 +2231,7 @@ PDB_print_stack_string(Interp *interpreter, const char *command) { unsigned long depth = 0, i = 0; - Stack_Chunk_t *chunk = interpreter->ctx.string_reg_stack; + Stack_Chunk_t *chunk = CONTEXT(interpreter->ctx)->string_reg_stack; valid_chunk(interpreter, command, chunk, depth, i); @@ -2256,7 +2256,7 @@ PDB_print_stack_pmc(Interp *interpreter, const char *command) { unsigned long depth = 0, i = 0; - Stack_Chunk_t *chunk = interpreter->ctx.pmc_reg_stack; + Stack_Chunk_t *chunk = CONTEXT(interpreter->ctx)->pmc_reg_stack; valid_chunk(interpreter, command, chunk, depth, i); @@ -2311,7 +2311,7 @@ PDB_print_user_stack(Interp *interpreter, const char *command) { long depth = 0; - Stack_Chunk_t *chunk = interpreter->ctx.user_stack; + Stack_Chunk_t *chunk = CONTEXT(interpreter->ctx)->user_stack; Stack_Entry_t *entry; if (*command) { @@ -2954,6 +2954,7 @@ PMC *sub; PMC *old = PMCNULL; int rec_level = 0; + parrot_context_t ctx; /* information about the current sub */ sub = interpinfo_p(interpreter, CURRENT_SUB); @@ -2964,17 +2965,23 @@ } /* backtrace: follow the continuation chain */ - sub = interpinfo_p(interpreter, CURRENT_CONT); - while (!PMC_IS_NULL(sub) && - sub->vtable->base_type == enum_class_Continuation && - NULL != (str = Parrot_Context_infostr(interpreter, - &PMC_cont(sub)->ctx)) ) { + ctx = interpreter->ctx; + while (1) { + sub = CONTEXT(ctx)->current_cont; + if (!sub) + break; + str = Parrot_Context_infostr(interpreter, + &PMC_cont(sub)->ctx); + if (!str) + break; /* recursion detection */ if (!PMC_IS_NULL(old) && PMC_cont(old) && - PMC_cont(old)->ctx.current_pc == PMC_cont(sub)->ctx.current_pc && - PMC_cont(old)->ctx.current_sub == PMC_cont(sub)->ctx.current_sub) { - ++rec_level; + CONTEXT(PMC_cont(old)->ctx)->current_pc == + CONTEXT(PMC_cont(sub)->ctx)->current_pc && + CONTEXT(PMC_cont(old)->ctx)->current_sub == + CONTEXT(PMC_cont(sub)->ctx)->current_sub) { + ++rec_level; } else if (rec_level != 0) { PIO_eprintf(interpreter, "... call repeated %d times\n", rec_level); rec_level = 0; @@ -2986,7 +2993,9 @@ /* get the next Continuation */ old = sub; - sub = PMC_cont(sub)->ctx.current_cont; + ctx.rctx = CONTEXT(ctx)->prev; + if (!ctx.rctx || !CONTEXT(ctx)->prev) + break; } if (rec_level != 0) { PIO_eprintf(interpreter, "... call repeated %d times\n", rec_level); Index: src/global.c =================================================================== --- src/global.c (revision 8478) +++ src/global.c (working copy) @@ -200,7 +200,7 @@ pad = scratchpad_get_current(interpreter); g = scratchpad_find(interpreter, pad, name); if (!g) { - current_sub = interpreter->ctx.current_sub; + current_sub = CONTEXT(interpreter->ctx)->current_sub; if (current_sub && (name_space = PMC_sub(current_sub)->name_space)) Index: src/dod.c =================================================================== --- src/dod.c (revision 8478) +++ src/dod.c (working copy) @@ -302,12 +302,12 @@ /* * mark current context stuff */ - if (interpreter->ctx.current_sub) - pobject_lives(interpreter, (PObj*)interpreter->ctx.current_sub); - if (interpreter->ctx.current_cont) - pobject_lives(interpreter, (PObj*)interpreter->ctx.current_cont); - if (interpreter->ctx.current_object) - pobject_lives(interpreter, (PObj*)interpreter->ctx.current_object); + if (CONTEXT(interpreter->ctx)->current_sub) + pobject_lives(interpreter, (PObj*)CONTEXT(interpreter->ctx)->current_sub); + if (CONTEXT(interpreter->ctx)->current_cont) + pobject_lives(interpreter, (PObj*)CONTEXT(interpreter->ctx)->current_cont); + if (CONTEXT(interpreter->ctx)->current_object) + pobject_lives(interpreter, (PObj*)CONTEXT(interpreter->ctx)->current_object); /* * mark vtable->data @@ -1264,6 +1264,7 @@ Parrot_do_dod_run(Interp *interpreter, UINTVAL flags) { interpreter->arena_base->do_dod_run(interpreter, flags); + parrot_gc_context(interpreter); } /* Index: src/inter_run.c =================================================================== --- src/inter_run.c (revision 8478) +++ src/inter_run.c (working copy) @@ -40,7 +40,7 @@ { volatile size_t offset = offs; - interpreter->ctx.runloop_level++; + CONTEXT(interpreter->ctx)->runloop_level++; /* * STACKED_EXCEPTIONS are necessary to catch exceptions in reentered * run loops, e.g. if a delegate methods throws an exception @@ -51,7 +51,7 @@ { new_internal_exception(interpreter); interpreter->exceptions->runloop_level = - interpreter->ctx.runloop_level; + CONTEXT(interpreter->ctx)->runloop_level; if (setjmp(interpreter->exceptions->destination)) { /* an exception was thrown */ offset = handle_exception(interpreter); @@ -74,7 +74,7 @@ * handler */ if (1 || interpreter->exceptions->runloop_level == - interpreter->ctx.runloop_level) { + CONTEXT(interpreter->ctx)->runloop_level) { /* if we are coming from an exception and it was thrown deeper * in a nested run loop, we just leave this loop */ @@ -87,7 +87,7 @@ if (STACKED_EXCEPTIONS) { free_internal_exception(interpreter); } - interpreter->ctx.runloop_level--; + CONTEXT(interpreter->ctx)->runloop_level--; /* * not yet - this needs classifying of exceptions and handlers * so that only an exit handler does catch this exception @@ -113,13 +113,13 @@ struct parrot_regs_t * Parrot_runops_fromc(Parrot_Interp interpreter, PMC *sub) { - PMC *ret_c, *p1; + PMC *ret_c; opcode_t offset, *dest; struct parrot_regs_t *bp; /* we need one return continuation with a NULL offset */ - p1 = REG_PMC(1); - REG_PMC(1) = ret_c = new_ret_continuation_pmc(interpreter, NULL); + interpreter->current_cont = ret_c = + new_ret_continuation_pmc(interpreter, NULL); #if GC_VERBOSE PObj_report_SET(ret_c); /* s. also dod.c */ #endif @@ -133,7 +133,6 @@ bp = interpreter->ctx.bp; offset = dest - interpreter->code->base.data; runops(interpreter, offset); - REG_PMC(1) = p1; return bp; } @@ -213,18 +212,18 @@ PMC *p3 = PMCNULL; int clear_p3, need_p3, max; PMC *arg; + parrot_context_t old_ctx; for (i = 0; i < 4; i++) { next[i] = 5; count[i] = 0; } - bp = interpreter->ctx.bp; + old_ctx = interpreter->ctx; ret_c = new_ret_continuation_pmc(interpreter, NULL); - interpreter->ctx.current_sub = sub; - interpreter->ctx.current_cont = ret_c; - interpreter->ctx.current_object = obj; + interpreter->current_object = obj; dest = VTABLE_invoke(interpreter, sub, NULL); + CONTEXT(interpreter->ctx)->current_cont = ret_c; if (!dest) internal_exception(1, "Subroutine returned a NULL address"); @@ -307,15 +306,14 @@ } if (any_registers) { - struct parrot_regs_t *new_bp; - new_bp = interpreter->ctx.bp; + parrot_context_t new_ctx = interpreter->ctx; /* need old context */ - interpreter->ctx.bp = bp; + interpreter->ctx = old_ctx; /* clone sets key values according to refered * register items */ arg = VTABLE_clone(interpreter, arg); - interpreter->ctx.bp = new_bp; + interpreter->ctx = new_ctx; } } if (next[2] == 16) @@ -409,23 +407,15 @@ { struct parrot_regs_t *bp; opcode_t offset, *dest; - PMC *p1, *p2; - STRING *s0; - p1 = REG_PMC(1); - p2 = REG_PMC(2); - s0 = REG_STR(0); - REG_PMC(1) = new_ret_continuation_pmc(interpreter, NULL); - interpreter->ctx.current_object = obj; + interpreter->current_cont = new_ret_continuation_pmc(interpreter, NULL); + interpreter->current_object = obj; dest = VTABLE_invoke(interpreter, sub, (void*)1); if (!dest) internal_exception(1, "Subroutine returned a NULL address"); bp = interpreter->ctx.bp; offset = dest - interpreter->code->base.data; runops(interpreter, offset); - REG_PMC(1) = p1; - REG_PMC(2) = p2; - REG_STR(0) = s0; return set_retval(interpreter, 0, bp); } Index: src/stack_common.c =================================================================== --- src/stack_common.c (revision 8478) +++ src/stack_common.c (working copy) @@ -124,70 +124,6 @@ /* =item C - -Like above for the register frame stack. If possible get new chunk from -the frame stack cache. - -=item - -Add a register frame to to the register frame stack cache. - -=cut - -*/ - -void* -new_register_frame(Interp* interpreter, Stack_Chunk_t **stack_p) -{ - Stack_Chunk_t *chunk = *stack_p, *new_chunk; - Caches *ic = interpreter->caches; - int i; - struct parrot_regs_t *bp; - - if (ic->frame_cache) { - /* - * frame_cache holds the stack top, next in chain is in bufstart - */ - new_chunk = ic->frame_cache; - ic->frame_cache = PObj_bufstart(ic->frame_cache); - } - else { - new_chunk = cst_new_stack_chunk(interpreter, chunk); - } - new_chunk->prev = chunk; - *stack_p = new_chunk; - /* - * W have to clean objects - register marking - * with junk PMC or STRING pointers fails. We need an upper bound - * of used registers per kind, so that we mark only valid registers - * This also means, that the register allocator has to allocate - * always from reg 0 up. - * Still better is to just allocate smaller chunks if needed - */ - bp = (struct parrot_regs_t *)STACK_DATAP(new_chunk); - for (i = 0; i < NUM_REGISTERS; i++) { - BP_REG_PMC(bp, i) = PMCNULL; - BP_REG_STR(bp, i) = NULL; - } - - return bp; -} - -void -add_to_fp_cache(Interp* interpreter, Stack_Chunk_t *stack_p) -{ - Caches *ic = interpreter->caches; - if (ic->frame_cache) - PObj_bufstart(ic->frame_cache) = ic->frame_cache; - ic->frame_cache = stack_p; - PObj_bufstart(stack_p) = NULL; -} - -/* - -=item C Return a pointer, where new entries are poped off. Index: src/generic_register.c =================================================================== --- src/generic_register.c (revision 8478) +++ src/generic_register.c (working copy) @@ -48,7 +48,7 @@ REG_PUSH(Interp *interpreter, void *where) { void* top; - top = stack_prepare_push(interpreter, &interpreter->ctx.REG_STACK); + top = stack_prepare_push(interpreter, &CONTEXT(interpreter->ctx)->REG_STACK); Parrot_memcpy_aligned(top, where, sizeof(struct REG_FRAME)); } @@ -67,7 +67,7 @@ REG_POP(Interp *interpreter, void *where) { void* top; - top = stack_prepare_pop(interpreter, &interpreter->ctx.REG_STACK); + top = stack_prepare_pop(interpreter, &CONTEXT(interpreter->ctx)->REG_STACK); Parrot_memcpy_aligned(where, top, sizeof(struct REG_FRAME)); } Index: src/objects.c =================================================================== --- src/objects.c (revision 8478) +++ src/objects.c (working copy) @@ -933,14 +933,6 @@ void mark_object_cache(Interp* interpreter) { - /* mark register frame cache */ - Stack_Chunk_t *chunk = interpreter->caches->frame_cache; - - while (chunk) { - pobject_lives(interpreter, (PObj*)chunk); - chunk = PObj_bufstart(chunk); - } - mark_retc_cache(interpreter); } void @@ -950,8 +942,6 @@ mc = interpreter->caches = mem_sys_allocate_zeroed(sizeof(*mc)); SET_NULL(mc->idx); - SET_NULL(mc->frame_cache); - SET_NULL(mc->retc_cache); } #define TBL_SIZE_MASK 0x1ff /* x bits 2..10 */ @@ -1163,7 +1153,7 @@ void Parrot_note_method_offset(Interp* interpreter, UINTVAL offset, PMC *method) { - interpreter->ctx.current_class_offset = offset; + CONTEXT(interpreter->ctx)->current_class_offset = offset; } /* @@ -1208,7 +1198,21 @@ if (VTABLE_exists_keyed_str(interpreter, attr_hash, full_attr_name)) internal_exception(1, "Attribute '%s' already exists", string_to_cstring(interpreter, full_attr_name)); +#if 0 + if (VTABLE_exists_keyed_str(interpreter, attr_hash, attr)) { + /* make old short name invisible */ + static int anon_count; + STRING *mangled; + INTVAL old_idx = VTABLE_get_integer_keyed_str(interpreter, + attr_hash, attr); + VTABLE_delete_keyed_str(interpreter, attr_hash, attr); + mangled = Parrot_sprintf_c(interpreter, "%Ss%c%canon_%d", + attr, 0, 0, ++anon_count); + VTABLE_set_integer_keyed_str(interpreter, attr_hash, + mangled, old_idx); + } +#endif /* * TODO check if someone is trying to add attributes to a parent class * while there are already child class attrs Index: src/inter_misc.c =================================================================== --- src/inter_misc.c (revision 8478) +++ src/inter_misc.c (working copy) @@ -240,15 +240,15 @@ PMC *cont; switch (what) { case CURRENT_SUB: - return interpreter->ctx.current_sub; + return CONTEXT(interpreter->ctx)->current_sub; case CURRENT_CONT: - cont = interpreter->ctx.current_cont; + cont = CONTEXT(interpreter->ctx)->current_cont; if (!PMC_IS_NULL(cont) && cont->vtable->base_type == enum_class_RetContinuation) return VTABLE_clone(interpreter, cont); return cont; case CURRENT_OBJECT: - return interpreter->ctx.current_object; + return CONTEXT(interpreter->ctx)->current_object; case NAMESPACE_ROOT: /* XXX */ return interpreter->globals->stash_hash; case CURRENT_LEXPAD: @@ -265,7 +265,7 @@ { switch (what) { case CURRENT_METHOD: - return interpreter->ctx.current_method; + return CONTEXT(interpreter->ctx)->current_method; default: /* or a warning only? */ internal_exception(UNIMPLEMENTED, "illegal argument in interpinfo"); Index: src/inter_create.c =================================================================== --- src/inter_create.c (revision 8478) +++ src/inter_create.c (working copy) @@ -75,7 +75,156 @@ } /* + * Context and register frame layout + * + * +----------+--------------------------+ + * | context | registers + + * +----------+--------------------------+ + * ^ + * | + * ctx.bp pointer + * + * Registers are addressed as usual via the register base pointer ctx.bp. + * Context variables are to the "left" of the pointer and accessible with + * the ctx union member ctx.rctx e.g. ctx.rctx[-1].current_sub + * + * The macro CTX_VAR hides these details + * + * + * Context and register frame allocation + * + * Both are allocated in one contiguous piece of memory carved out from + * interpreter->ctx_mem. The pointer C holds the next usable + * location. With (full) continuations the C pointer can't be + * moved below the C, which is the highest context pointer + * of all continuations. + * + * TODO GC has to lower this threshold when collecting continuations. + */ +#define CTX_ALLOC_SIZE 0x20000 + +static void +new_context_mem(Interp *interpreter, context_mem *ctx_mem) +{ + ctx_mem->data = mem_sys_allocate(CTX_ALLOC_SIZE); + ctx_mem->free = ctx_mem->data + ALIGNED_CTX_SIZE; + ctx_mem->threshold = NULL; + ctx_mem->prev = NULL; +} + +static void +destroy_context(Interp *interpreter) +{ + context_mem *ctx_mem, *prev; + + mem_sys_free(interpreter->ctx_mem.data); + for (ctx_mem = interpreter->ctx_mem.prev; ctx_mem; ) { + prev = ctx_mem->prev; + mem_sys_free(ctx_mem->data); + mem_sys_free(ctx_mem); + ctx_mem = prev; + } +} + +static void +create_context(Interp *interpreter) +{ + new_context_mem(interpreter, &interpreter->ctx_mem); + LVALUE_CAST(char *, interpreter->ctx.bp) = interpreter->ctx_mem.free; + memset(CONTEXT(interpreter->ctx), 0, + sizeof(struct Parrot_Context)); + CONTEXT(interpreter->ctx)->prev = NULL; +} + +void +parrot_gc_context(Interp *interpreter) +{ + parrot_context_t ctx; + + if (!interpreter->ctx_mem.threshold) + return; + LVALUE_CAST(char *, ctx.bp) = interpreter->ctx_mem.threshold; + /* TODO */ +} + +void +Parrot_alloc_context(Interp *interpreter) +{ + + parrot_context_t ctx; + struct parrot_regs_t *bp; + size_t used; + int i; + + /* for now still use 32 regs fixed chunks */ + size_t to_alloc = sizeof(struct parrot_regs_t) + ALIGNED_CTX_SIZE; + + used = interpreter->ctx_mem.free - interpreter->ctx_mem.data; + if (used + sizeof(struct parrot_regs_t) + to_alloc >= CTX_ALLOC_SIZE ) { + /* trigger a DOD run to reuse ctx hel by dead continuations */ + if (interpreter->ctx_mem.threshold) { + Parrot_do_dod_run(interpreter, DOD_trace_stack_FLAG); + used = interpreter->ctx_mem.free - interpreter->ctx_mem.data; + } + if (used + sizeof(struct parrot_regs_t) + + to_alloc >= CTX_ALLOC_SIZE ) { + context_mem *ctx_mem = mem_sys_allocate(sizeof(context_mem)); + memcpy(ctx_mem, &interpreter->ctx_mem, sizeof(context_mem)); + ctx_mem->prev = NULL; + new_context_mem(interpreter, &interpreter->ctx_mem); + interpreter->ctx_mem.prev = ctx_mem; + interpreter->ctx_mem.free -= to_alloc; /* is incremented first */ + } + } + ctx = interpreter->ctx; + interpreter->ctx_mem.free += to_alloc; + LVALUE_CAST(char *, interpreter->ctx.bp) = interpreter->ctx_mem.free; + memcpy(CONTEXT(interpreter->ctx), + CONTEXT(ctx), sizeof(struct Parrot_Context)); + CONTEXT(interpreter->ctx)->prev = ctx.rctx; + + /* NULL out registers */ + bp = interpreter->ctx.bp; + for (i = 0; i < NUM_REGISTERS; i++) { + BP_REG_PMC(bp, i) = PMCNULL; + BP_REG_STR(bp, i) = NULL; + } +} + +void +Parrot_free_context(Interp *interpreter, parrot_context_t *ctxp, int re_use) +{ + + struct Parrot_Context *prev; + size_t to_alloc = sizeof(struct parrot_regs_t) + ALIGNED_CTX_SIZE; + parrot_context_t ctx = *ctxp; + + prev = CONTEXT(ctx)->prev; + if (!prev) { + /* returning from main */ + return; + } + CONTEXT(ctx)->prev = NULL; + if (re_use && (char *)ctx.bp == interpreter->ctx_mem.free && + interpreter->ctx_mem.free > interpreter->ctx_mem.threshold) { + interpreter->ctx_mem.free -= to_alloc; + } + else { + /* mark this ctx area dead */ + if (interpreter->ctx_mem.threshold == (char *)ctx.bp) + interpreter->ctx_mem.threshold -= to_alloc; + else + *(void**)&CONTEXT(ctx)->prev = (void*) 0xdeaddead; + if ((char *)ctx.bp == interpreter->ctx_mem.free && + interpreter->ctx_mem.free > interpreter->ctx_mem.threshold) { + interpreter->ctx_mem.free -= to_alloc; + } + } +} + +/* + =item C @@ -120,6 +269,7 @@ MUTEX_INIT(interpreter_array_mutex); MUTEX_INIT(class_count_mutex); } + create_context(interpreter); interpreter->resume_flag = RESUME_INITIAL; interpreter->recursion_limit = 1000; @@ -176,27 +326,27 @@ /* allocate stack chunk cache */ stack_system_init(interpreter); /* Set up the initial register chunks */ - setup_register_stacks(interpreter, &interpreter->ctx); + setup_register_stacks(interpreter); Parrot_clear_s(interpreter); Parrot_clear_p(interpreter); /* Stack for lexical pads */ - interpreter->ctx.pad_stack = new_stack(interpreter, "Pad"); + CONTEXT(interpreter->ctx)->pad_stack = new_stack(interpreter, "Pad"); /* Need a user stack */ - interpreter->ctx.user_stack = new_stack(interpreter, "User"); + CONTEXT(interpreter->ctx)->user_stack = new_stack(interpreter, "User"); /* And a control stack */ - interpreter->ctx.control_stack = new_stack(interpreter, "Control"); + CONTEXT(interpreter->ctx)->control_stack = new_stack(interpreter, "Control"); /* A regex stack would be nice too. */ - interpreter->ctx.intstack = intstack_new(interpreter); + CONTEXT(interpreter->ctx)->intstack = intstack_new(interpreter); /* clear context introspection vars */ - SET_NULL_P(interpreter->ctx.current_sub, PMC*); - SET_NULL_P(interpreter->ctx.current_cont, PMC*); - SET_NULL_P(interpreter->ctx.current_object, PMC*); + SET_NULL_P(CONTEXT(interpreter->ctx)->current_sub, PMC*); + SET_NULL_P(CONTEXT(interpreter->ctx)->current_cont, PMC*); + SET_NULL_P(CONTEXT(interpreter->ctx)->current_object, PMC*); /* Load the core op func and info tables */ interpreter->op_lib = PARROT_CORE_OPLIB_INIT(1); @@ -210,7 +360,7 @@ /* Set up defaults for line/package/file */ interpreter->current_file = string_make(interpreter, "(unknown file)", 14, NULL, 0); - interpreter->ctx.current_package = + CONTEXT(interpreter->ctx)->current_package = string_make(interpreter, "(unknown package)", 18, NULL, 0); SET_NULL_P(interpreter->code, struct PackFile *); @@ -390,6 +540,8 @@ Parrot_destroy_vtable(interpreter, Parrot_base_vtables[i]); mmd_destroy(interpreter); + destroy_context(interpreter); + if (interpreter->profile) { mem_sys_free(interpreter->profile->data); interpreter->profile->data = NULL; @@ -400,11 +552,11 @@ /* deinit op_lib */ (void) PARROT_CORE_OPLIB_INIT(0); - stack_destroy(interpreter->ctx.pad_stack); - stack_destroy(interpreter->ctx.user_stack); - stack_destroy(interpreter->ctx.control_stack); + stack_destroy(CONTEXT(interpreter->ctx)->pad_stack); + stack_destroy(CONTEXT(interpreter->ctx)->user_stack); + stack_destroy(CONTEXT(interpreter->ctx)->control_stack); /* intstack */ - intstack_free(interpreter, interpreter->ctx.intstack); + intstack_free(interpreter, CONTEXT(interpreter->ctx)->intstack); /* predefined exceptions */ mem_sys_free(interpreter->exception_list); Index: src/thread.c =================================================================== --- src/thread.c (revision 8478) +++ src/thread.c (working copy) @@ -119,7 +119,7 @@ */ ret_c = pmc_new(d, enum_class_RetContinuation); INTERP_REG_PMC(d, 1) = /* XXX remove when done pdd03 */ - d->ctx.current_cont = ret_c; + CONTEXT(d->ctx)->current_cont = ret_c; } /* @@ -161,11 +161,8 @@ pt_thread_prepare_for_run(interpreter, interp); /* * set regs according to pdd03 - * P0 = sub, P2 = object - * P5 is first argument */ - REG_PMC(0) = sub; - REG_PMC(2) = dest_interp; + interpreter->current_object = dest_interp; /* * create a joinable thread */ Index: src/mmd.c =================================================================== --- src/mmd.c (revision 8478) +++ src/mmd.c (working copy) @@ -1962,12 +1962,12 @@ static int mmd_search_package(Interp *interpreter, STRING *meth, PMC *arg_tuple, PMC *cl) { - /* STRING *name_space = interpreter->ctx.current_package; */ + /* STRING *name_space = CONTEXT(interpreter->ctx)->current_package; */ PMC *pmc; PMC *current_sub; PMC *name_space; - current_sub = interpreter->ctx.current_sub; + current_sub = CONTEXT(interpreter->ctx)->current_sub; if (!current_sub || !VTABLE_defined(interpreter, current_sub)) return 0; name_space = PMC_sub(current_sub)->name_space; Index: src/exceptions.c =================================================================== --- src/exceptions.c (revision 8478) +++ src/exceptions.c (working copy) @@ -156,7 +156,7 @@ { if (handler->vtable->base_type != enum_class_Exception_Handler) PANIC("Tried to set_eh a non Exception_Handler"); - stack_push(interpreter, &interpreter->ctx.control_stack, handler, + stack_push(interpreter, &CONTEXT(interpreter->ctx)->control_stack, handler, STACK_ENTRY_PMC, STACK_CLEANUP_NULL); } @@ -178,14 +178,14 @@ const_string(interpreter, "Sub"))) { internal_exception(1, "Tried to push a non Sub PMC action"); } - stack_push(interpreter, &interpreter->ctx.control_stack, sub, + stack_push(interpreter, &CONTEXT(interpreter->ctx)->control_stack, sub, STACK_ENTRY_ACTION, run_cleanup_action); } void Parrot_push_mark(Interp * interpreter, INTVAL mark) { - stack_push(interpreter, &interpreter->ctx.control_stack, &mark, + stack_push(interpreter, &CONTEXT(interpreter->ctx)->control_stack, &mark, STACK_ENTRY_MARK, STACK_CLEANUP_NULL); } @@ -194,10 +194,10 @@ { Stack_Entry_t *e; do { - e = stack_entry(interpreter, interpreter->ctx.control_stack, 0); + e = stack_entry(interpreter, CONTEXT(interpreter->ctx)->control_stack, 0); if (!e) internal_exception(1, "mark not found"); - (void)stack_pop(interpreter, &interpreter->ctx.control_stack, + (void)stack_pop(interpreter, &CONTEXT(interpreter->ctx)->control_stack, NULL, e->entry_type); if (e->entry_type == STACK_ENTRY_MARK) { if (UVal_int(e->entry) == mark) @@ -230,7 +230,7 @@ message = VTABLE_get_string_keyed_int(interpreter, exception, 0); do { Stack_Entry_t *e = stack_entry(interpreter, - interpreter->ctx.control_stack, 0); + CONTEXT(interpreter->ctx)->control_stack, 0); if (!e) break; if (e->entry_type == STACK_ENTRY_ACTION) { @@ -241,9 +241,10 @@ */ PMC *sub = UVal_pmc(e->entry); e->cleanup = STACK_CLEANUP_NULL; + Parrot_alloc_context(interpreter); Parrot_runops_fromc_args(interpreter, sub, "vI", 1); } - (void)stack_pop(interpreter, &interpreter->ctx.control_stack, + (void)stack_pop(interpreter, &CONTEXT(interpreter->ctx)->control_stack, NULL, e->entry_type); if (e->entry_type == STACK_ENTRY_PMC) { handler = UVal_pmc(e->entry); @@ -319,11 +320,11 @@ Stack_entry_type type; PMC *handler; - handler = stack_peek(interpreter, interpreter->ctx.control_stack, &type); + handler = stack_peek(interpreter, CONTEXT(interpreter->ctx)->control_stack, &type); if (type != STACK_ENTRY_PMC || handler->vtable->base_type != enum_class_Exception_Handler) return; /* no exception on TOS */ - (void)stack_pop(interpreter, &interpreter->ctx.control_stack, NULL, + (void)stack_pop(interpreter, &CONTEXT(interpreter->ctx)->control_stack, NULL, STACK_ENTRY_PMC); } Index: src/stacks.c =================================================================== --- src/stacks.c (revision 8478) +++ src/stacks.c (working copy) @@ -150,7 +150,7 @@ /* For negative depths, look from the bottom of the stack up. */ if (depth < 0) { - depth = stack_height(interpreter, interpreter->ctx.user_stack) + depth; + depth = stack_height(interpreter, CONTEXT(interpreter->ctx)->user_stack) + depth; if (depth < 0) return NULL; offset = (size_t)depth; @@ -363,7 +363,7 @@ /* We don't mind the extra call, so we do this: (previous comment * said we *do* mind, but I say let the compiler decide) */ void *dest; - (void)stack_pop(interpreter, &interpreter->ctx.control_stack, + (void)stack_pop(interpreter, &CONTEXT(interpreter->ctx)->control_stack, &dest, STACK_ENTRY_DESTINATION); return dest; } Index: src/sub.c =================================================================== --- src/sub.c (revision 8478) +++ src/sub.c (working copy) @@ -24,42 +24,8 @@ /* =item C +mark_context(Interp* interpreter, parrot_context_t* ctx)> -Save the current "context" of interpreter. - -=cut - -*/ - -void -save_context(Interp *interp, struct Parrot_Context *ctx) -{ - memcpy(ctx, &interp->ctx, sizeof(*ctx)); -} - -/* - -=item C - -Set context of interpreter from a context buffer. - -=cut - -*/ - -void -restore_context(Interp *interp, struct Parrot_Context *ctx) -{ - memcpy(&interp->ctx, ctx, sizeof(*ctx)); -} - -/* - -=item C - Marks the context C<*ctx>. =cut @@ -67,34 +33,52 @@ */ void -mark_context(Interp* interpreter, struct Parrot_Context* ctx) +mark_context(Interp* interpreter, parrot_context_t* ctxp) { PObj *obj; + parrot_context_t ctx = *ctxp; + int i, n; + struct parrot_regs_t *regs; - mark_stack(interpreter, ctx->pad_stack); - mark_stack(interpreter, ctx->user_stack); - mark_stack(interpreter, ctx->control_stack); - mark_register_stack(interpreter, ctx->int_reg_stack); - mark_register_stack(interpreter, ctx->num_reg_stack); - mark_string_register_stack(interpreter, ctx->string_reg_stack); - mark_pmc_register_stack(interpreter, ctx->pmc_reg_stack); - mark_reg_stack(interpreter, ctx->reg_stack); - - obj = (PObj*)ctx->current_sub; + mark_stack(interpreter, CONTEXT(ctx)->pad_stack); + mark_stack(interpreter, CONTEXT(ctx)->user_stack); + mark_stack(interpreter, CONTEXT(ctx)->control_stack); + mark_register_stack(interpreter, CONTEXT(ctx)->int_reg_stack); + mark_register_stack(interpreter, CONTEXT(ctx)->num_reg_stack); + mark_string_register_stack(interpreter, CONTEXT(ctx)->string_reg_stack); + mark_pmc_register_stack(interpreter, CONTEXT(ctx)->pmc_reg_stack); + obj = (PObj*)CONTEXT(ctx)->current_sub; if (obj) pobject_lives(interpreter, obj); - obj = (PObj*)ctx->current_object; + obj = (PObj*)CONTEXT(ctx)->current_object; if (obj) pobject_lives(interpreter, obj); - obj = (PObj*)ctx->current_cont; + /* the current continuation in the interpreter has + * to be marked too in the call sequence currently + * as e.g. a MMD search could need resources + * and GC the continuation + */ + obj = (PObj*)interpreter->current_cont; if (obj && !PObj_live_TEST(obj)) pobject_lives(interpreter, obj); - obj = (PObj*)ctx->current_method; + obj = (PObj*)CONTEXT(ctx)->current_cont; + if (obj && !PObj_live_TEST(obj)) + pobject_lives(interpreter, obj); + obj = (PObj*)CONTEXT(ctx)->current_method; if (obj) pobject_lives(interpreter, obj); - obj = (PObj*)ctx->current_package; + obj = (PObj*)CONTEXT(ctx)->current_package; if (obj) pobject_lives(interpreter, obj); + regs = ctx.bp; + for (i = 0; i < NUM_REGISTERS; ++i) { + obj = (PObj*) BP_REG_PMC(regs, i); + if (obj) + pobject_lives(interpreter, obj); + obj = (PObj*) BP_REG_STR(regs, i); + if (obj) + pobject_lives(interpreter, obj); + } } /* @@ -170,50 +154,44 @@ swap_context(Interp *interpreter, struct PMC *sub) { struct Parrot_coro* co = PMC_coro(sub); - struct Parrot_Context *ctx = &co->ctx; - struct Parrot_Context temp; + parrot_context_t ctx; - /* - * Swap context structures - */ - memcpy(&temp, &interpreter->ctx, sizeof(temp)); - memcpy(&interpreter->ctx, ctx, sizeof(temp)); - memcpy(ctx, &temp, sizeof(temp)); + ctx = interpreter->ctx; - /* if calling the coroutine */ - if (!(PObj_get_FLAGS(sub) & SUB_FLAG_CORO_FF)) { + if (!co->ctx.bp) { + PMC *pad; /* * first time set current sub, cont, object */ - if (!interpreter->ctx.current_sub) { - copy_regs(interpreter, ctx->bp); - interpreter->ctx.current_sub = sub; - if (!(PObj_get_FLAGS(sub) & SUB_FLAG_GENERATOR)) - ctx->current_sub = sub; - interpreter->ctx.current_cont = BP_REG_PMC(ctx->bp,1); - REG_PMC(0) = sub; - REG_PMC(1) = interpreter->ctx.current_cont; - /* - * invalidate return continuations - */ - invalidate_retc_context(interpreter, ctx); + Parrot_alloc_context(interpreter); + co->ctx = interpreter->ctx; + pad = scratchpad_get_current(interpreter); + if (pad) { + stack_push(interpreter, &CONTEXT(co->ctx)->pad_stack, pad, + STACK_ENTRY_PMC, STACK_CLEANUP_NULL); } - /* - * construct stacks that have the interpreter stack - * at bottom and the coroutine stack at top - * - * XXX is this needed if we don't create a new stack for - * the coroutine - likely not - */ - prepend_stack(&interpreter->ctx.control_stack, &ctx->control_stack, - co->co_control_stack, co->co_control_base); + CONTEXT(co->ctx)->current_sub = sub; + CONTEXT(co->ctx)->current_cont = interpreter->current_cont; + CONTEXT(co->ctx)->current_object = NULL; + interpreter->current_object = NULL; + PObj_get_FLAGS(sub) |= SUB_FLAG_CORO_FF; + /* copy args from interpreter */ + copy_regs(interpreter, ctx.bp); + /* some code still needs this */ + REG_PMC(0) = BP_REG_PMC(ctx.bp, 0); } + /* if calling the coroutine */ + else if (!(PObj_get_FLAGS(sub) & SUB_FLAG_CORO_FF)) { + PObj_get_FLAGS(sub) |= SUB_FLAG_CORO_FF; + interpreter->ctx = co->ctx; + } else { PObj_get_FLAGS(sub) &= ~SUB_FLAG_CORO_FF; - restore_stack(&interpreter->ctx.control_stack, &ctx->control_stack, - &co->co_control_stack, co->co_control_base); - copy_regs(interpreter, ctx->bp); + ctx.rctx = CONTEXT(ctx)->prev; + interpreter->ctx = ctx; + /* yield values */ + copy_regs(interpreter, co->ctx.bp); } } @@ -281,7 +259,9 @@ new_continuation(Interp *interp) { struct Parrot_cont *cc = mem_sys_allocate(sizeof(struct Parrot_cont)); - save_context(interp, &cc->ctx); + cc->ctx = interp->ctx; + if ((char*)cc->ctx.bp > interp->ctx_mem.threshold) + interp->ctx_mem.threshold = (char*)cc->ctx.bp; cc->seg = interp->code; cc->address = NULL; return cc; @@ -301,7 +281,11 @@ struct Parrot_cont * new_ret_continuation(Interp *interp) { - return new_continuation(interp); + struct Parrot_cont *cc = mem_sys_allocate(sizeof(struct Parrot_cont)); + cc->ctx = interp->ctx; + cc->seg = interp->code; + cc->address = NULL; + return cc; } /* @@ -320,88 +304,16 @@ struct Parrot_coro * new_coroutine(Interp *interp) { - PMC * pad; - struct Parrot_Context *ctx; struct Parrot_coro *co = mem_sys_allocate_zeroed(sizeof(struct Parrot_coro)); co->seg = interp->code; - ctx = &co->ctx; - save_context(interp, ctx); - ctx->current_sub = NULL; - - /* we have separate register stacks - * - or not, with our single item stack - */ - setup_register_stacks(interp, ctx); - - /* create new (pad ??) and control stacks, - * when invoking the coroutine the real stacks are - * constructed in swap_context - * XXX decide what to do with pad - */ - co->co_control_base = co->co_control_stack = - new_stack(interp, "Coro_Control"); - - /* - * XXX probably in swap_context - */ - pad = scratchpad_get_current(interp); - if (pad) { - stack_push(interp, &ctx->pad_stack, pad, - STACK_ENTRY_PMC, STACK_CLEANUP_NULL); - } + co->ctx.bp = NULL; return co; } - /* - * Return continuation PMCs are re-used. - * In the cache they are chained together by this pointer: - */ -# define PREV_RETC(p) PMC_pmc_val(p) -/* - -=item C - -Mark the objects in the return continuation cache being alive. - -=item C - -Add the return continuation C to the cache and turn off custom -marking, so that its context isn't marked. - -Note: the context structure in C remains allocated. - -*/ -void -mark_retc_cache(Interp *interpreter) -{ - PMC *pmc = interpreter->caches->retc_cache; - - while (pmc) { - pobject_lives(interpreter, (PObj*)pmc); - pmc = PREV_RETC(pmc); - } -} - -void -add_to_retc_cache(Interp *interpreter, PMC *pmc) -{ - Caches *mc = interpreter->caches; - - if (mc->retc_cache) - PREV_RETC(mc->retc_cache) = mc->retc_cache; - PREV_RETC(pmc) = NULL; - mc->retc_cache = pmc; - /* XXX expensive w. ARENA_DOD_FLAGS */ - PObj_custom_mark_CLEAR(pmc); -} - -/* - =item C @@ -416,24 +328,7 @@ new_ret_continuation_pmc(Interp * interpreter, opcode_t * address) { PMC* continuation; - Caches *mc = interpreter->caches; - - if (mc->retc_cache) { - struct Parrot_cont * cc; - - continuation = mc->retc_cache; - mc->retc_cache = PREV_RETC(mc->retc_cache); - /* XXX expensive w. ARENA_DOD_FLAGS */ - PObj_custom_mark_SET(continuation); - /* copy interpreter context into continuation */ - cc = PMC_cont(continuation); - save_context(interpreter, &cc->ctx); - /* set current segment */ - cc->seg = interpreter->code; - } - else { - continuation = pmc_new(interpreter, enum_class_RetContinuation); - } + continuation = pmc_new(interpreter, enum_class_RetContinuation); VTABLE_set_pointer(interpreter, continuation, address); return continuation; } @@ -495,23 +390,27 @@ */ void -invalidate_retc_context(Interp *interpreter, struct Parrot_Context *ctx) +invalidate_retc_context(Interp *interpreter, parrot_context_t *ctxp) { - struct Parrot_cont * cc; + parrot_context_t ctx; PMC *cont; - cont = ctx->current_cont; - while (!PMC_IS_NULL(cont)) { + ctx = *ctxp; + if ((char*)ctx.bp > interpreter->ctx_mem.threshold) + interpreter->ctx_mem.threshold = (char*)ctx.bp; + while (1) { /* - * We could stop if we encounter a true continuation, because + * We stop if we encounter a true continuation, because * if one were created, everything up the chain would have been * invalidated earlier. - * But as long as Continuation usage can be considered being rare, - * the tests are probably more expensive than to stop early. */ + cont = CONTEXT(ctx)->current_cont; + if (cont->vtable == Parrot_base_vtables[enum_class_Continuation]) + break; cont->vtable = Parrot_base_vtables[enum_class_Continuation]; - cc = PMC_cont(cont); - cont = cc->ctx.current_cont; + ctx.rctx = CONTEXT(ctx)->prev; + if (!ctx.rctx) + break; } } @@ -554,10 +453,11 @@ } int -Parrot_Context_info(Interp *interpreter, struct Parrot_Context *ctx, +Parrot_Context_info(Interp *interpreter, parrot_context_t *ctxp, struct Parrot_Context_info *info) { struct Parrot_sub *sub; + parrot_context_t ctx = *ctxp; /* set file/line/pc defaults */ info->file = "(unknown file)"; @@ -568,7 +468,7 @@ info->fullname = NULL; /* is the current sub of the specified context valid? */ - if (PMC_IS_NULL(ctx->current_sub)) { + if (PMC_IS_NULL(CONTEXT(ctx)->current_sub)) { info->subname = string_from_cstring(interpreter, "???", 3); info->nsname = info->subname; info->fullname = string_from_cstring(interpreter, "??? :: ???", 10); @@ -577,21 +477,21 @@ } /* make sure there is a sub (not always the case, e.g in pasm code) */ - if (ctx->current_sub->vtable->base_type == enum_class_Undef || - PMC_sub(ctx->current_sub)->address == 0) { + if (CONTEXT(ctx)->current_sub->vtable->base_type == enum_class_Undef || + PMC_sub(CONTEXT(ctx)->current_sub)->address == 0) { /* XXX: is this correct? (try with load_bytecode) */ /* use the current interpreter's bytecode as start address */ - if (ctx->current_pc != NULL) - info->pc = ctx->current_pc - interpreter->code->base.data; + if (CONTEXT(ctx)->current_pc != NULL) + info->pc = CONTEXT(ctx)->current_pc - interpreter->code->base.data; return 1; } /* fetch struct Parrot_sub of the current sub in the given context */ - if (!VTABLE_isa(interpreter, ctx->current_sub, + if (!VTABLE_isa(interpreter, CONTEXT(ctx)->current_sub, const_string(interpreter, "Sub"))) return 1; - sub = PMC_sub(ctx->current_sub); + sub = PMC_sub(CONTEXT(ctx)->current_sub); /* set the sub name */ info->subname = sub->name; @@ -608,14 +508,14 @@ } /* return here if there is no current pc */ - if (ctx->current_pc == NULL) + if (CONTEXT(ctx)->current_pc == NULL) return 1; /* calculate the current pc */ - info->pc = ctx->current_pc - sub->seg->base.data; + info->pc = CONTEXT(ctx)->current_pc - sub->seg->base.data; /* determine the current source file/line */ - if (interpreter->ctx.current_pc) { + if (CONTEXT(interpreter->ctx)->current_pc) { size_t offs = info->pc; size_t i, n; /* XXX: interpreter->code->cur_cs is not correct, is it? */ @@ -642,7 +542,7 @@ } STRING* -Parrot_Context_infostr(Interp *interpreter, struct Parrot_Context *ctx) +Parrot_Context_infostr(Interp *interpreter, parrot_context_t *ctx) { struct Parrot_Context_info info; const char* msg = (&interpreter->ctx == ctx) ? Index: ops/core.ops =================================================================== --- ops/core.ops (revision 8478) +++ ops/core.ops (working copy) @@ -205,7 +205,7 @@ =cut inline op bsr (label INT) :base_core,check_event { - stack_push(interpreter, &interpreter->ctx.control_stack, expr NEXT(), STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL); + stack_push(interpreter, &CONTEXT(interpreter->ctx)->control_stack, expr NEXT(), STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL); goto OFFSET($1); } @@ -231,7 +231,7 @@ inline op jsr(label INT) :base_core,check_event { opcode_t * loc; - stack_push(interpreter, &interpreter->ctx.control_stack, expr NEXT(), STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL); + stack_push(interpreter, &CONTEXT(interpreter->ctx)->control_stack, expr NEXT(), STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL); loc = INTVAL2PTR(opcode_t *, $1); goto ADDRESS(loc); } @@ -418,6 +418,8 @@ opcode_t *dest; PMC * p = REG_PMC(0); + interpreter->current_object = NULL; + interpreter->current_cont = REG_PMC(1); dest = (opcode_t *)p->vtable->invoke(interpreter, p, expr NEXT()); goto ADDRESS(dest); @@ -427,6 +429,8 @@ opcode_t *dest; PMC * p = $1; + interpreter->current_object = NULL; + interpreter->current_cont = REG_PMC(1); dest = (opcode_t *)p->vtable->invoke(interpreter, p, expr NEXT()); goto ADDRESS(dest); @@ -436,10 +440,9 @@ opcode_t *dest; PMC * p = REG_PMC(0); dest = expr NEXT(); - REG_PMC(2) = NULL; - REG_PMC(1) = new_ret_continuation_pmc(interpreter, dest); + interpreter->current_object = NULL; + interpreter->current_cont = new_ret_continuation_pmc(interpreter, dest); dest = (opcode_t *)p->vtable->invoke(interpreter, p, dest); - goto ADDRESS(dest); } @@ -447,8 +450,8 @@ opcode_t *dest; PMC * p = $1; dest = expr NEXT(); - REG_PMC(2) = NULL; - REG_PMC(1) = new_ret_continuation_pmc(interpreter, dest); + interpreter->current_object = NULL; + interpreter->current_cont = new_ret_continuation_pmc(interpreter, dest); dest = (opcode_t *)p->vtable->invoke(interpreter, p, dest); goto ADDRESS(dest); } @@ -457,8 +460,8 @@ opcode_t *dest; PMC * p = $1; dest = expr NEXT(); - REG_PMC(1) = interpreter->ctx.current_cont; - PObj_get_FLAGS(REG_PMC(1)) |= SUB_FLAG_TAILCALL; + interpreter->current_cont = CONTEXT(interpreter->ctx)->current_cont; + PObj_get_FLAGS(interpreter->current_cont) |= SUB_FLAG_TAILCALL; dest = (opcode_t *)p->vtable->invoke(interpreter, p, dest); goto ADDRESS(dest); } @@ -466,14 +469,14 @@ inline op updatecc() { struct Parrot_cont *cc = PMC_cont(REG_PMC(1)); /* update context */ - cc->ctx.warns = interpreter->ctx.warns; - cc->ctx.errors = interpreter->ctx.errors; + CONTEXT(cc->ctx)->warns = CONTEXT(interpreter->ctx)->warns; + CONTEXT(cc->ctx)->errors = CONTEXT(interpreter->ctx)->errors; goto NEXT(); } inline op returncc() { opcode_t *dest; - PMC * p = interpreter->ctx.current_cont; + PMC * p = CONTEXT(interpreter->ctx)->current_cont; dest = (opcode_t *)p->vtable->invoke(interpreter, p, expr NEXT()); goto ADDRESS(dest); @@ -938,7 +941,7 @@ =cut inline op setpackage(in STR) { - interpreter->ctx.current_package = $1; + CONTEXT(interpreter->ctx)->current_package = $1; goto NEXT(); } @@ -949,7 +952,7 @@ =cut inline op getpackage(out STR) { - $1 = interpreter->ctx.current_package; + $1 = CONTEXT(interpreter->ctx)->current_package; goto NEXT(); } Index: ops/var.ops =================================================================== --- ops/var.ops (revision 8478) +++ ops/var.ops (working copy) @@ -47,7 +47,7 @@ PMC * pad; PMC * parent = scratchpad_get_current(interpreter); pad = scratchpad_new(interpreter, parent, $1); - stack_push(interpreter, &interpreter->ctx.pad_stack, pad, + stack_push(interpreter, &CONTEXT(interpreter->ctx)->pad_stack, pad, STACK_ENTRY_PMC, STACK_CLEANUP_NULL); goto NEXT(); } @@ -67,7 +67,7 @@ =cut op push_pad(in PMC) { - stack_push(interpreter, &interpreter->ctx.pad_stack, $1, + stack_push(interpreter, &CONTEXT(interpreter->ctx)->pad_stack, $1, STACK_ENTRY_PMC, STACK_CLEANUP_NULL); goto NEXT(); } @@ -86,13 +86,13 @@ =cut op pop_pad() { - stack_pop(interpreter, &interpreter->ctx.pad_stack, + stack_pop(interpreter, &CONTEXT(interpreter->ctx)->pad_stack, NULL, STACK_ENTRY_PMC); goto NEXT(); } op pop_pad(out PMC) { - stack_pop(interpreter, &interpreter->ctx.pad_stack, + stack_pop(interpreter, &CONTEXT(interpreter->ctx)->pad_stack, &$1, STACK_ENTRY_PMC); goto NEXT(); } Index: ops/rx.ops =================================================================== --- ops/rx.ops (revision 8478) +++ ops/rx.ops (working copy) @@ -195,7 +195,7 @@ =cut op rx_pushindex(in int) { - intstack_push(interpreter, interpreter->ctx.intstack, $1); + intstack_push(interpreter, CONTEXT(interpreter->ctx)->intstack, $1); goto NEXT(); } @@ -203,14 +203,14 @@ =item B() op rx_initstack() { - interpreter->ctx.intstack = intstack_new(interpreter); + CONTEXT(interpreter->ctx)->intstack = intstack_new(interpreter); goto NEXT(); } =item B() op rx_clearstack () { - intstack_free(interpreter, interpreter->ctx.intstack); + intstack_free(interpreter, CONTEXT(interpreter->ctx)->intstack); goto NEXT(); } @@ -225,7 +225,7 @@ =cut op rx_pushmark() { - intstack_push(interpreter, interpreter->ctx.intstack, RX_MARK); + intstack_push(interpreter, CONTEXT(interpreter->ctx)->intstack, RX_MARK); goto NEXT(); } @@ -242,7 +242,7 @@ op rx_popindex(out int, labelconst int) { INTVAL i; - i=intstack_pop(interpreter, interpreter->ctx.intstack); + i=intstack_pop(interpreter, CONTEXT(interpreter->ctx)->intstack); if(i==RX_MARK) { goto OFFSET($2); Index: ops/experimental.ops =================================================================== --- ops/experimental.ops (revision 8478) +++ ops/experimental.ops (working copy) @@ -352,7 +352,7 @@ PMC *signature = $1; INTVAL argc; - interpreter->ctx.current_results = this; + CONTEXT(interpreter->ctx)->current_results = this; argc = VTABLE_elements(interpreter, signature); goto ADDRESS(this + 2 + argc); } @@ -361,12 +361,12 @@ opcode_t *this = CUR_OPCODE; PMC *signature = $1; INTVAL argc; - struct Parrot_sub * sub = PMC_sub(interpreter->ctx.current_sub); + struct Parrot_sub * sub = PMC_sub(CONTEXT(interpreter->ctx)->current_sub); - interpreter->ctx.current_params = this; + CONTEXT(interpreter->ctx)->current_params = this; if (sub->address != this) { struct parrot_regs_t *caller_regs; - PMC *cont_pmc = interpreter->ctx.current_cont; + PMC *cont_pmc = CONTEXT(interpreter->ctx)->current_cont; opcode_t *pc; caller_regs = PMC_cont(cont_pmc)->ctx.bp; Index: ops/stack.ops =================================================================== --- ops/stack.ops (revision 8478) +++ ops/stack.ops (working copy) @@ -374,7 +374,7 @@ op entrytype(out INT, in INT) :base_core { Stack_Entry_t *entry; - entry = stack_entry(interpreter, interpreter->ctx.user_stack, $2); + entry = stack_entry(interpreter, CONTEXT(interpreter->ctx)->user_stack, $2); if (!entry) { internal_exception(99, "Stack Depth wrong"); } @@ -391,7 +391,7 @@ =cut inline op depth(out INT) :base_core { - $1 = stack_height(interpreter, interpreter->ctx.user_stack); + $1 = stack_height(interpreter, CONTEXT(interpreter->ctx)->user_stack); goto NEXT(); } @@ -414,7 +414,7 @@ op lookback(out INT, in INT) :base_core { Stack_Entry_t *entry = - stack_entry(interpreter, interpreter->ctx.user_stack, $2); + stack_entry(interpreter, CONTEXT(interpreter->ctx)->user_stack, $2); if (!entry) internal_exception(99, "Stack depth wrong"); if (entry->entry_type != STACK_ENTRY_INT) { @@ -427,7 +427,7 @@ op lookback(out STR, in INT) :base_core { Stack_Entry_t *entry = - stack_entry(interpreter, interpreter->ctx.user_stack, $2); + stack_entry(interpreter, CONTEXT(interpreter->ctx)->user_stack, $2); if (!entry) internal_exception(99, "Stack depth wrong"); if (entry->entry_type != STACK_ENTRY_STRING) { @@ -440,7 +440,7 @@ op lookback(out NUM, in INT) :base_core { Stack_Entry_t *entry = - stack_entry(interpreter, interpreter->ctx.user_stack, $2); + stack_entry(interpreter, CONTEXT(interpreter->ctx)->user_stack, $2); if (!entry) internal_exception(99, "Stack depth wrong"); if (entry->entry_type != STACK_ENTRY_FLOAT) { @@ -453,7 +453,7 @@ op lookback(out PMC, in INT) :base_core { Stack_Entry_t *entry = - stack_entry(interpreter, interpreter->ctx.user_stack, $2); + stack_entry(interpreter, CONTEXT(interpreter->ctx)->user_stack, $2); if (!entry) internal_exception(99, "Stack depth wrong"); if (entry->entry_type != STACK_ENTRY_PMC) { @@ -480,22 +480,22 @@ inline op save(in INT) :base_core { INTVAL i = $1; - stack_push(interpreter, &interpreter->ctx.user_stack, &i, STACK_ENTRY_INT, STACK_CLEANUP_NULL); + stack_push(interpreter, &CONTEXT(interpreter->ctx)->user_stack, &i, STACK_ENTRY_INT, STACK_CLEANUP_NULL); goto NEXT(); } inline op save(in NUM) :base_core { - stack_push(interpreter, &interpreter->ctx.user_stack, &($1), STACK_ENTRY_FLOAT, STACK_CLEANUP_NULL); + stack_push(interpreter, &CONTEXT(interpreter->ctx)->user_stack, &($1), STACK_ENTRY_FLOAT, STACK_CLEANUP_NULL); goto NEXT(); } inline op save(in PMC) :base_core { - stack_push(interpreter, &interpreter->ctx.user_stack, $1, STACK_ENTRY_PMC, STACK_CLEANUP_NULL); + stack_push(interpreter, &CONTEXT(interpreter->ctx)->user_stack, $1, STACK_ENTRY_PMC, STACK_CLEANUP_NULL); goto NEXT(); } inline op save(in STR) :base_core { - stack_push(interpreter, &interpreter->ctx.user_stack, $1, STACK_ENTRY_STRING, STACK_CLEANUP_NULL); + stack_push(interpreter, &CONTEXT(interpreter->ctx)->user_stack, $1, STACK_ENTRY_STRING, STACK_CLEANUP_NULL); goto NEXT(); } @@ -508,7 +508,7 @@ =cut inline op savec(in STR) :base_core { - stack_push(interpreter, &interpreter->ctx.user_stack, string_copy(interpreter, $1), STACK_ENTRY_STRING, STACK_CLEANUP_NULL); + stack_push(interpreter, &CONTEXT(interpreter->ctx)->user_stack, string_copy(interpreter, $1), STACK_ENTRY_STRING, STACK_CLEANUP_NULL); goto NEXT(); } @@ -527,25 +527,25 @@ =cut inline op restore(out INT) :base_core { - (void)stack_pop(interpreter, &interpreter->ctx.user_stack, &($1), + (void)stack_pop(interpreter, &CONTEXT(interpreter->ctx)->user_stack, &($1), STACK_ENTRY_INT); goto NEXT(); } inline op restore(out NUM) :base_core { - (void)stack_pop(interpreter, &interpreter->ctx.user_stack, &($1), + (void)stack_pop(interpreter, &CONTEXT(interpreter->ctx)->user_stack, &($1), STACK_ENTRY_FLOAT); goto NEXT(); } inline op restore(out PMC) :base_core { - (void)stack_pop(interpreter, &interpreter->ctx.user_stack, &($1), + (void)stack_pop(interpreter, &CONTEXT(interpreter->ctx)->user_stack, &($1), STACK_ENTRY_PMC); goto NEXT(); } inline op restore(out STR) :base_core { - (void)stack_pop(interpreter, &interpreter->ctx.user_stack, &($1), + (void)stack_pop(interpreter, &CONTEXT(interpreter->ctx)->user_stack, &($1), STACK_ENTRY_STRING); goto NEXT(); } @@ -565,7 +565,7 @@ =cut inline op rotate_up(in INT) :base_core { - rotate_entries(interpreter, &interpreter->ctx.user_stack, $1); + rotate_entries(interpreter, &CONTEXT(interpreter->ctx)->user_stack, $1); goto NEXT(); } @@ -578,7 +578,7 @@ =cut inline op intsave(in INT) :base_core { - intstack_push(interpreter, interpreter->ctx.intstack, $1); + intstack_push(interpreter, CONTEXT(interpreter->ctx)->intstack, $1); goto NEXT(); } @@ -591,7 +591,7 @@ =cut inline op intrestore(out INT) :base_core { - $1=intstack_pop(interpreter, interpreter->ctx.intstack); + $1=intstack_pop(interpreter, CONTEXT(interpreter->ctx)->intstack); goto NEXT(); } @@ -604,7 +604,7 @@ =cut inline op intdepth(out INT) :base_core { - $1=intstack_depth(interpreter, interpreter->ctx.intstack); + $1=intstack_depth(interpreter, CONTEXT(interpreter->ctx)->intstack); goto NEXT(); } Index: ops/object.ops =================================================================== --- ops/object.ops (revision 8478) +++ ops/object.ops (working copy) @@ -73,9 +73,9 @@ real_exception(interpreter, next, METH_NOT_FOUND, "Method '%Ss' not found", meth); } - REG_PMC(0) = method_pmc; - interpreter->ctx.current_object = object; - interpreter->ctx.current_method = meth; + interpreter->current_object = object; + interpreter->current_cont = NULL; + interpreter->current_method = meth; dest = (opcode_t *)VTABLE_invoke(interpreter, method_pmc, next); goto ADDRESS(dest); } @@ -92,9 +92,9 @@ real_exception(interpreter, next, METH_NOT_FOUND, "Method '%Ss' not found", meth); } - REG_PMC(0) = method_pmc; - interpreter->ctx.current_object = object; - interpreter->ctx.current_method = meth; + interpreter->current_object = object; + interpreter->current_cont = NULL; + interpreter->current_method = meth; dest = (opcode_t *)VTABLE_invoke(interpreter, method_pmc, next); goto ADDRESS(dest); } @@ -105,18 +105,18 @@ opcode_t *next = expr NEXT(); STRING *meth = REG_STR(0); - REG_PMC(1) = new_ret_continuation_pmc(interpreter, next); - interpreter->ctx.current_object = object = REG_PMC(2); - interpreter->ctx.current_method = meth; + object = REG_PMC(2); assert(!PMC_IS_NULL(object)); assert(meth!=0); + interpreter->current_object = object; + interpreter->current_cont = new_ret_continuation_pmc(interpreter, next); + interpreter->current_method = meth; method_pmc = VTABLE_find_method(interpreter, object, meth); if (!method_pmc) { real_exception(interpreter, next, METH_NOT_FOUND, "Method '%Ss' not found", meth); } - REG_PMC(0) = method_pmc; - dest = (opcode_t *)REG_PMC(0)->vtable->invoke(interpreter, method_pmc, next); + dest = (opcode_t *)VTABLE_invoke(interpreter, method_pmc, next); goto ADDRESS(dest); } @@ -132,16 +132,15 @@ goto NEXT(); next = expr NEXT(); - REG_PMC(1) = new_ret_continuation_pmc(interpreter, next); - interpreter->ctx.current_object = object; - interpreter->ctx.current_method = meth; + interpreter->current_object = object; + interpreter->current_cont = new_ret_continuation_pmc(interpreter, next); + interpreter->current_method = meth; method_pmc = VTABLE_find_method(interpreter, object, meth); if (!method_pmc) { real_exception(interpreter, next, METH_NOT_FOUND, "Method '%Ss' not found", meth); } - REG_PMC(0) = method_pmc; - dest = (opcode_t *)REG_PMC(0)->vtable->invoke(interpreter, method_pmc, next); + dest = (opcode_t *)VTABLE_invoke(interpreter, method_pmc, next); goto ADDRESS(dest); } @@ -152,18 +151,16 @@ STRING *meth; meth = $1; - REG_PMC(1) = interpreter->ctx.current_cont; - PObj_get_FLAGS(REG_PMC(1)) |= SUB_FLAG_TAILCALL; - - interpreter->ctx.current_object = object = REG_PMC(2); - interpreter->ctx.current_method = meth; + interpreter->current_cont = CONTEXT(interpreter->ctx)->current_cont; + PObj_get_FLAGS(interpreter->current_cont) |= SUB_FLAG_TAILCALL; + interpreter->current_object = object; + interpreter->current_method = meth; method_pmc = VTABLE_find_method(interpreter, object, meth); if (!method_pmc) { real_exception(interpreter, next, METH_NOT_FOUND, "Method '%Ss' not found", meth); } - REG_PMC(0) = method_pmc; - dest = (opcode_t *)REG_PMC(0)->vtable->invoke(interpreter, method_pmc, next); + dest = (opcode_t *)VTABLE_invoke(interpreter, method_pmc, next); goto ADDRESS(dest); } Index: imcc/optimizer.c =================================================================== --- imcc/optimizer.c (revision 8478) +++ imcc/optimizer.c (working copy) @@ -667,8 +667,7 @@ char b[128], fmt[64], op[20]; const char *debug_fmt; int found, branched; - struct parrot_regs_t *bp; - Stack_Chunk_t *stack_p, *reg_stack; + parrot_context_t ctx; /* construct a FLOATVAL_FMT with needed precision */ @@ -751,10 +750,8 @@ return NULL; } /* preserve registers */ - bp = interpreter->ctx.bp; - reg_stack = interpreter->ctx.reg_stack; - interpreter->ctx.bp = new_register_frame(interpreter, - &interpreter->ctx.reg_stack); + ctx = interpreter->ctx; + Parrot_alloc_context(interpreter); IMCC_debug(interpreter, DEBUG_OPT1, debug_fmt, name); /* we construct a parrot instruction @@ -795,7 +792,7 @@ } r[1] = mk_const(interpreter, str_dup(b), r[0]->set); tmp = INS(interpreter, unit, "set", "", r, - 2, 0, 0); + 2, 0, 0); } if (tmp) { IMCC_debug(interpreter, DEBUG_OPT1, "%I\n", tmp); @@ -804,10 +801,8 @@ /* * restore and recycle register frame */ - stack_p = interpreter->ctx.reg_stack; - interpreter->ctx.bp = bp; - interpreter->ctx.reg_stack = reg_stack; - add_to_fp_cache(interpreter, stack_p); + Parrot_free_context(interpreter, &interpreter->ctx, 1); + interpreter->ctx = ctx; return tmp; } Index: imcc/imclexer.c =================================================================== --- imcc/imclexer.c (revision 8478) +++ imcc/imclexer.c (working copy) @@ -10,8 +10,8 @@ #define YY_FLEX_MINOR_VERSION 5 #include -#include + /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ #ifdef c_plusplus #ifndef __cplusplus @@ -23,9 +23,7 @@ #ifdef __cplusplus #include -#ifndef _WIN32 #include -#endif /* Use prototypes in function declarations. */ #define YY_USE_PROTOS @@ -65,7 +63,6 @@ #define YY_PROTO(proto) () #endif - /* Returned upon end-of-file. */ #define YY_NULL 0 @@ -1887,7 +1884,7 @@ #define cmt5 8 -#line 1891 "imcc/imclexer.c" +#line 1888 "imcc/imclexer.c" /* Macros after this point can all be overridden by user definitions in * section 1. @@ -1987,20 +1984,9 @@ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - } + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - @@ -2069,7 +2055,7 @@ return 0; } -#line 2073 "imcc/imclexer.c" +#line 2059 "imcc/imclexer.c" if ( yy_init ) { @@ -3089,7 +3075,7 @@ #line 526 "imcc/imcc.l" ECHO; YY_BREAK -#line 3093 "imcc/imclexer.c" +#line 3079 "imcc/imclexer.c" case YY_STATE_EOF(pod): case YY_STATE_EOF(cmt1): case YY_STATE_EOF(cmt2): @@ -3660,15 +3646,11 @@ } -#ifndef _WIN32 -#include -#else #ifndef YY_ALWAYS_INTERACTIVE #ifndef YY_NEVER_INTERACTIVE extern int isatty YY_PROTO(( int )); #endif #endif -#endif #ifdef YY_USE_PROTOS void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) Index: imcc/t/syn/objects.t =================================================================== --- imcc/t/syn/objects.t (revision 8478) +++ imcc/t/syn/objects.t (working copy) @@ -276,7 +276,7 @@ done OUT -pir_output_is(<<'CODE', <<'OUT', "explicit meth call syntax, retcont"); +pir_output_is(<<'CODE', <<'OUT', "explicit meth call syntax"); .sub test @MAIN .local pmc class @@ -284,12 +284,9 @@ newclass class, "Foo" find_type $I0, "Foo" new obj, $I0 - .local pmc retc - newsub retc, .RetContinuation, label .pcc_begin .invocant obj - .meth_call "_meth", retc -label: + .meth_call "_meth" .pcc_end print "done\n" end Index: imcc/t/syn/pcc.t =================================================================== --- imcc/t/syn/pcc.t (revision 8478) +++ imcc/t/syn/pcc.t (working copy) @@ -357,10 +357,8 @@ .pcc_end print $I2 print "\n" - savetop invoke goto ret_addr - restoretop after_loop: print "done in main\n" end Index: include/parrot/sub.h =================================================================== --- include/parrot/sub.h (revision 8478) +++ include/parrot/sub.h (working copy) @@ -39,6 +39,7 @@ } sub_flags_enum; +union parrot_context_t; /* * Sub and Closure share a Parrot_sub structure, Closure has additionally @@ -82,9 +83,7 @@ /* - end common */ - struct Parrot_Context ctx; /* XXX 2 continuations */ - struct Stack_Chunk *co_control_base; - struct Stack_Chunk *co_control_stack; /* control stack top of the cor.*/ + parrot_context_t ctx; /* coroutine context */ struct PackFile_ByteCode *caller_seg; /* bytecode segment */ } * parrot_coro_t; @@ -93,7 +92,7 @@ typedef struct Parrot_cont { struct PackFile_ByteCode *seg; /* bytecode segment */ opcode_t *address; /* start of bytecode, addr to continue */ - struct Parrot_Context ctx; /* copy of interpreter context */ + parrot_context_t ctx; /* pointer to interpreter context */ } * parrot_cont_t; #define PMC_cont(pmc) LVALUE_CAST(parrot_cont_t, PMC_struct_val(pmc)) @@ -116,23 +115,19 @@ PMC * new_ret_continuation_pmc(Interp *, opcode_t * address); -void save_context(Interp *, struct Parrot_Context *); void swap_context(Interp *, PMC *); -void restore_context(Interp *, struct Parrot_Context *); -void mark_context(Interp *, struct Parrot_Context *); +void mark_context(Interp *, parrot_context_t *); opcode_t * parrot_pass_args(Interp *, struct Parrot_sub * sub, struct parrot_regs_t *caller_regs, int what); void copy_regs(Interp *, struct parrot_regs_t *caller_regs); void mark_reg_stack(Interp *, Stack_Chunk_t *); +void invalidate_retc_context(Interp *interpreter, parrot_context_t *ctx); -void invalidate_retc_context(Interp *interpreter, struct Parrot_Context *); -void add_to_retc_cache(Interp *interpreter, PMC *pmc); -void mark_retc_cache(Interp *); STRING* Parrot_full_sub_name(Interp* interpreter, PMC* sub); -int Parrot_Context_info(Interp *interpreter, struct Parrot_Context *, struct Parrot_Context_info *); -STRING* Parrot_Context_infostr(Interp *interpreter, struct Parrot_Context *); +int Parrot_Context_info(Interp *interpreter, parrot_context_t *, struct Parrot_Context_info *); +STRING* Parrot_Context_infostr(Interp *interpreter, parrot_context_t *); #endif /* PARROT_SUB_H_GUARD */ Index: include/parrot/register.h =================================================================== --- include/parrot/register.h (revision 8478) +++ include/parrot/register.h (working copy) @@ -49,9 +49,8 @@ }; struct Stack_Chunk; -struct Parrot_Context; -void setup_register_stacks(Interp*, struct Parrot_Context *); +void setup_register_stacks(Interp*); void mark_register_stack(Interp* interpreter, struct Stack_Chunk* stack); void mark_pmc_register_stack(Interp* interpreter, @@ -59,9 +58,6 @@ void mark_string_register_stack(Interp* interpreter, struct Stack_Chunk* stack); -void add_to_fp_cache(Interp*, struct Stack_Chunk *stack_p); -void* new_register_frame(Interp* interpreter, struct Stack_Chunk **stack_p); - #endif /* PARROT_REGISTER_H_GUARD */ /* Index: include/parrot/caches.h =================================================================== --- include/parrot/caches.h (revision 8478) +++ include/parrot/caches.h (working copy) @@ -34,8 +34,6 @@ UINTVAL mc_size; /* sizeof table */ Meth_cache_entry ***idx; /* bufstart idx */ /* PMC **hash */ /* for non-constant keys */ - struct Stack_Chunk * frame_cache; /* register frame cache */ - PMC* retc_cache; /* return continuations recycling */ } Caches; void init_object_cache(Parrot_Interp interpreter); Index: include/parrot/warnings.h =================================================================== --- include/parrot/warnings.h (revision 8478) +++ include/parrot/warnings.h (working copy) @@ -27,11 +27,11 @@ /* &end_gen */ #define PARROT_we_on(we, interp, flag) do { \ - (interp)->ctx.we |= (flag); } while (0) + CONTEXT((interp)->ctx)->we |= (flag); } while (0) #define PARROT_we_off(we, interp, flag) do { \ - (interp)->ctx.we &= ~(flag); } while (0) + CONTEXT((interp)->ctx)->we &= ~(flag); } while (0) #define PARROT_we_test(we, interp, flag) \ - (interp)->ctx.we & (flag) + CONTEXT((interp)->ctx)->we & (flag) #define PARROT_WARNINGS_on(interp, flag) PARROT_we_on(warns, interp, flag) #define PARROT_WARNINGS_off(interp, flag) PARROT_we_off(warns, interp, flag) Index: include/parrot/interpreter.h =================================================================== --- include/parrot/interpreter.h (revision 8478) +++ include/parrot/interpreter.h (working copy) @@ -91,9 +91,9 @@ #define Interp_debug_CLEAR(interp, flag) ((interp)->debug_flags &= ~(flag)) #define Interp_debug_TEST(interp, flag) ((interp)->debug_flags & (flag)) -#define Interp_trace_SET(interp, flag) ((interp)->ctx.trace_flags |= (flag)) -#define Interp_trace_CLEAR(interp, flag) ((interp)->ctx.trace_flags &= ~(flag)) -#define Interp_trace_TEST(interp, flag) ((interp)->ctx.trace_flags & (flag)) +#define Interp_trace_SET(interp, flag) (CONTEXT((interp)->ctx)->trace_flags |= (flag)) +#define Interp_trace_CLEAR(interp, flag) (CONTEXT((interp)->ctx)->trace_flags &= ~(flag)) +#define Interp_trace_TEST(interp, flag) (CONTEXT((interp)->ctx)->trace_flags & (flag)) #define Interp_core_SET(interp, core) ((interp)->run_core = (core)) #define Interp_core_TEST(interp, core) ((interp)->run_core == (core)) @@ -179,15 +179,13 @@ #endif /* SLIDING_BP */ }; -typedef struct Parrot_Context { - struct parrot_regs_t *bp; /* indirect reg base pointer */ +struct Parrot_Context { + struct Parrot_Context *prev; struct Stack_Chunk *int_reg_stack; /* register frame stacks */ struct Stack_Chunk *num_reg_stack; struct Stack_Chunk *string_reg_stack; struct Stack_Chunk *pmc_reg_stack; - struct Stack_Chunk *reg_stack; /* all in one register stack */ - struct Stack_Chunk *pad_stack; /* Base of the lex pad stack */ struct Stack_Chunk *user_stack; /* Base of the scratch stack */ struct Stack_Chunk *control_stack; /* Base of the flow control stack */ @@ -215,8 +213,11 @@ INTVAL current_HLL; /* see also src/hll.c */ opcode_t *current_params; /* ptr into code with get_params opcode */ opcode_t *current_results; /* ptr into code with get_results opcode */ -} parrot_context_t; +}; +#define ALIGNED_CTX_SIZE ( (1 + sizeof(struct Parrot_Context)/NUMVAL_SIZE) * \ + NUMVAL_SIZE ) + struct _Thread_data; /* in thread.h */ struct _Caches; /* caches .h */ @@ -233,13 +234,25 @@ } Prederef; +typedef union All_Context { + struct parrot_regs_t *bp; /* register base pointer */ + struct Parrot_Context *rctx; /* context is at rctx[-1] */ +} parrot_context_t; +#define CONTEXT(ctx) ((ctx).rctx -1) + +typedef struct _context_mem { + char *data; /* ctx + register store */ + char *free; /* free to allocate */ + char *threshold; /* continuation threshold */ + struct _context_mem *prev; /* previous allocated area */ +} context_mem; /* * The actual interpreter structure */ struct parrot_interp_t { - struct Parrot_Context ctx; /* All the registers and stacks that - matter when context switching */ + parrot_context_t ctx; + context_mem ctx_mem; /* ctx memory managment */ struct Stash *globals; /* Pointer to the global variable * area */ @@ -314,6 +327,12 @@ UINTVAL gc_generation; /* GC generation number */ opcode_t *current_args; /* ptr into code with set_args opcode */ opcode_t *current_returns; /* ptr into code with get_returns opcode */ + /* during a call sequencer the caller fills these objects + * inside the invoke these get moved to the context structure + */ + PMC *current_cont; /* the return continuation PMC */ + PMC *current_object; /* current object if a method call */ + STRING *current_method; /* name of method */ }; /* typedef struct parrot_interp_t Interp; done in parrot.h so that @@ -364,10 +383,10 @@ # define INTERP_REG_STR(i, x) i->ctx.bp->string_reg.registers[x] # define INTERP_REG_PMC(i, x) i->ctx.bp->pmc_reg.registers[x] -# define BP_REG_INT(bp, x) bp->int_reg.registers[x] -# define BP_REG_NUM(bp, x) bp->num_reg.registers[x] -# define BP_REG_STR(bp, x) bp->string_reg.registers[x] -# define BP_REG_PMC(bp, x) bp->pmc_reg.registers[x] +# define BP_REG_INT(bp, x) (bp)->int_reg.registers[x] +# define BP_REG_NUM(bp, x) (bp)->num_reg.registers[x] +# define BP_REG_STR(bp, x) (bp)->string_reg.registers[x] +# define BP_REG_PMC(bp, x) (bp)->pmc_reg.registers[x] #endif /* SLIDING_BP */ @@ -432,6 +451,10 @@ void Parrot_init(Interp *); void Parrot_destroy(Interp *); +void Parrot_alloc_context(Interp *); +void Parrot_free_context(Interp *, parrot_context_t *, int re_use); +void parrot_gc_context(Interp *); + INTVAL interpinfo(Interp *interpreter, INTVAL what); PMC* interpinfo_p(Interp *interpreter, INTVAL what); STRING*interpinfo_s(Interp *interpreter, INTVAL what); Index: classes/retcontinuation.pmc =================================================================== --- classes/retcontinuation.pmc (revision 8478) +++ classes/retcontinuation.pmc (working copy) @@ -38,13 +38,30 @@ */ void init () { - PMC_cont(SELF) = new_continuation(INTERP); + PMC_cont(SELF) = new_ret_continuation(INTERP); PMC_pmc_val(SELF) = NULL; PObj_custom_mark_destroy_SETALL(SELF); } /* +=item C + +Destroys the continuation. + +=cut + +*/ + + void destroy () { + struct Parrot_cont * sub = PMC_cont(SELF); + if (sub) { + mem_sys_free(sub); + PMC_cont(SELF) = NULL; + } + } +/* + =item C Return a new Continuation PMC with the context of SELF. Note: the @@ -75,13 +92,13 @@ */ void* invoke (void* next) { - Stack_Chunk_t *stack_p; Stack_Chunk_t *ctr_stack, *stack_now; + parrot_context_t ctx; /* * unwind control stack */ - stack_now = INTERP->ctx.control_stack; - ctr_stack = PMC_cont(SELF)->ctx.control_stack; + stack_now = CONTEXT(INTERP->ctx)->control_stack; + ctr_stack = CONTEXT(PMC_cont(SELF)->ctx)->control_stack; while (stack_now != ctr_stack) { if (!stack_now || !ctr_stack) internal_exception(1, "Control stack damaged"); @@ -94,10 +111,14 @@ NULL, NO_STACK_ENTRY_TYPE); } - stack_p = INTERP->ctx.reg_stack; + /* + * Continuation.invoke resets the context pointer to + * it's own context - remember pointer and free the + * used context memory - that's safe as long as this + * is a plain return continuation + */ + Parrot_free_context(INTERP, &INTERP->ctx, 1); next = SUPER(next); - add_to_fp_cache(INTERP, stack_p); - add_to_retc_cache(INTERP, SELF); return next; } Index: classes/parrotinterpreter.pmc =================================================================== --- classes/parrotinterpreter.pmc (revision 8478) +++ classes/parrotinterpreter.pmc (working copy) @@ -173,6 +173,7 @@ clone_regs_thread(d, s, dest); else clone_regs_interp(d, s, dest); + CONTEXT(d->ctx)->current_object = dest; } /* @@ -202,7 +203,7 @@ /* * copy over packfile - done currently in the runinterp opcode * for multi-threading we have to generate separate - * profile, prederef, and JIT data + * profile data */ #if 0 pt_clone_code(d, s); @@ -453,7 +454,7 @@ int level = 0; PMC* nextkey; STRING *item, *s; - struct Parrot_Context *ctx; + parrot_context_t ctx; PMC *cont; item = key_string(interpreter, key); @@ -463,23 +464,23 @@ nextkey = key_next(INTERP, key); if (nextkey) level = key_integer(interpreter, nextkey); - ctx = &interpreter->ctx; + ctx = interpreter->ctx; for (; level; --level) { - cont = ctx->current_cont; + cont = CONTEXT(ctx)->current_cont; if (PMC_IS_NULL(cont) || !PMC_cont(cont)->seg) real_exception(interpreter, NULL, E_ValueError, "No such caller depth"); - ctx = &PMC_cont(cont)->ctx; + ctx = PMC_cont(cont)->ctx; } s = CONST_STRING(interpreter, "sub"); if (string_equal(interpreter, item, s) == 0) - return ctx->current_sub; + return CONTEXT(ctx)->current_sub; s = CONST_STRING(interpreter, "pad"); if (string_equal(interpreter, item, s) == 0) - return stack_peek(interpreter, ctx->pad_stack, NULL); + return stack_peek(interpreter, CONTEXT(ctx)->pad_stack, NULL); s = CONST_STRING(interpreter, "continuation"); if (string_equal(interpreter, item, s) == 0) - return VTABLE_clone(interpreter, ctx->current_cont); + return VTABLE_clone(interpreter, CONTEXT(ctx)->current_cont); return PMCNULL; } /* Index: classes/bound_nci.pmc =================================================================== --- classes/bound_nci.pmc (revision 8478) +++ classes/bound_nci.pmc (working copy) @@ -71,7 +71,7 @@ } else { PMC *p2 = REG_PMC(2); - REG_PMC(2) = PMC_pmc_val(SELF); + INTERP->current_object = REG_PMC(2) = PMC_pmc_val(SELF); SUPER(next); REG_PMC(2) = p2; } Index: classes/coroutine.pmc =================================================================== --- classes/coroutine.pmc (revision 8478) +++ classes/coroutine.pmc (working copy) @@ -94,7 +94,6 @@ struct Parrot_coro * sub = PMC_coro(SELF); struct PackFile_ByteCode *wanted_seg; void * dest = sub->address; - int argcP = REG_INT(3); sub->address = next; /* if calling the Coro we need the segment of the Coro */ @@ -126,10 +125,13 @@ void mark () { struct Parrot_coro *c = PMC_coro(SELF); +#if 0 mark_stack(INTERP, c->co_control_stack); mark_stack(INTERP, c->co_control_base); - /* mark_stack(INTERP, c->co_pad_stack); */ - mark_context(INTERP, &c->ctx); + mark_stack(INTERP, c->co_pad_stack); +#endif + if (c && c->ctx.bp) + mark_context(INTERP, &c->ctx); } } Index: classes/continuation.pmc =================================================================== --- classes/continuation.pmc (revision 8478) +++ classes/continuation.pmc (working copy) @@ -99,7 +99,11 @@ void destroy () { struct Parrot_cont * sub = PMC_cont(SELF); - mem_sys_free(sub); + if (sub) { + Parrot_free_context(interpreter, &sub->ctx, 0); + mem_sys_free(sub); + PMC_cont(SELF) = NULL; + } } /* @@ -205,16 +209,16 @@ opcode_t *pc; caller_regs = INTERP->ctx.bp; - restore_context(INTERP, &cc->ctx); + INTERP->ctx = cc->ctx; if (Interp_trace_TEST(INTERP, PARROT_TRACE_SUB_CALL_FLAG)) { - PMC *sub = INTERP->ctx.current_sub; + PMC *sub = CONTEXT(INTERP->ctx)->current_sub; STRING *unk = CONST_STRING(INTERP, "(unknown"); PIO_eprintf(INTERP, "# Back in sub '%Ss'\n", Parrot_full_sub_name(INTERP, sub)); } pc = cc->address; if (pc) { - if (INTERP->ctx.current_results) { + if (CONTEXT(INTERP->ctx)->current_results) { /* possibly a true continuation that acts as a Sub */ if (*pc == PARROT_OP_get_params_pc) pc = parrot_pass_args(INTERP, (struct Parrot_sub*)cc, @@ -264,7 +268,7 @@ METHOD PMC* caller() { struct Parrot_cont * cc = PMC_cont(SELF); - PMC *caller = cc->ctx.current_sub; + PMC *caller = CONTEXT(cc->ctx)->current_sub; if (!caller || !PMC_sub(caller)->address) { caller = pmc_new(INTERP, enum_class_Undef); } @@ -283,7 +287,7 @@ METHOD PMC* continuation() { struct Parrot_cont * cc = PMC_cont(SELF); - PMC *cont = cc->ctx.current_cont; + PMC *cont = CONTEXT(cc->ctx)->current_cont; if (cont) return cont; return pmc_new(INTERP, enum_class_Undef); Index: classes/closure.pmc =================================================================== --- classes/closure.pmc (revision 8478) +++ classes/closure.pmc (working copy) @@ -74,7 +74,7 @@ void* invoke (void* next) { struct Parrot_sub * sub = PMC_sub(SELF); - INTERP->ctx.pad_stack = sub->pad_stack; + CONTEXT(INTERP->ctx)->pad_stack = sub->pad_stack; return SUPER(next); } Index: classes/nci.pmc =================================================================== --- classes/nci.pmc (revision 8478) +++ classes/nci.pmc (working copy) @@ -125,6 +125,7 @@ void* invoke (void * next) { Parrot_csub_t func = (Parrot_csub_t)D2FPTR(PMC_data(SELF)); PMC *obj; + PMC *p2 = CONTEXT(INTERP->ctx)->current_object; UINTVAL flags; if (!func) @@ -141,7 +142,8 @@ * private1 ... created via dlfunc * */ - obj = REG_PMC(2); + obj = INTERP->current_object; + INTERP->current_object = NULL; flags = PObj_get_FLAGS(SELF); if (flags & PObj_private0_FLAG) { /* MMD */ if (obj) { /* as method */ @@ -161,7 +163,9 @@ REG_PMC(i) = REG_PMC(i+1); } } + CONTEXT(INTERP->ctx)->current_object = obj; func(INTERP, SELF); + CONTEXT(INTERP->ctx)->current_object = p2; return next; } Index: classes/sub.pmc =================================================================== --- classes/sub.pmc (revision 8478) +++ classes/sub.pmc (working copy) @@ -81,8 +81,8 @@ _array = CONST_STRING(interpreter, "array"); constants = interpreter->code->const_table->constants; if (what == PARROT_OP_get_params_pc) { - if (interpreter->ctx.current_params) - dst_pc = interpreter->ctx.current_params; + if (CONTEXT(interpreter->ctx)->current_params) + dst_pc = CONTEXT(interpreter->ctx)->current_params; else if (*sub->address != what) return sub->address; else @@ -90,14 +90,14 @@ args_op = PARROT_OP_set_args_pc; src_pc = interpreter->current_args; - interpreter->ctx.current_params = NULL; + CONTEXT(interpreter->ctx)->current_params = NULL; action = "params"; } else { - dst_pc = interpreter->ctx.current_results; + dst_pc = CONTEXT(interpreter->ctx)->current_results; args_op = PARROT_OP_set_returns_pc; src_pc = interpreter->current_returns; - interpreter->ctx.current_results = NULL; + CONTEXT(interpreter->ctx)->current_results = NULL; action = "results"; } @@ -481,7 +481,8 @@ * create new register frame, remember old */ caller_regs = INTERP->ctx.bp; - ccont = INTERP->ctx.current_cont; + ccont = INTERP->current_cont; + INTERP->current_cont = NULL; /* * we have: * sub A: @@ -518,13 +519,10 @@ * */ pc = sub->address; - /* not yet seen */ - INTERP->ctx.current_params = INTERP->ctx.current_results = NULL; if (!PMC_IS_NULL(ccont)) { if (PObj_get_FLAGS(ccont) & SUB_FLAG_TAILCALL) { PObj_get_FLAGS(ccont) &= ~SUB_FLAG_TAILCALL; - assert(ccont == REG_PMC(1)); if (INTERP->current_args) { pc = parrot_pass_args(INTERP, sub, caller_regs, PARROT_OP_get_params_pc); @@ -532,13 +530,15 @@ goto is_tail_call; } } - if (++INTERP->ctx.recursion_depth > + if (++CONTEXT(INTERP->ctx)->recursion_depth > INTERP->recursion_limit) { real_exception(INTERP, next, E_RuntimeError, "maximum recursion depth exceeded"); } - INTERP->ctx.bp = new_register_frame(INTERP, - &INTERP->ctx.reg_stack); + Parrot_alloc_context(INTERP); + /* not yet seen */ + CONTEXT(INTERP->ctx)->current_params = + CONTEXT(INTERP->ctx)->current_results = NULL; /* * when next == NULL the call creates args in the * new frame, e.g. @@ -547,8 +547,8 @@ if (next) { /* XXX temporary hack during call syntax switch */ if (INTERP->current_args) { - INTERP->ctx.current_sub = SELF; - INTERP->ctx.current_pc = pc; + CONTEXT(INTERP->ctx)->current_sub = SELF; + CONTEXT(INTERP->ctx)->current_pc = pc; pc = parrot_pass_args(INTERP, sub, caller_regs, PARROT_OP_get_params_pc); } @@ -559,11 +559,17 @@ /* * and copy set context variables */ - INTERP->ctx.current_cont = BP_REG_PMC(caller_regs, 1); + CONTEXT(INTERP->ctx)->current_cont = ccont; is_tail_call: - INTERP->ctx.current_sub = SELF; } - INTERP->ctx.current_HLL = sub->HLL_id; + CONTEXT(INTERP->ctx)->current_sub = SELF; + if (!PMC_IS_NULL(INTERP->current_object)) { + CONTEXT(INTERP->ctx)->current_object = INTERP->current_object; + INTERP->current_object = NULL; + CONTEXT(INTERP->ctx)->current_method = INTERP->current_method; + INTERP->current_method = NULL; + } + CONTEXT(INTERP->ctx)->current_HLL = sub->HLL_id; return pc; } Index: classes/parrotio.pmc =================================================================== --- classes/parrotio.pmc (revision 8478) +++ classes/parrotio.pmc (working copy) @@ -38,7 +38,7 @@ */ METHOD INTVAL say(STRING *s) { - PMC *p2 = INTERP->ctx.current_object; + PMC *p2 = CONTEXT(INTERP->ctx)->current_object; PMC *out = p2 == Parrot_base_vtables[enum_class_ParrotIO]->class ? PIO_STDOUT(INTERP) : p2; INTVAL r = PIO_putps(INTERP, out, s); Index: t/pmc/sub.t =================================================================== --- t/pmc/sub.t (revision 8478) +++ t/pmc/sub.t (working copy) @@ -17,7 +17,7 @@ =cut -use Parrot::Test tests => 51; +use Parrot::Test tests => 49; use Test::More; use Parrot::Config; @@ -710,40 +710,6 @@ ok 2 OUTPUT -output_is(<<'CODE', <<'OUTPUT', "continuation close over register stacks"); - set S20, "ok\n" - savetop - newsub P0, .Continuation, next - restoretop - concat S20, "not ", S20 - invoke - print "bad\n" -next: - restoretop - print S20 - end -CODE -ok -OUTPUT - -output_is(<<'CODE', <<'OUTPUT', "DOD marks continuation's register stacks"); - set S20, "ok\n" - savetop - newsub P0, .Continuation, next - restoretop - null S20 - sweep 1 - collect - invoke - print "bad\n" -next: - restoretop - print S20 - end -CODE -ok -OUTPUT - output_is(<<'CODE', <<'OUT', "MAIN pragma, syntax only"); .pcc_sub @MAIN _main: print "ok\n" Index: t/pmc/io.t =================================================================== --- t/pmc/io.t (revision 8478) +++ t/pmc/io.t (working copy) @@ -382,8 +382,7 @@ if I0, ok1 print "not " ok1: print "ok 1\n" - find_method P0, P2, "puts" - invoke + callmethod "puts" end CODE ok 1 Index: t/pmc/threads.t =================================================================== --- t/pmc/threads.t (revision 8478) +++ t/pmc/threads.t (working copy) @@ -73,9 +73,8 @@ # set regs P2 = thread-interp, P5 = sub find_global P5, "_foo" new P2, .ParrotThread - find_method P0, P2, "thread1" set I3, 1 - invoke # start the thread + callmethod "thread1" sleep 1 print "main " @@ -84,8 +83,7 @@ # get tid of thread set I5, P2 # wait for it - find_method P0, P2, "join" - invoke + callmethod "join" end .pcc_sub _foo: @@ -117,8 +115,7 @@ print "ok 2\n" new P2, .ParrotThread set I3, 2 # 2 args - find_method P0, P2, "thread2" - invoke # start the thread + callmethod "thread2" sleep 1 # now the thread should run print P6 @@ -127,8 +124,7 @@ # get tid of thread set I5, P2 # wait for it - find_method P0, P2, "join" - invoke + callmethod "join" end .pcc_sub _foo: @@ -139,15 +135,13 @@ print P6 print I5 print S5 + getinterp P2 typeof S0, P2 print S0 print " tid " set I0, P2 print I0 print "\n" - typeof S0, P0 - print S0 - print "\n" set I3, 0 returncc # ret and be done with thread @@ -156,7 +150,6 @@ ok 2 hello from 1 thread ParrotThread tid 1 -Sub from 10 interp OUTPUT @@ -168,15 +161,13 @@ print "start " print I10 print "\n" - find_method P0, P2, "thread3" set I3, 1 - invoke # start the thread + callmethod "thread3" sleep 1 set I5, I10 getinterp P2 - find_method P0, P2, "kill" - invoke + callmethod "kill" print "done\n" end @@ -209,26 +200,13 @@ .sym pmc to to = new Integer to = MAX - .sym pmc Thread_new - find_method Thread_new, kid, "thread3" - .pcc_begin - .arg Adder - .arg from - .arg to - .invocant kid - .nci_call Thread_new - .pcc_end + kid."thread3"(Adder, from, to) - .sym int tid + .local int tid tid = kid - .sym pmc Thread_join - find_method Thread_join, kid, "join" - .pcc_begin - .arg tid - .nci_call Thread_join - .sym pmc result - .result result - .pcc_end + .local pmc me, result + me = getinterp + result = me."join"(tid) print result print "\n" # sum = n * (n + 1)/2 @@ -268,15 +246,13 @@ output_like(<<'CODE', <<'OUTPUT', "detach"); find_global P5, "_foo" new P2, .ParrotThread - find_method P0, P2, "thread3" new P6, .TQueue # need a flag that thread is done set I3, 2 - invoke # start the thread + callmethod "thread3" set I5, P2 getinterp P2 - find_method P0, P2, "detach" - invoke + callmethod "detach" wait: defined I0, P6 unless I0, wait @@ -297,19 +273,17 @@ output_is(<<'CODE', <<'OUTPUT', "share a PMC"); find_global P5, "_foo" new P2, .ParrotThread - find_method P0, P2, "thread3" new P20, .Integer new P6, .SharedRef, P20 set P6, 20 set I3, 2 # P5..P6 - invoke # start the thread + callmethod "thread3" # now sleep a bit, so that the thread runs sleep 0.1 set I5, P2 getinterp P2 - find_method P0, P2, "join" - invoke + callmethod "join" print "done\n" print P6 print "\n" @@ -343,14 +317,12 @@ set P6, P10 new P2, .ParrotThread - find_method P0, P2, "thread3" find_global P5, "_foo" set I3, 2 - invoke # start the thread + callmethod "thread3" set I5, P2 getinterp P2 - find_method P0, P2, "join" - invoke # join the thread + callmethod "join" print "done main\n" end @@ -394,14 +366,12 @@ set P6, P10 new P2, .ParrotThread - find_method P0, P2, "thread3" find_global P5, "_foo" set I3, 2 - invoke # start the thread + callmethod "thread3" set I5, P2 getinterp P2 - find_method P0, P2, "join" - invoke # join the thread + callmethod "join" print "done main\n" end @@ -473,12 +443,10 @@ find_global P5, "_foo" new P2, .ParrotThread - find_method P0, P2, "thread3" - invoke # start the thread + callmethod "thread3" set I5, P2 getinterp P2 - find_method P0, P2, "join" - invoke # join the thread + callmethod "join" print "done main\n" end Index: t/pmc/exception.t =================================================================== --- t/pmc/exception.t (revision 8478) +++ t/pmc/exception.t (working copy) @@ -434,7 +434,7 @@ print "in coro\n" newsub P20, .Exception_Handler, _handler set_eh P20 - invoke P1 + returncc _handler: print "caught it\n" @@ -465,7 +465,7 @@ .local pmc n new_pad 0 $P0 = getinterp - $P0."recursion_limit"(100) + $P0."recursion_limit"(50) newclass $P0, "b" $I0 = find_type "b" $P0 = new $I0 @@ -495,7 +495,7 @@ .end CODE ok 1 -99 +49 OUTPUT output_is(<<'CODE', <<'OUTPUT', "push_eh - throw"); Index: config/gen/makefiles/root.in =================================================================== --- config/gen/makefiles/root.in (revision 8478) +++ config/gen/makefiles/root.in (working copy) @@ -1158,12 +1158,15 @@ EXTRA_TEST_ARGS = --gc-debug --running-make-test SRC_TEST_FILES = t/src/*.t PERL_TEST_FILES = t/perl/*.t -TEST_FILES = t/library/*.t \ + +# note python tests disabled +TEST_FILES = \ t/op/*.t \ t/pmc/*.t \ t/native_pbc/*.t \ $(IMCC_DIR)/t/*/*.t \ - t/dynclass/*.t \ + t/library/*.t \ + t/dynclass/foo.t t/dynclass/g*.t \ t/p6rules/*.t # Common prep for all test targets. Index: config/gen/makefiles/dynclasses.in =================================================================== --- config/gen/makefiles/dynclasses.in (revision 8478) +++ config/gen/makefiles/dynclasses.in (working copy) @@ -10,6 +10,10 @@ #CONDITIONED_LINE(has_gdbm):gdbmhash \ match \ matchrange \ + subproxy \ + foo + +DISABLED_PMCS = \ pybuiltin \ pyclass \ pyobject \ @@ -35,9 +39,7 @@ pytuple \ pyproxytype \ pyproxyclass \ - pyiter \ - subproxy \ - foo + pyiter BUILD = $(PERL) "${build_dir}${slash}build_tools${slash}build_dynclasses.pl"