Author: leo
Date: Mon Oct 24 16:06:01 2005
New Revision: 9550
Modified:
trunk/build_tools/ops2c.pl
trunk/classes/coroutine.pmc
trunk/classes/sub.pmc
trunk/imcc/optimizer.c
trunk/include/parrot/interpreter.h
trunk/jit/ppc/jit_emit.h
trunk/lib/Parrot/OpTrans/CGP.pm
trunk/lib/Parrot/OpTrans/CSwitch.pm
trunk/src/exceptions.c
trunk/src/inter_create.c
trunk/src/pic.c
trunk/src/register.c
trunk/src/sub.c
Log:
Variable-sized reg frames 10 - convert ctx.bp too
11 - rewrite saveall/restoreall
* use the second base pointer too
* rewrite all REG access macros to new scheme
* Parrot_alloc_context takes now (still unused) register usage args
* get rid of more struct parrot_regs_t inside register stack code
saveall/restoreall should now work with var-regs out-of-the-box
* drop superfluous alloc_context for exception handling
Extra thanks to Psyche, who experimented with amd64 errors and found out
that i->ctx.bp.regs_n[-1L-(x)] works - note the '-1L'.
A few tests are failing, though:
t/op/interp.t 4 1024 11 4 36.36% 7-10 # amd64, ppc [1]
t/src/extend.t 1 256 13 1 7.69% 7 # ppc
t/src/hash.t 1 256 10 1 10.00% 6 # ppc
t/src/sprintf.t 1 256 3 1 33.33% 3 # ppc
[1] tests are bogus (running a new interpreter from a label, with
argument passing)
Modified: trunk/build_tools/ops2c.pl
==============================================================================
--- trunk/build_tools/ops2c.pl (original)
+++ trunk/build_tools/ops2c.pl Mon Oct 24 16:06:01 2005
@@ -364,7 +364,7 @@ if ($suffix =~ /cgp/) {
asm ("jmp *4(%ebp)"); /* jump to ret addr, used by JIT */
# endif
#endif
- _reg_base = (char*)interpreter->ctx.bp;
+ _reg_base = (char*)interpreter->ctx.bp.regs_i;
goto *((void *)*cur_opcode);
END_C
Modified: trunk/classes/coroutine.pmc
==============================================================================
--- trunk/classes/coroutine.pmc (original)
+++ trunk/classes/coroutine.pmc Mon Oct 24 16:06:01 2005
@@ -110,7 +110,7 @@ Swaps the "context".
/*
* first time set current sub, cont, object
*/
- Parrot_alloc_context(INTERP);
+ Parrot_alloc_context(INTERP, co->n_regs_used);
co->ctx = ctx = CONTEXT(INTERP->ctx);
PMC_cont(ccont)->from_ctx = ctx;
/*
Modified: trunk/classes/sub.pmc
==============================================================================
--- trunk/classes/sub.pmc (original)
+++ trunk/classes/sub.pmc Mon Oct 24 16:06:01 2005
@@ -308,7 +308,7 @@ create_ctx:
* plain subroutine call
* create new context, place it in interpreter
*/
- Parrot_alloc_context(INTERP);
+ Parrot_alloc_context(INTERP, sub->n_regs_used);
context = CONTEXT(INTERP->ctx);
/* check recursion/call depth */
if (++context->recursion_depth >
Modified: trunk/imcc/optimizer.c
==============================================================================
--- trunk/imcc/optimizer.c (original)
+++ trunk/imcc/optimizer.c Mon Oct 24 16:06:01 2005
@@ -674,6 +674,7 @@ IMCC_subst_constants(Interp *interpreter
const char *debug_fmt;
int found, branched;
parrot_context_t *ctx;
+ INTVAL regs_used[4] = {3,3,3,3};
/* construct a FLOATVAL_FMT with needed precision */
@@ -757,7 +758,7 @@ IMCC_subst_constants(Interp *interpreter
}
/* preserve registers */
ctx = CONTEXT(interpreter->ctx);
- Parrot_alloc_context(interpreter);
+ Parrot_alloc_context(interpreter, regs_used);
IMCC_debug(interpreter, DEBUG_OPT1, debug_fmt, name);
/* we construct a parrot instruction
Modified: trunk/include/parrot/interpreter.h
==============================================================================
--- trunk/include/parrot/interpreter.h (original)
+++ trunk/include/parrot/interpreter.h Mon Oct 24 16:06:01 2005
@@ -157,12 +157,9 @@ typedef struct _RunProfile {
struct _imc_info_t;
/*
- * Parrot registers are now accessed through interpreter->ctx.bp
- * This structure is dynamically allocated in subroutine calls
- * and restored on subroutine returns on more precisely on invokation
- * of a continuation by restoring the interpreter context.
+ * doomed helper structure
*/
-struct parrot_regs_t {
+struct _parrot_regs_t {
struct NReg num_reg;
struct IReg int_reg;
struct PReg pmc_reg;
@@ -174,12 +171,18 @@ typedef union {
STRING **regs_s;
} Regs_ps;
+typedef union {
+ FLOATVAL *regs_n;
+ INTVAL *regs_i;
+} Regs_ni;
+
typedef struct Parrot_Context {
/* common header with Interp_Context */
struct Parrot_Context *prev;
- struct parrot_regs_t *bp; /* register base pointer */
+ Regs_ni bp; /* pointers to FLOATVAL & INTVAL */
Regs_ps bp_ps; /* pointers to PMC & STR */
/* end common header */
+ INTVAL n_regs_used[4]; /* INSP in PBC */
INTVAL ref_count; /* how often refered to */
struct Stack_Chunk *reg_stack; /* register stack */
@@ -230,10 +233,15 @@ typedef struct _Prederef {
} Prederef;
+/*
+ * This is an 'inlined' copy of the first 3 Context items for
+ * faster access of registers mainly
+ * During a context switch a 3 pointers are set
+ */
struct Interp_Context {
/* common header */
struct Parrot_Context *state; /* context */
- struct parrot_regs_t *bp; /* register base pointer */
+ Regs_ni bp; /* pointers to FLOATVAL & INTVAL */
Regs_ps bp_ps; /* pointers to PMC & STR */
/* end common header */
};
@@ -383,17 +391,40 @@ typedef enum {
* Macros to make accessing registers more convenient/readable.
*/
-# define INTERP_REG_NUM(i, x) i->ctx.bp->num_reg.registers[x]
-# define INTERP_REG_INT(i, x) i->ctx.bp->int_reg.registers[x]
-# define INTERP_REG_PMC(i, x) i->ctx.bp_ps.regs_p[-32+x]
+# define INTERP_REG_NUM(i, x) i->ctx.bp.regs_n[-1L-(x)]
+# define INTERP_REG_INT(i, x) i->ctx.bp.regs_i[x]
+# define INTERP_REG_PMC(i, x) i->ctx.bp_ps.regs_p[-1L-(x)]
# define INTERP_REG_STR(i, x) i->ctx.bp_ps.regs_s[x]
-# define CTX_REG_NUM(ctx, x) (ctx)->bp->num_reg.registers[x]
-# define CTX_REG_INT(ctx, x) (ctx)->bp->int_reg.registers[x]
-# define CTX_REG_PMC(ctx, x) (ctx)->bp_ps.regs_p[-32+x]
+# define CTX_REG_NUM(ctx, x) (ctx)->bp.regs_n[-1L-(x)]
+# define CTX_REG_INT(ctx, x) (ctx)->bp.regs_i[x]
+# define CTX_REG_PMC(ctx, x) (ctx)->bp_ps.regs_p[-1L-(x)]
# define CTX_REG_STR(ctx, x) (ctx)->bp_ps.regs_s[x]
+/*
+ * and a set of macros to access a register by offset, used
+ * in JIT emit prederef code
+ * The offsets are relative to interpreter->ctx.bp.
+ *
+ * Reg order in imcc/reg_alloc.c is "INSP" TODO make defines
+ */
+
+#define REGNO_INT 0
+#define REGNO_NUM 1
+#define REGNO_STR 2
+#define REGNO_PMC 3
+
+# define __CTX interpreter->ctx.state
+# define _SIZEOF_INTS (sizeof(INTVAL) * __CTX->n_regs_used[REGNO_INT])
+# define _SIZEOF_NUMS (sizeof(FLOATVAL) * __CTX->n_regs_used[REGNO_NUM])
+# define _SIZEOF_PMCS (sizeof(PMC*) * __CTX->n_regs_used[REGNO_PMC])
+# define _SIZEOF_STRS (sizeof(STRING*) * __CTX->n_regs_used[REGNO_STR])
+
+# define REG_OFFS_NUM(x) (sizeof(FLOATVAL) * (-1L - (x)))
+# define REG_OFFS_INT(x) (sizeof(INTVAL) * (x))
+# define REG_OFFS_PMC(x) (_SIZEOF_INTS + sizeof(PMC*) * \
+ (__CTX->n_regs_used[REGNO_PMC] - 1L - x))
+# define REG_OFFS_STR(x) (sizeof(STRING*) * (x) + _SIZEOF_INTS + _SIZEOF_PMCS
)
-#define REG_BASE struct parrot_regs_t
/*
* same with the default name interpreter
@@ -403,19 +434,6 @@ typedef enum {
#define REG_STR(x) INTERP_REG_STR(interpreter, x)
#define REG_PMC(x) INTERP_REG_PMC(interpreter, x)
-/*
- * and a set of macros to access a register by offset, mostly used
- * in JIT emit code
- * The offsets are relative to REG_BASE, which is REG_INT(0),
- * i.e. that what interpreter->ctx.bp is pointing to.
- */
-
-
-# define REG_OFFS_INT(x) offsetof(REG_BASE, int_reg.registers[x])
-# define REG_OFFS_NUM(x) offsetof(REG_BASE, num_reg.registers[x])
-# define REG_OFFS_STR(x) offsetof(REG_BASE, string_reg.registers[x])
-# define REG_OFFS_PMC(x) offsetof(REG_BASE, pmc_reg.registers[x])
-
#define PCONST(i) PF_CONST(interpreter->code, (i))
#define PNCONST PF_NCONST(interpreter->code)
@@ -451,7 +469,7 @@ Interp *make_interpreter(Interp * parent
void Parrot_init(Interp *);
void Parrot_destroy(Interp *);
-void Parrot_alloc_context(Interp *);
+void Parrot_alloc_context(Interp *, INTVAL *n_regs_used);
void Parrot_free_context(Interp *, parrot_context_t *, int re_use);
void Parrot_set_context_threshold(Interp *, parrot_context_t *);
void parrot_gc_context(Interp *);
Modified: trunk/jit/ppc/jit_emit.h
==============================================================================
--- trunk/jit/ppc/jit_emit.h (original)
+++ trunk/jit/ppc/jit_emit.h Mon Oct 24 16:06:01 2005
@@ -423,11 +423,11 @@ enum { JIT_PPC_CALL, JIT_PPC_BRANCH, JIT
# define jit_emit_mov_rm_i(pc, reg, addr) \
jit_emit_lwz(pc, reg, (((char *)addr) - \
- ((char *)interpreter->ctx.bp)), r13)
+ ((char *)interpreter->ctx.bp.regs_i)), r13)
# define jit_emit_mov_rm_n(pc, reg, addr) \
jit_emit_lfd(pc, reg, (((char *)addr) - \
- ((char *)interpreter->ctx.bp)), r13)
+ ((char *)interpreter->ctx.bp.regs_i)), r13)
/* compare operation.
*
@@ -563,11 +563,11 @@ jit_emit_bx(Parrot_jit_info_t *jit_info,
# define jit_emit_mov_mr_i(pc, addr, reg) \
jit_emit_stw(pc, reg, (((char *)addr) - \
- ((char *)interpreter->ctx.bp)), r13)
+ ((char *)interpreter->ctx.bp.regs_i)), r13)
# define jit_emit_mov_mr_n(pc, addr, reg) \
jit_emit_stfd(pc, reg, (((char *)addr) - \
- ((char *)interpreter->ctx.bp)), r13)
+ ((char *)interpreter->ctx.bp.regs_i)), r13)
/*
Modified: trunk/lib/Parrot/OpTrans/CGP.pm
==============================================================================
--- trunk/lib/Parrot/OpTrans/CGP.pm (original)
+++ trunk/lib/Parrot/OpTrans/CGP.pm Mon Oct 24 16:06:01 2005
@@ -107,7 +107,7 @@ sub goto_address
{
return "if ((opcode_t *) $addr == 0)
return 0;
- _reg_base = (char*)interpreter->ctx.bp;
+ _reg_base = (char*)interpreter->ctx.bp.regs_i;
goto *((void*)*(cur_opcode = (opcode_t *)
opcode_to_prederef(interpreter, $addr)))";
}
@@ -144,7 +144,7 @@ sub goto_pop
sub run_core_func_start
{
return <<END_C;
-#if defined(__GNUC__) && defined(I386) && __GNUC__ < 4
+#if defined(__GNUC__) && defined(I386) && __GNUC__ < 4
register opcode_t *cur_opcode asm ("esi") = cur_op;
register char * _reg_base asm ("edi");
#else
Modified: trunk/lib/Parrot/OpTrans/CSwitch.pm
==============================================================================
--- trunk/lib/Parrot/OpTrans/CSwitch.pm (original)
+++ trunk/lib/Parrot/OpTrans/CSwitch.pm Mon Oct 24 16:06:01 2005
@@ -176,7 +176,7 @@ Returns the C code prior to the run core
sub run_core_func_start
{
return <<END_C;
-#if defined(__GNUC__) && defined(I386) && __GNUC__ < 4
+#if defined(__GNUC__) && defined(I386) && __GNUC__ < 4
register opcode_t *cur_opcode asm ("esi") = cur_op;
register char * _reg_base asm ("edi");
#else
@@ -185,7 +185,7 @@ sub run_core_func_start
#endif
SWITCH_RELOAD:
- _reg_base = (char*)interpreter->ctx.bp;
+ _reg_base = (char*)interpreter->ctx.bp.regs_i;
do {
SWITCH_AGAIN:
cur_opcode = CHECK_EVENTS(interpreter, cur_opcode);
Modified: trunk/src/exceptions.c
==============================================================================
--- trunk/src/exceptions.c (original)
+++ trunk/src/exceptions.c Mon Oct 24 16:06:01 2005
@@ -232,7 +232,6 @@ find_exception_handler(Interp * interpre
*/
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, &CONTEXT(interpreter->ctx)->control_stack,
Modified: trunk/src/inter_create.c
==============================================================================
--- trunk/src/inter_create.c (original)
+++ trunk/src/inter_create.c Mon Oct 24 16:06:01 2005
@@ -191,23 +191,31 @@ destroy_context(Interp *interpreter)
static void
create_initial_context(Interp *interpreter)
{
- size_t to_alloc = sizeof(struct parrot_regs_t) + ALIGNED_CTX_SIZE;
- void *p;
+ size_t to_alloc = ALIGNED_CTX_SIZE;
parrot_context_t *ctx;
+ void *p, *ptr;
+ int i;
- ctx = p = mem_sys_allocate_zeroed(to_alloc);
+ ctx = ptr = mem_sys_allocate_zeroed(to_alloc);
#if CTX_LEAK_DEBUG
- fprintf(stderr, "alloc %p\n", p);
+ fprintf(stderr, "alloc %p\n", ctx);
#endif
CONTEXT(interpreter->ctx) = ctx;
- p = (void *) ((char *)p + ALIGNED_CTX_SIZE);
- interpreter->ctx.bp = p;
- interpreter->ctx.bp_ps.regs_s = (STRING**) ((char*)p +
- offsetof(struct parrot_regs_t, string_reg.registers[0]));
+ for (i = 0; i < 4; ++i)
+ ctx->n_regs_used[i] = NUM_REGISTERS;
+ /* regs start past the context */
+ p = (void *) ((char *)ptr + ALIGNED_CTX_SIZE);
+ /* ctx.bp points to I0, which has Nx at left */
+ interpreter->ctx.bp.regs_i = (INTVAL*)((char*)p + _SIZEOF_NUMS);
+ /* this points to S0 */
+ interpreter->ctx.bp_ps.regs_s = (STRING**)((char*)p + _SIZEOF_NUMS +
+ _SIZEOF_INTS + _SIZEOF_PMCS);
interpreter->ctx_mem.free = NULL;
- ctx->bp = interpreter->ctx.bp;
- ctx->bp_ps = interpreter->ctx.bp_ps;
+ ctx->bp.regs_i = interpreter->ctx.bp.regs_i;
+ ctx->bp_ps.regs_s = interpreter->ctx.bp_ps.regs_s;
ctx->prev = NULL;
+ for (i = 0; i < 4; ++i)
+ ctx->n_regs_used[i] = 0;
}
#endif
@@ -218,7 +226,7 @@ create_initial_context(Interp *interpret
Cleanup dead context memory. Called by the gargabe collector.
-=item C<void Parrot_alloc_context(Interp *)>
+=item C<void Parrot_alloc_context(Interp *, INTVAL *n_regs_used)>
Allocate a new context and set the context pointer.
@@ -250,48 +258,54 @@ parrot_gc_context(Interp *interpreter)
}
static void
-init_context(Interp *interpreter, parrot_context_t *old_state)
+init_context(Interp *interpreter, parrot_context_t *ctx)
{
int i;
- parrot_context_t *ctx;
- memcpy(CONTEXT(interpreter->ctx),
- old_state, sizeof(struct Parrot_Context));
- CONTEXT(interpreter->ctx)->prev = old_state;
- CONTEXT(interpreter->ctx)->ref_count = 0;
- CONTEXT(interpreter->ctx)->current_results = NULL;
- CONTEXT(interpreter->ctx)->current_args = NULL;
+ ctx->ref_count = 0;
+ ctx->current_results = NULL;
+ ctx->current_args = NULL;
/* NULL out registers
*
* if the architecture has 0x := NULL and 0.0 we could memset too
- *
*/
- ctx = CONTEXT(interpreter->ctx);
ctx->bp = interpreter->ctx.bp;
ctx->bp_ps = interpreter->ctx.bp_ps;
- for (i = 0; i < NUM_REGISTERS; i++) {
+ for (i = 0; i < ctx->n_regs_used[REGNO_PMC]; i++) {
CTX_REG_PMC(ctx, i) = PMCNULL;
+ }
+ for (i = 0; i < ctx->n_regs_used[REGNO_STR]; i++) {
CTX_REG_STR(ctx, i) = NULL;
+ }
#ifndef NDEBUG
+ for (i = 0; i < ctx->n_regs_used[REGNO_INT]; i++) {
/* depending on -D40 we set int, num to garbage or zero
*/
if (Interp_debug_TEST(interpreter, PARROT_REG_DEBUG_FLAG)) {
/* TODO better use rand values */
CTX_REG_INT(ctx, i) = -999;
- CTX_REG_NUM(ctx, i) = -99.9;
}
else {
CTX_REG_INT(ctx, i) = 0;
+ }
+ }
+ for (i = 0; i < ctx->n_regs_used[REGNO_NUM]; i++) {
+ /* depending on -D40 we set int, num to garbage or zero
+ */
+ if (Interp_debug_TEST(interpreter, PARROT_REG_DEBUG_FLAG)) {
+ CTX_REG_NUM(ctx, i) = -99.9;
+ }
+ else {
CTX_REG_NUM(ctx, i) = 0.0;
}
-#endif
}
+#endif
}
#if CHUNKED_CTX_MEM
void
-Parrot_alloc_context(Interp *interpreter)
+Parrot_alloc_context(Interp *interpreter, INTVAL *n_regs_used)
{
parrot_context_t ctx;
@@ -397,33 +411,39 @@ Parrot_free_context(Interp *interpreter,
void
-Parrot_alloc_context(Interp *interpreter)
+Parrot_alloc_context(Interp *interpreter, INTVAL *n_regs_used)
{
-
- struct Parrot_Context *old;
+ struct Parrot_Context *old, *ctx;
void *ptr, *p;
+ int i;
ptr = interpreter->ctx_mem.free;
if (ptr) {
interpreter->ctx_mem.free = *(void **) ptr;
}
else {
- ptr = mem_sys_allocate(sizeof(struct parrot_regs_t) +
+ ptr = mem_sys_allocate(sizeof(struct _parrot_regs_t) +
ALIGNED_CTX_SIZE);
*(void **) ptr = NULL;
}
- p = (void *) ((char *)ptr + ALIGNED_CTX_SIZE);
- old = CONTEXT(interpreter->ctx);
- CONTEXT(interpreter->ctx) = ptr;
#if CTX_LEAK_DEBUG
- fprintf(stderr, "alloc %p\n", p);
+ fprintf(stderr, "alloc %p\n", ptr);
#endif
- /* XXX .bp this still points to start */
- interpreter->ctx.bp = p;
- /* this points to S0 - currently fixed regs still */
- interpreter->ctx.bp_ps.regs_s = (STRING**) ((char*)p +
- offsetof(struct parrot_regs_t, string_reg.registers[0]));
- init_context(interpreter, old);
+ old = CONTEXT(interpreter->ctx);
+ CONTEXT(interpreter->ctx) = ctx = ptr;
+ memcpy(ctx, old, sizeof(struct Parrot_Context));
+ ctx->prev = old;
+ for (i = 0; i < 4; ++i)
+ ctx->n_regs_used[i] = NUM_REGISTERS;
+ /* regs start past the context */
+ p = (void *) ((char *)ptr + ALIGNED_CTX_SIZE);
+ /* ctx.bp points to I0, which has Nx at left */
+ interpreter->ctx.bp.regs_i = (INTVAL*)((char*)p + _SIZEOF_NUMS);
+ /* this points to S0 */
+ interpreter->ctx.bp_ps.regs_s = (STRING**)((char*)p + _SIZEOF_NUMS +
+ _SIZEOF_INTS + _SIZEOF_PMCS);
+
+ init_context(interpreter, ctx);
}
void
Modified: trunk/src/pic.c
==============================================================================
--- trunk/src/pic.c (original)
+++ trunk/src/pic.c Mon Oct 24 16:06:01 2005
@@ -259,7 +259,7 @@ void
parrot_PIC_prederef(Interp *interpreter, opcode_t op, void **pc_pred, int core)
{
op_func_t *prederef_op_func = interpreter->op_lib->op_func_table;
- char * _reg_base = (char*)interpreter->ctx.bp;
+ char * _reg_base = (char*)interpreter->ctx.bp.regs_i;
opcode_t *cur_opcode = (opcode_t*)pc_pred;
switch (op) {
Modified: trunk/src/register.c
==============================================================================
--- trunk/src/register.c (original)
+++ trunk/src/register.c Mon Oct 24 16:06:01 2005
@@ -8,15 +8,16 @@ src/register.c - Register handling routi
=head1 DESCRIPTION
-Parrot has 4 register sets, one for each of its basic types. There are
-32 registers in each set.
-
-Each register set has a register frame stack for saving and restoring
-its contents. Note that, whereas the C<push{i,n,s,p}> opcodes push all
-32 registers on to the stack, in the C implementation a register frame
-is actually only I<half> the register set. The opcode calls the the
-C<Parrot_push_{i,n,s,p}()> function twice, once for each half of the
-set.
+Parrot has 4 register sets, one for each of its basic types. The amount
+of registers in each set varies depending on the use counts of the
+respective subroutine and is determined by the PASM/PIR compiler in
+the register allocation pass (F<imcc/reg_alloc.c>).
+
+There is one register stack to support the C<saveall> and
+C<restoreall> opcodes. The former copies all registers to a newly
+allocated storage and points the register base pointers to this
+storage. In C<Parrot_pop_regs> the register base pointers are restored
+to the previous values and the allocated register memory is discarded.
=head2 Functions
@@ -35,7 +36,7 @@ and register frame stacks.
/*
=item C<void
-setup_register_stacks(Parrot_Interp, struct Parrot_Context *)>
+setup_register_stacks(Interp *)>
Sets up the register stacks.
@@ -51,64 +52,74 @@ Restore all registers from register stac
*/
+typedef struct {
+ Regs_ni old_bp_ni; /* restoreall just resets ptrs */
+ Regs_ps old_bp_ps;
+ Regs_ps bp_ps; /* pushed regs need DOD marking */
+ INTVAL n_regs_pmc;
+ INTVAL n_regs_str;
+} save_regs_t;
+
void
-setup_register_stacks(Parrot_Interp interpreter)
+setup_register_stacks(Interp * interpreter)
{
CONTEXT(interpreter->ctx)->reg_stack =
register_new_stack(interpreter,
- "Regs_", sizeof(struct parrot_regs_t));
+ "Regs_", sizeof(save_regs_t));
}
void
Parrot_push_regs(Interp *interpreter)
{
- struct parrot_regs_t *bp = stack_prepare_push(interpreter,
- &CONTEXT(interpreter->ctx)->reg_stack);
- memcpy(bp, interpreter->ctx.bp, sizeof(struct parrot_regs_t));
+ Stack_Chunk_t *chunk, **chunk_p;
+ save_regs_t *save_r;
+ parrot_context_t *ctx;
+ size_t size_nis, size_nisp;
+ void *ptr;
+
+ ctx = CONTEXT(interpreter->ctx);
+ chunk_p = &ctx->reg_stack;
+ save_r = stack_prepare_push(interpreter, chunk_p);
+ save_r->old_bp_ni.regs_i = ctx->bp.regs_i;
+ save_r->old_bp_ps.regs_s = ctx->bp_ps.regs_s;
+ save_r->n_regs_str = ctx->n_regs_used[REGNO_STR];
+ save_r->n_regs_pmc = ctx->n_regs_used[REGNO_PMC];
+
+ size_nis = _SIZEOF_NUMS + _SIZEOF_INTS + _SIZEOF_STRS;
+ size_nisp = size_nis + _SIZEOF_PMCS;
+ ptr = mem_sys_allocate(size_nisp);
+ memcpy(ptr, (char*)ctx->bp.regs_i - _SIZEOF_NUMS, size_nisp);
+ save_r->bp_ps.regs_s = (void*) ((char*) ptr + size_nis);
+ interpreter->ctx.bp.regs_i = ctx->bp.regs_i =
+ (void*) ((char*) ptr + _SIZEOF_NUMS);
+ interpreter->ctx.bp_ps = ctx->bp_ps = save_r->bp_ps;
+ chunk = *chunk_p;
+ PObj_bufstart(chunk) = ptr;
+ PObj_buflen (chunk) = size_nisp;
+ PObj_sysmem_SET(chunk);
}
void
Parrot_pop_regs(Interp* interpreter)
{
- /*
- * TODO just move the base pointer - no copying needed
- */
- struct parrot_regs_t *bp = stack_prepare_pop(interpreter,
- &CONTEXT(interpreter->ctx)->reg_stack);
- memcpy(interpreter->ctx.bp, bp, sizeof(struct parrot_regs_t));
-}
-
-void
-Parrot_clear_i(Interp *interpreter)
-{
- int i;
- for (i = 0; i < NUM_REGISTERS; ++i)
- REG_INT(i) = 0;
-}
-
-void
-Parrot_clear_s(Interp *interpreter)
-{
- int i;
- for (i = 0; i < NUM_REGISTERS; ++i)
- REG_STR(i) = NULL;
-}
-
-void
-Parrot_clear_p(Interp *interpreter)
-{
- int i;
- for (i = 0; i < NUM_REGISTERS; ++i)
- REG_PMC(i) = PMCNULL;
-}
-
-void
-Parrot_clear_n(Interp *interpreter)
-{
- int i;
- for (i = 0; i < NUM_REGISTERS; ++i)
- REG_NUM(i) = 0.0;
+ Stack_Chunk_t *chunk, **chunk_p;
+ save_regs_t *save_r;
+ parrot_context_t *ctx;
+
+ ctx = CONTEXT(interpreter->ctx);
+ chunk_p = &ctx->reg_stack;
+ save_r = stack_prepare_pop(interpreter, chunk_p);
+
+ /* restore register base pointers */
+ interpreter->ctx.bp = ctx->bp = save_r->old_bp_ni;
+ interpreter->ctx.bp_ps = ctx->bp_ps = save_r->old_bp_ps;
+ /* deal with allocated memory, GC handles the chunk itself */
+ chunk = *chunk_p;
+ mem_sys_free(PObj_bufstart(chunk));
+ PObj_bufstart(chunk) = NULL;
+ PObj_buflen (chunk) = 0;
+ PObj_sysmem_CLEAR(chunk);
}
/*
@@ -125,23 +136,24 @@ Marks the register stack and it's regist
void
mark_register_stack(Parrot_Interp interpreter, Stack_Chunk_t* chunk)
{
- struct parrot_regs_t *regs;
int i;
PObj *obj;
struct Interp_Context ctx;
+ save_regs_t *save_r;
for (; ; chunk = chunk->prev) {
pobject_lives(interpreter, (PObj*)chunk);
if (chunk == chunk->prev)
break;
- regs = (struct parrot_regs_t *)STACK_DATAP(chunk);
- /* XXX intermediate hack */
- ctx.bp = regs;
- ctx.bp_ps.regs_p = regs->pmc_reg.registers;
- for (i = 0; i < NUM_REGISTERS; ++i) {
+ save_r = (save_regs_t *)STACK_DATAP(chunk);
+ ctx.bp.regs_i = NULL;
+ ctx.bp_ps.regs_p = save_r->bp_ps.regs_p;
+ for (i = 0; i < save_r->n_regs_pmc; ++i) {
obj = (PObj *)CTX_REG_PMC(&ctx, i);
if (obj)
pobject_lives(interpreter, obj);
+ }
+ for (i = 0; i < save_r->n_regs_str; ++i) {
obj = (PObj *)CTX_REG_STR(&ctx, i);
if (obj)
pobject_lives(interpreter, obj);
@@ -150,6 +162,38 @@ mark_register_stack(Parrot_Interp interp
}
+void
+Parrot_clear_i(Interp *interpreter)
+{
+ int i;
+ for (i = 0; i < NUM_REGISTERS; ++i)
+ REG_INT(i) = 0;
+}
+
+void
+Parrot_clear_s(Interp *interpreter)
+{
+ int i;
+ for (i = 0; i < NUM_REGISTERS; ++i)
+ REG_STR(i) = NULL;
+}
+
+void
+Parrot_clear_p(Interp *interpreter)
+{
+ int i;
+ for (i = 0; i < NUM_REGISTERS; ++i)
+ REG_PMC(i) = PMCNULL;
+}
+
+void
+Parrot_clear_n(Interp *interpreter)
+{
+ int i;
+ for (i = 0; i < NUM_REGISTERS; ++i)
+ REG_NUM(i) = 0.0;
+}
+
/*
Modified: trunk/src/sub.c
==============================================================================
--- trunk/src/sub.c (original)
+++ trunk/src/sub.c Mon Oct 24 16:06:01 2005
@@ -65,10 +65,12 @@ mark_context(Interp* interpreter, parrot
obj = (PObj*)ctx->current_package;
if (obj)
pobject_lives(interpreter, obj);
- for (i = 0; i < NUM_REGISTERS; ++i) {
+ for (i = 0; i < ctx->n_regs_used[REGNO_PMC]; ++i) {
obj = (PObj*) CTX_REG_PMC(ctx, i);
if (obj)
pobject_lives(interpreter, obj);
+ }
+ for (i = 0; i < ctx->n_regs_used[REGNO_STR]; ++i) {
obj = (PObj*) CTX_REG_STR(ctx, i);
if (obj)
pobject_lives(interpreter, obj);