cvsuser     03/02/28 06:21:45

  Modified:    .        .cvsignore MANIFEST jit.c packfile.c
               config/gen/makefiles imcc.in
               jit/i386 jit_emit.h
               languages/imcc cfg.c cfg.h imc.c imcc.y instructions.c
                        instructions.h optimizer.c pbc.c pbc.h symreg.c
  Added:       languages/imcc jit.c
  Log:
  imcc-Oj-3 s. the announce on perl6-internals
  
  Revision  Changes    Path
  1.25      +2 -0      parrot/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  RCS file: /cvs/public/parrot/.cvsignore,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -w -r1.24 -r1.25
  --- .cvsignore        5 Dec 2002 01:42:44 -0000       1.24
  +++ .cvsignore        28 Feb 2003 14:21:38 -0000      1.25
  @@ -2,6 +2,8 @@
   config.opt
   *_ops_cg.h
   core_ops_cg.c
  +*_ops_cgp.h
  +core_ops_cgp.c
   core_ops.c
   core_ops_prederef.c
   disassemble
  
  
  
  1.319     +1 -0      parrot/MANIFEST
  
  Index: MANIFEST
  ===================================================================
  RCS file: /cvs/public/parrot/MANIFEST,v
  retrieving revision 1.318
  retrieving revision 1.319
  diff -u -w -r1.318 -r1.319
  --- MANIFEST  24 Feb 2003 06:58:37 -0000      1.318
  +++ MANIFEST  28 Feb 2003 14:21:38 -0000      1.319
  @@ -1389,6 +1389,7 @@
   languages/imcc/imcparser.h
   languages/imcc/instructions.c
   languages/imcc/instructions.h
  +languages/imcc/jit.c
   languages/imcc/main.c
   languages/imcc/optimizer.c
   languages/imcc/optimizer.h
  
  
  
  1.60      +119 -58   parrot/jit.c
  
  Index: jit.c
  ===================================================================
  RCS file: /cvs/public/parrot/jit.c,v
  retrieving revision 1.59
  retrieving revision 1.60
  diff -u -w -r1.59 -r1.60
  --- jit.c     25 Feb 2003 10:25:32 -0000      1.59
  +++ jit.c     28 Feb 2003 14:21:38 -0000      1.60
  @@ -1,13 +1,15 @@
   /*
    * jit.c
    *
  - * $Id: jit.c,v 1.59 2003/02/25 10:25:32 leo Exp $
  + * $Id: jit.c,v 1.60 2003/02/28 14:21:38 leo Exp $
    */
   
   #include <parrot/parrot.h>
  +#include <assert.h>
   #include "parrot/jit.h"
   #define JIT_EMIT 0
   #include "parrot/jit_emit.h"
  +#include "parrot/packfile.h"
   
   /*
    * s. jit/$arch/jit_emit.h for the meaning of these defs
  @@ -52,7 +54,25 @@
   void Parrot_jit_debug(struct Parrot_Interp* interpreter);
   #endif
   
  -/* #define JIT_IMCC_OJ */
  +/* look at fixups, mark all fixup entries as branch target */
  +static void
  +insert_fixup_targets(struct Parrot_Interp* interpreter, char *branch,
  +        size_t limit)
  +{
  +    struct PackFile_FixupTable *ft = interpreter->code->fixup_table;
  +    int i;
  +
  +    if (!ft)
  +        return;
  +    for (i = 0; i < ft->fixup_count; i++) {
  +        switch (ft->fixups[i]->type) {
  +            case 0:
  +                if ((size_t)ft->fixups[i]->u.t0.offset < limit)
  +                    branch[ft->fixups[i]->u.t0.offset] |= JIT_BRANCH_TARGET;
  +                break;
  +        }
  +    }
  +}
   
   /*
    * optimizer->map_branch parallels the opcodes with a list of
  @@ -161,20 +181,7 @@
           /* Move to the next opcode */
           cur_op += op_info->arg_count;
       }
  -    /* now look at fixups, mark all fixup entries as branch target */
  -    {
  -        struct PackFile_FixupTable *ft = interpreter->code->fixup_table;
  -        int i;
  -        if (!ft)
  -            return;
  -        for (i = 0; i < ft->fixup_count; i++) {
  -            switch (ft->fixups[i]->type) {
  -                case 0:
  -                    branch[ft->fixups[i]->u.t0.offset] |= JIT_BRANCH_TARGET;
  -                    break;
  -            }
  -        }
  -    }
  +    insert_fixup_targets(interpreter, branch, code_end - code_start);
   }
   
   static void
  @@ -200,10 +207,8 @@
               case PARROT_ARG_I:
               case PARROT_ARG_KI:
                   typ = 0;
  -#ifdef JIT_IMCC_OJ
                   if (idx < 0)
                       idx = -1 - idx;
  -#endif /* JIT_IMCC_OJ */
                   break;
               case PARROT_ARG_P:
               case PARROT_ARG_K:
  @@ -213,10 +218,8 @@
                   typ = 2;
                   break;
               case PARROT_ARG_N:
  -#ifdef JIT_IMCC_OJ
                   if (idx < 0)
                       idx = -1 - idx;
  -#endif /* JIT_IMCC_OJ */
                   typ = 3;
                   break;
               default:
  @@ -241,8 +244,11 @@
                   UINTVAL flags = PObj_get_FLAGS(key);
                   if (flags & KEY_register_FLAG) {
                       INTVAL n = key->cache.int_val;
  -                    if (flags & KEY_integer_FLAG)
  +                    if (flags & KEY_integer_FLAG) {
                           typ = 0;
  +                        if (n < 0)
  +                            n = -1 - n;
  +                    }
                       else if (flags & KEY_pmc_FLAG)
                           typ = 1;
                       else if (flags & KEY_string_FLAG)
  @@ -277,7 +283,7 @@
       opcode_t *next_op;
       op_info_t *op_info;
       char *branch;
  -    int i, typ, branched, start_new;
  +    int branched, start_new;
   
       branch = optimizer->map_branch;
   
  @@ -479,13 +485,6 @@
                   }
               }
               ru[typ].registers_used = k;
  -#ifdef JIT_IMCC_OJ
  -            for (i = 0; i < to_map[typ]; i++) {
  -                ru[typ].reg_usage[i] = i;
  -                /* set rn1, N1 */
  -            }
  -            ru[typ].registers_used = to_map[typ];
  -#endif /* JIT_IMCC_OJ */
           }
           next = cur_section->next;
           prev = cur_section;
  @@ -511,16 +510,13 @@
   assign_registers(struct Parrot_Interp *interpreter,
           Parrot_jit_optimizer_t *optimizer,
           Parrot_jit_optimizer_section_ptr cur_section,
  -        opcode_t * code_start)
  +        opcode_t * code_start, int from_imcc)
   {
       char *map;
       op_info_t *op_info;
       int i, op_arg, typ;
       opcode_t * cur_op;
       char * maps[] = {0, 0, 0, 0};
  -#ifdef JIT_IMCC_OJ
  -    int to_map[] = { INT_REGISTERS_TO_MAP, 0, 0, FLOAT_REGISTERS_TO_MAP };
  -#endif
       maps[0] = intval_map;
       maps[3] = floatval_map;
   
  @@ -543,21 +539,18 @@
                   if (!maps[typ])
                       continue;
                   /* If the argument is in most used list for this typ */
  -#ifndef JIT_IMCC_OJ
  -                for (i = 0; i < cur_section->ru[typ].registers_used; i++)
  -                    if (cur_op[op_arg] ==
  -                            (opcode_t)cur_section->ru[typ].reg_usage[i]) {
  -#else /* JIT_IMCC_OJ */
  -                for (i = 0; i < to_map[typ]; i++)
  -                    if (-1 - cur_op[op_arg] ==
  -                            (opcode_t)cur_section->ru[typ].reg_usage[i]) {
  -#endif /* JIT_IMCC_OJ */
  +                for (i = 0; i < cur_section->ru[typ].registers_used; i++) {
  +                    opcode_t idx = cur_op[op_arg];
  +                    if (from_imcc)
  +                        idx = -1 - idx;
  +                    if (idx == (opcode_t)cur_section->ru[typ].reg_usage[i]) {
                           map[cur_op + op_arg - code_start] = maps[typ][i];
                           cur_section->maps++;
                           break;
                       }
               }
           }
  +        }
   
           /* Move to the next opcode */
           cur_op += op_info->arg_count;
  @@ -576,7 +569,7 @@
       /* While there is section */
       while (cur_section) {
   
  -        assign_registers(interpreter, optimizer, cur_section, code_start);
  +        assign_registers(interpreter, optimizer, cur_section, code_start, 0);
   
           /* Move to the next section */
           cur_section = cur_section->next;
  @@ -702,6 +695,69 @@
       return optimizer;
   }
   
  +/* generate optimizer stuff from the _JIT section in the packfile */
  +static Parrot_jit_optimizer_t *
  +optimize_imcc_jit(struct Parrot_Interp *interpreter, opcode_t *cur_op,
  +             opcode_t *code_start, opcode_t *code_end,
  +             struct PackFile_Segment *jit_seg)
  +{
  +    Parrot_jit_optimizer_t *optimizer;
  +    size_t size, i, typ;
  +    int j;
  +    opcode_t *ptr, offs;
  +    Parrot_jit_optimizer_section_ptr section, prev;
  +    char *branch;
  +    op_info_t *op_info;
  +
  +    /* Allocate space for the optimizer */
  +    optimizer = (Parrot_jit_optimizer_t *)
  +        mem_sys_allocate_zeroed(sizeof(Parrot_jit_optimizer_t));
  +    optimizer->map_branch = branch =
  +        (char *)mem_sys_allocate_zeroed((size_t)(code_end - code_start));
  +    ptr = jit_seg->data;
  +    size = jit_seg->size;
  +    assert(jit_seg->itype == 0);
  +    assert((size % 6) == 0);
  +    cur_op = code_start;
  +    for (prev = NULL, i = 0; i < size/6; i++, prev = section) {
  +        section = (Parrot_jit_optimizer_section_t *)
  +            mem_sys_allocate_zeroed(sizeof(Parrot_jit_optimizer_section_t));
  +        if (prev)
  +            prev->next = section;
  +        else
  +            optimizer->sections = section;
  +        section->prev = prev;
  +        section->block = i;
  +        offs = *ptr++;
  +        if (offs & 0x80000000) {
  +            offs &= ~0x80000000;
  +            branch[offs] = JIT_BRANCH_TARGET;
  +        }
  +        section->begin = code_start + offs;
  +        section->end = code_start + *ptr++;
  +        section->isjit = 1;
  +        for (typ = 0; typ < 4; typ++) {
  +            section->ru[typ].registers_used = *ptr++;
  +            for (j = 0; j < section->ru[typ].registers_used; j++)
  +                section->ru[typ].reg_usage[j] = j;
  +
  +        }
  +        while (cur_op <= section->end) {
  +            op_info = &interpreter->op_info_table[*cur_op];
  +            set_register_usage(interpreter, optimizer, section,
  +                    op_info, cur_op, code_start);
  +            section->op_count++;
  +            cur_op += op_info->arg_count;
  +        }
  +        assign_registers(interpreter, optimizer, section, code_start, 1);
  +    }
  +    insert_fixup_targets(interpreter, branch, code_end - code_start);
  +#if JIT_DEBUG
  +    debug_sections(interpreter, optimizer, code_start);
  +#endif
  +    return optimizer;
  +}
  +
   static char *
   reg_addr(struct Parrot_Interp * interpreter, int typ, int i)
   {
  @@ -830,6 +886,8 @@
       Parrot_jit_info_t *jit_info = NULL;
       opcode_t cur_opcode_byte, *cur_op;
       Parrot_jit_optimizer_section_ptr cur_section;
  +    struct PackFile_Segment *jit_seg;
  +    char *name;
       char *map;
   
   
  @@ -842,7 +900,16 @@
           jit_info = interpreter->jit_info =
               mem_sys_allocate(sizeof(Parrot_jit_info_t));
   
  -    jit_info->optimizer = optimize_jit(interpreter, pc, code_start, code_end);
  +    name = malloc(strlen(interpreter->code->cur_cs->base.name) + 5);
  +    sprintf(name, "%s_JIT", interpreter->code->cur_cs->base.name);
  +    jit_seg = PackFile_find_segment(interpreter->code, name);
  +    free(name);
  +    if (jit_seg)
  +        jit_info->optimizer =
  +            optimize_imcc_jit(interpreter, pc, code_start, code_end, jit_seg);
  +    else
  +        jit_info->optimizer =
  +            optimize_jit(interpreter, pc, code_start, code_end);
   
       /* Attach the register map to the jit_info structure */
       jit_info->intval_map = intval_map;
  @@ -899,11 +966,9 @@
           cur_op = jit_info->cur_op = cur_section->begin;
   
           /* Load mapped registers for this section, if JIT */
  -#ifndef JIT_IMCC_OJ
  -        if (cur_section->isjit) {
  +        if (!jit_seg && cur_section->isjit) {
               Parrot_jit_load_registers(jit_info, interpreter);
           }
  -#endif /* JIT_IMCC_OJ */
   
           /* The first opcode of each section doesn't have a previous one since
            * it's impossible to be sure which was it */
  @@ -935,14 +1000,12 @@
                * and also, if we have a jitted sections and encounter
                * and "end" opcode, e.g. in evaled code
                */
  -#ifndef JIT_IMCC_OJ
               if ((((map[cur_op - code_start] == JIT_BRANCH_SOURCE) &&
                       (cur_section->branch_target != cur_section)) ||
                           !cur_opcode_byte) &&
                       cur_section->isjit) {
                   Parrot_jit_save_registers(jit_info, interpreter);
               }
  -#endif /* JIT_IMCC_OJ */
   
               /* Generate native code for current op */
               (op_jit[cur_opcode_byte].fn) (jit_info, interpreter);
  @@ -975,10 +1038,8 @@
           }
   
           /* Save mapped registers back to the Parrot registers */
  -#ifndef JIT_IMCC_OJ
  -        if (cur_section->isjit)
  +        if (!jit_seg && cur_section->isjit)
               Parrot_jit_save_registers(jit_info, interpreter);
  -#endif /* JIT_IMCC_OJ */
   
           /* update the offset for saved registers */
           jit_info->arena.op_map[jit_info->op_i].offset =
  
  
  
  1.78      +3 -2      parrot/packfile.c
  
  Index: packfile.c
  ===================================================================
  RCS file: /cvs/public/parrot/packfile.c,v
  retrieving revision 1.77
  retrieving revision 1.78
  diff -u -w -r1.77 -r1.78
  --- packfile.c        18 Feb 2003 20:36:59 -0000      1.77
  +++ packfile.c        28 Feb 2003 14:21:38 -0000      1.78
  @@ -7,7 +7,7 @@
   ** This program is free software. It is subject to the same
   ** license as Parrot itself.
   **
  -** $Id: packfile.c,v 1.77 2003/02/18 20:36:59 leo Exp $
  +** $Id: packfile.c,v 1.78 2003/02/28 14:21:38 leo Exp $
   **
   ** History:
   **  Rework by Melvin; new bytecode format, make bytecode portable.
  @@ -845,7 +845,8 @@
       if (i % 8)
           PIO_printf(interpreter, "\n %04x:  ", (int) i);
   
  -    for ( ; i < self->file_offset+self->op_count; i++) {
  +    for ( ; i < (self->size ? self->file_offset+self->size + 4 :
  +            self->file_offset + self->op_count); i++) {
           if (i % 8 == 0) {
               PIO_printf(interpreter, "\n %04x:  ", (int) i);
           }
  
  
  
  1.13      +1 -1      parrot/config/gen/makefiles/imcc.in
  
  Index: imcc.in
  ===================================================================
  RCS file: /cvs/public/parrot/config/gen/makefiles/imcc.in,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -w -r1.12 -r1.13
  --- imcc.in   8 Feb 2003 17:16:13 -0000       1.12
  +++ imcc.in   28 Feb 2003 14:21:39 -0000      1.13
  @@ -14,7 +14,7 @@
   
   IMCC_O_FILES = imcparser$(O) imclexer$(O) imc$(O) stacks$(O) symreg$(O) \
        instructions$(O) cfg$(O) sets$(O) debug$(O) \
  -     optimizer$(O) pbc$(O) main$(O) parser_util$(O)
  +     optimizer$(O) pbc$(O) main$(O) parser_util$(O) jit$(O)
   
   
   O_FILES = $(IMCC_O_FILES) \
  
  
  
  1.58      +1 -5      parrot/jit/i386/jit_emit.h
  
  Index: jit_emit.h
  ===================================================================
  RCS file: /cvs/public/parrot/jit/i386/jit_emit.h,v
  retrieving revision 1.57
  retrieving revision 1.58
  diff -u -w -r1.57 -r1.58
  --- jit_emit.h        25 Feb 2003 10:25:38 -0000      1.57
  +++ jit_emit.h        28 Feb 2003 14:21:41 -0000      1.58
  @@ -3,7 +3,7 @@
    *
    * i386
    *
  - * $Id: jit_emit.h,v 1.57 2003/02/25 10:25:38 leo Exp $
  + * $Id: jit_emit.h,v 1.58 2003/02/28 14:21:41 leo Exp $
    */
   
   #include <assert.h>
  @@ -2714,10 +2714,6 @@
    * set this to 1 or 0 to change allocation scheme
    */
   #  define ALLOCATE_REGISTERS_PER_SECTION 1
  -
  -#define MAP(i) OMAP(i)
  -#undef MAP
  -#define MAP(i) (i) >= 0 : 0 ? OMAP(i)
   
   
   /*
  
  
  
  1.21      +99 -73    parrot/languages/imcc/cfg.c
  
  Index: cfg.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/cfg.c,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -w -r1.20 -r1.21
  --- cfg.c     23 Feb 2003 20:21:09 -0000      1.20
  +++ cfg.c     28 Feb 2003 14:21:43 -0000      1.21
  @@ -14,13 +14,14 @@
    * flow of execution between blocks.
    */
   
  +static void add_instruc_reads(Instruction *ins, SymReg *r0);
   
   /* Code: */
   
   
   void find_basic_blocks () {
       Basic_block *bb;
  -    Instruction *ins, *lab;
  +    Instruction *ins;
       int nu = 0;
       int i;
   
  @@ -29,7 +30,7 @@
       for(i = 0; i < HASH_SIZE; i++) {
           SymReg * r = hash[i];
           if (r && (r->type & VTADDRESS)) {
  -            r->first_ins = r->last_ins = NULL;
  +            r->last_ins = NULL;
           }
       }
   
  @@ -37,11 +38,7 @@
       ins->index = i = 0;
   
       bb = make_basic_block(ins);
  -    if ( (ins->type & ITLABEL)) {
  -        /* set the labels address (ins) */
  -        ins->r[0]->first_ins = ins;
  -    }
  -    else if (ins->type & ITBRANCH) {
  +    if (ins->type & ITBRANCH) {
           SymReg * addr = get_branch_reg(bb->end);
           if (addr)
               addr->last_ins = ins;
  @@ -51,6 +48,17 @@
   
           bb->end = ins;
           ins->bbindex = n_basic_blocks - 1;
  +        /* invoke w/o arg implicitly uses P0, so mark it as doing so
  +         * XXX but in the parser
  +         */
  +        if (ins->opsize == 1 && !strcmp(ins->op, "invoke")) {
  +            SymReg * p0 = mk_pasm_reg(str_dup("P0"));
  +            add_instruc_reads(ins, p0);
  +            ins->type |= 1;      /* mark branch register */
  +            dont_optimize = 1;  /* too complex, to follow */
  +            optimizer_level &= ~OPT_PASM;
  +            p0->use_count++;
  +        }
           /* a LABEL starts a new basic block, but not, if we have
            * a new one (last was a branch) */
           if ( (ins->type & ITLABEL)) {
  @@ -60,6 +68,11 @@
           if (nu)
               nu = 0;
           else if ( (ins->type & ITLABEL)) {
  +            /* XXX look at this change bb->end did include the label,
  +             * now no more
  +             * s. t/rx/basic_6
  +             */
  +            bb->end = ins->prev;
               bb = make_basic_block(ins);
           }
           /* a branch is the end of a basic block
  @@ -77,28 +90,31 @@
               if (!strcmp(ins->op, "bsr") || !strcmp(ins->op, "set_addr")) {
                   char *name =
                       *ins->op == 'b' ? ins->r[0]->name : ins->r[1]->name;
  -                found = 0;
  -                /* TODO get_sym */
  -                for (lab = instructions; lab; lab = lab->next) {
  -                    if ((lab->type & ITLABEL) &&
  -                            !strcmp(lab->r[0]->name, name)) {
  -                        int j = 0;
  -                        found = 1;
  -                        /* XXX look if first 5 ins have saveall
  -                         * this is a ugly but working hack ;-)
  -                         */
  -                        for (lab = lab->next; j < 5 && lab;
  +                SymReg *r = get_sym(name);
  +                if (*ins->op == 'b') {
  +                    Instruction * lab;
  +                    found = r != NULL && r->first_ins;
  +                    debug(DEBUG_CFG, "bsr %s local:%s\n",
  +                            name, found ? "yes": "no");
  +                    if (r) {
  +                        int j;
  +                        lab = r->first_ins;
  +                        if (lab)
  +                            for (j = 0, lab = lab->next; j < 5 && lab;
                                   lab = lab->next, j++) {
                               if (!strcmp(lab->op, "saveall")) {
  -                                found = 0;
  +                                    ins->type |= ITSAVES;
  +                                    lab->type |= ITSAVES;
  +                                    debug(DEBUG_CFG, "\ttype saveall\n");
                                   break;
                               }
                           }
  -                        break;
                       }
                   }
  -                debug(DEBUG_CFG, "bsr %s local:%s\n",
  -                        name, found ? "yes": "no");
  +                else {
  +                    /* treat the set_addr as jump source */
  +                    found = 1;
  +                }
               }
               if (found) {
                   if (ins->next)
  @@ -120,7 +136,7 @@
   void build_cfg() {
       int i, j;
       SymReg * addr;
  -    Basic_block *last, *bb;
  +    Basic_block *last = NULL, *bb;
       Edge *pred;
   
       info(2, "build_cfg\n");
  @@ -135,30 +151,47 @@
           if (addr)
               bb_findadd_edge(bb, addr);
           if (!strcmp(bb->end->op, "ret")) {
  +            int found = 0;
               debug(DEBUG_CFG, "found ret in bb %d\n", i);
               /* now go back, find labels and connect these with
                * bsrs
                */
  -            for (pred = bb->pred_list; pred; pred=pred->pred_next) {
  +            for (pred = bb->pred_list; pred; pred=pred->next) {
                   if (!strcmp(pred->from->end->op, "bsr")) {
  +                    Instruction * sub;
  +
                       SymReg *r = pred->from->end->r[0];
  -                    int found = 0;
   
                       j = pred->from->index;
  -                    debug(DEBUG_CFG, "\tcalled from bb %d label '%s'? - ",
  -                            j, r->name);
  -                    if ((bb->start->type & ITLABEL) &&
  -                            (!strcmp(bb->start->r[0]->name, r->name)))
  +                    sub = pred->to->start;
  +                    if ((sub->type & ITLABEL) &&
  +                            (!strcmp(sub->r[0]->name, r->name)))
                           found = 1;
                       if (found) {
  -                        debug(DEBUG_CFG, "yep!\n");
  +                        int saves = 0;
  +                        debug(DEBUG_CFG, "\tcalled from bb %d '%s'\n",
  +                            j, ins_string(pred->from->end));
  +                        for (; sub && sub != bb->end; sub = sub->next) {
  +                            if (!strcmp(sub->op, "saveall"))
  +                                if (!(sub->type & ITSAVES)) {
  +                                    break;
  +                                }
  +                            bb_list[sub->bbindex]->flag |= BB_IS_SUB;
  +                            if (!strcmp(sub->op, "restoreall")) {
  +                                sub->type |= ITSAVES;
  +                                saves = 1;
  +                            }
  +                        }
  +                        if (!saves)
                           bb_add_edge(bb, bb_list[j+1]);
  +                        debug(DEBUG_CFG, "\tand does saevall %s\n",
  +                                saves ? "yes" : "no");
  +                        break;
                       }
  -                    else
  -                        debug(DEBUG_CFG, "na!\n");
  -
                   }
               }
  +            if (!found)
  +                debug(DEBUG_CFG, "\tcalled from unknown!\n");
           }
   
           last = bb;
  @@ -169,29 +202,23 @@
   /* find the placement of the label, and link the two nodes */
   
   void bb_findadd_edge(Basic_block *from, SymReg *label) {
  -#if 0
  -    /* ugly slow quadratic search for a label takes ~35 s for
  -     * ../../t/op/stacks_33
  -     */
       Instruction *ins;
  -
  -    for (ins = instructions; ins; ins = ins->next) {
  -        if ((ins->type & ITLABEL) && label == ins->r[0]){
  -
  -            bb_add_edge(from, bb_list[ins->bbindex]);
  -            return;
  -
  -            /* a label appears just once */
  -
  -        }
  -    }
  -#else
  -    SymReg *r = get_sym(label->name);
  +    SymReg *r = find_sym(label->name);
   
       if (r && (r->type & VTADDRESS) && r->first_ins)
           bb_add_edge(from, bb_list[r->first_ins->bbindex]);
  -
  -#endif
  +    else {
  +        debug(DEBUG_CFG, "register branch %s ",
  +                ins_string(from->end));
  +        for (ins = from->end; ins; ins = ins->prev) {
  +            if ((ins->type & ITBRANCH) && !strcmp(ins->op, "set_addr")) {
  +                bb_add_edge(from, bb_list[ins->r[1]->first_ins->bbindex]);
  +                debug(DEBUG_CFG, "(%s) ", ins->r[1]->name);
  +                break;
  +            }
  +        }
  +        debug(DEBUG_CFG, "\n");
  +    }
   }
   
   
  @@ -310,12 +337,6 @@
                ins = curr;
            }
        }
  -        /* invoke w/o arg implicitly uses P0, so mark it as doing so */
  -        else if (ins->opsize == 1 && !strcmp(ins->op, "invoke")) {
  -            SymReg * p0 = mk_pasm_reg(str_dup("P0"));
  -            add_instruc_reads(ins, p0);
  -            p0->use_count++;
  -        }
       }
       if (IMCC_DEBUG & DEBUG_CFG) {
        debug(DEBUG_CFG, "\nAfter propagate_alias\n");
  @@ -367,11 +388,14 @@
   void free_life_info(SymReg *r)
   {
       int i;
  +    if (r->life_info) {
       for (i=0; i < n_basic_blocks; i++) {
        if (r->life_info[i])
               free(r->life_info[i]);
       }
       free(r->life_info);
  +        r->life_info = NULL;
  +    }
   }
   
   /* analyse_life_block studies the state of the var r
  @@ -569,7 +593,7 @@
        * order of finding loops
        */
       for (i = 0; i < n_loops-1; i++) {
  -        int first = -1, last;
  +        int first = -1, last = 0;
           loop_info[i]->depth = 1;
           /* we could also take the depth of the first contained
            * block, but below is a check, that a inner loop is fully
  @@ -730,10 +754,12 @@
   
   void clear_basic_blocks() {
       int i;
  +    if (bb_list) {
       for (i=0; i < n_basic_blocks; i++)
           free(bb_list[i]);
       free(bb_list);
       bb_list = NULL;
  +    }
       free_edge();
       free_dominators();
       free_loops();
  
  
  
  1.7       +5 -0      parrot/languages/imcc/cfg.h
  
  Index: cfg.h
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/cfg.h,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -w -r1.6 -r1.7
  --- cfg.h     22 Dec 2002 17:23:04 -0000      1.6
  +++ cfg.h     28 Feb 2003 14:21:43 -0000      1.7
  @@ -19,7 +19,12 @@
       Edge *succ_list;
       int loop_depth;
       int index;                  /*on bb_list*/
  +    int flag;
   } Basic_block;
  +
  +enum {
  +     BB_IS_SUB = 1 << 0
  +} block_enum_flags;
   
   /* Globals: */
   EXTERN Basic_block **bb_list;
  
  
  
  1.41      +50 -208   parrot/languages/imcc/imc.c
  
  Index: imc.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/imc.c,v
  retrieving revision 1.40
  retrieving revision 1.41
  diff -u -w -r1.40 -r1.41
  --- imc.c     25 Feb 2003 10:25:45 -0000      1.40
  +++ imc.c     28 Feb 2003 14:21:43 -0000      1.41
  @@ -15,14 +15,10 @@
   #include <assert.h>
   #include "imc.h"
   #include "optimizer.h"
  -#define JIT_IMCC
  -#include "parrot/jit.h"
  -#include "parrot/jit_emit.h"
   
   static void make_stat(int *sets, int *cols);
   static void imc_stat_init(void);
   static void print_stat(void);
  -static void allocate_jit(struct Parrot_Interp *interpreter);
   
   extern int pasm_file;
   /* Globals: */
  @@ -54,7 +50,7 @@
           return;
   
       nodeStack = imcstack_new();
  -    dont_optimize = n_spilled = 0;
  +    n_spilled = 0;
   
       todo = first = 1;
       while (todo) {
  @@ -115,15 +111,8 @@
       }
       if (IMCC_DEBUG & DEBUG_IMC)
           dump_instructions();
  -    if (optimizer_level & OPT_J) {
  -        allocate_jit(interpreter);
  -        if (IMCC_DEBUG & DEBUG_IMC)
  -            dump_instructions();
  -    }
       if (IMCC_VERBOSE > 1 || (IMCC_DEBUG & DEBUG_IMC))
           print_stat();
  -    free_reglist();
  -    clear_basic_blocks();       /* and cfg ... */
       imcstack_free(nodeStack);
   }
   
  @@ -133,8 +122,12 @@
           interference_graph = 0;
       }
       if (reglist) {
  +        int i;
  +        for (i = 0; i < n_symbols; i++)
  +            free_life_info(reglist[i]);
           free(reglist);
  -        reglist = 0;
  +        reglist = NULL;
  +        n_symbols = 0;
       }
   }
   
  @@ -274,8 +267,11 @@
    * same time
    */
   
  -void build_interference_graph() {
  +void
  +build_interference_graph()
  +{
        int x, y;
  +
       if (!n_symbols)
           return;
   
  @@ -463,15 +459,36 @@
          l0 = r0->life_info[i];
          l1 = r1->life_info[i];
   
  +        /* one or both are not alive in this block, so we have
  +         * no conflict
  +         */
          if (!l0->first_ins || !l1->first_ins)
            continue;
   
  +        /* if the registers don't overlap, i.e first_x > last_y
  +         * then no interference
  +         */
          if (l0->first_ins->index > l1->last_ins->index)
            continue;
  -
          if (l1->first_ins->index > l0->last_ins->index)
            continue;
   
  +#if 1
  +        /* if they only overlap one instruction and one is used RHS only
  +         * and the other LHS, then that's ok
  +         */
  +        if (l0->first_ins->index == l1->last_ins->index &&
  +                instruction_writes(l0->first_ins, r0) &&
  +                instruction_reads(l1->last_ins, r1) &&
  +                !instruction_reads(l0->first_ins, r0))
  +            continue;
  +        if (l1->first_ins->index == l0->last_ins->index &&
  +                instruction_writes(l1->first_ins, r1) &&
  +                instruction_reads(l0->last_ins, r0) &&
  +                !instruction_reads(l1->first_ins, r1))
  +            continue;
  +#endif
  +
          return 1;
       }
   
  @@ -529,7 +546,7 @@
    */
   
   void order_spilling () {
  -    int min_score, total_score;
  +    int min_score = 0, total_score;
       int min_node;
       int x;
   
  @@ -763,181 +780,6 @@
   
       return cnt;
   }
  -
  -/* PASM registers are already in most used order, so now:
  - * - consider the top N registers as processor registers
  - * - look at the instruction stream and insert register load/store ins
  - *   for e.g. calling out to unJITted functions
  - *   This is of course processor dependend
  - *
  - * NOTE: rx_ ops may have a inout INT parameter for position/mark.
  - *       Actually, the either branch or update the inout parameter
  - *       so they are save.
  - */
  -
  -#ifndef EXTCALL
  -#  define EXTCALL(op) op_jit[*(op)].extcall
  -#endif
  -
  -#ifndef INT_REGISTERS_TO_MAP
  -#  define INT_REGISTERS_TO_MAP 0
  -#endif
  -
  -#ifndef FLOAT_REGISTERS_TO_MAP
  -#  define FLOAT_REGISTERS_TO_MAP 0
  -#endif
  -
  -#ifndef PRESERVED_INT_REGS
  -#  define PRESERVED_INT_REGS MAX_MAPPED
  -#endif
  -
  -#ifndef PRESERVED_FLOAT_REGS
  -#  define PRESERVED_FLOAT_REGS MAX_MAPPED
  -#endif
  -
  -static void
  -allocate_jit(struct Parrot_Interp *interpreter)
  -{
  -    int c, j, k, typ;
  -    int to_map[4] = {0,0,0,0};
  -#define MAX_MAPPED 32
  -    int preserved[] =
  -    {PRESERVED_INT_REGS, MAX_MAPPED, MAX_MAPPED, PRESERVED_FLOAT_REGS};
  -    const char *types = "IPSN";
  -    Instruction * ins, *last, *tmp, *prev;
  -    SymReg * r;
  -    SymReg * regs[IMCC_MAX_REGS];
  -    static SymReg  *cpu[4][MAX_MAPPED];
  -    static SymReg  *par[4][MAX_MAPPED];
  -    int reads[4][MAX_MAPPED], writes[4][MAX_MAPPED], nr, nw;
  -    int maxc[4] = {0,0,0,0};
  -
  -    assert(INT_REGISTERS_TO_MAP < MAX_MAPPED);
  -    assert(FLOAT_REGISTERS_TO_MAP < MAX_MAPPED);
  -    to_map[0] = INT_REGISTERS_TO_MAP;
  -    to_map[3] = FLOAT_REGISTERS_TO_MAP;
  -    /* make a list of mapped cpu regs */
  -    if (cpu[0][0] == NULL) {
  -        for (typ = 0; typ < 4; typ++)
  -            for (k = 0; k < to_map[typ]; k++) {
  -                char name[16];
  -                sprintf(name, "%c%d#c", types[typ], k);
  -                cpu[typ][k] = mk_pasm_reg(str_dup(name));
  -                cpu[typ][k]->color = -1 - k;
  -                sprintf(name, "%c%d#p", types[typ], k);
  -                par[typ][k] = mk_pasm_reg(str_dup(name));
  -            }
  -    }
  -    prev = last = NULL;
  -    nr = nw = 0;
  -    /* change all mappable registers to mapped ones */
  -    for (j = 0; j < n_symbols; j++) {
  -        r = reglist[j];
  -        typ = strchr(types, r->set) - types;
  -        if (r->color < to_map[typ]) {
  -            if (r->color >= maxc[typ])
  -                maxc[typ] = r->color + 1;
  -            r->color = -1 - r->color;
  -        }
  -
  -    }
  -    to_map[0] = maxc[0];
  -    to_map[3] = maxc[3];
  -    /* clear all used regs at beginning */
  -    for (typ = 0; typ < 4; typ++)
  -        for (j = 0; j < to_map[typ]; j++) {
  -            regs[0] = cpu[typ][j];
  -            regs[1] = par[typ][j];
  -            tmp = INS(interpreter, "set", "%s, %s\t# init",
  -                    regs, 2, 0, 0);
  -            insert_ins(NULL, tmp);
  -        }
  -    /* TODO restore regs before end if non main */
  -    for (ins = instructions; ins; prev = ins, ins = ins->next) {
  -        /* clear preserved regs, set rw of non preserved regs */
  -        for (typ = 0; ins != instructions && typ < 4; typ++)
  -            for (k = 0; k < to_map[typ]; k++) {
  -                reads[typ][k] = writes[typ][k] =
  -                    k >= preserved[typ];
  -            }
  -        /* if extern, go through regs and check the usage */
  -        if (ins->opnum >= 0 && EXTCALL(&ins->opnum)) {
  -            nr = nw = 1;
  -            /* TODO stop at basic block end */
  -            for (last = ins; ins && ins->opnum >= 0 && EXTCALL(&ins->opnum);
  -                    ins = ins->next) {
  -                ins->type |= ITEXT;
  -                for (j = 0; j < n_symbols; j++) {
  -                    r = reglist[j];
  -                    if (r->color >= 0)
  -                        continue;
  -                    typ = strchr(types, r->set) - types;
  -                    c = -1 - r->color;
  -                    if (instruction_reads(ins, r) &&
  -                            instruction_writes(ins, r)) {
  -                        reads[typ][c] = 1;
  -                        writes[typ][c] = 1;
  -                        nr = nw = 1;
  -                    }
  -                    else if (instruction_reads(ins, r)) {
  -                        reads[typ][c] = 1;
  -                        nr = 1;
  -                    }
  -                    else if (instruction_writes(ins, r)) {
  -                        writes[typ][c] = 1;
  -                        nw = 1;
  -                    }
  -                }
  -                /* changed mapped regs to parrot regs */
  -                for (j = 0; (r = ins->r[j]) && j < IMCC_MAX_REGS; j++) {
  -                    typ = strchr(types, r->set) - types;
  -                    if ((r->type & VTREGISTER) && r->color < 0)
  -                        ins->r[j] = par[typ][-1 - r->color];
  -                }
  -                /* remember last extern opcode, all loads are inserted
  -                 * after this instruction
  -                 */
  -                last = ins;
  -                if (ins->type & ITBRANCH) {
  -                    break;
  -                }
  -            }
  -        }
  -        /* insert load ins after non JIT block */
  -        if (last && nw) {
  -            for (typ = 0; typ < 4; typ++)
  -                for (j = 0; j < to_map[typ]; j++) {
  -                    if (!writes[typ][j])
  -                        continue;
  -                    regs[0] = cpu[typ][j];
  -                    regs[1] = par[typ][j];
  -                    tmp = INS(interpreter, "set", "%s, %s\t# load",
  -                            regs, 2, 0, 0);
  -                    insert_ins(last, tmp);
  -                }
  -            nw = 0;
  -        }
  -        /* insert save ins before extern op */
  -        if (nr) {
  -            for (typ = 0; typ < 4; typ++)
  -                for (j = 0; j < to_map[typ]; j++) {
  -                    if (!reads[typ][j])
  -                        continue;
  -                    regs[0] = par[typ][j];
  -                    regs[1] = cpu[typ][j];
  -                    tmp = INS(interpreter, "set", "%s, %s\t# save",
  -                            regs, 2, 0, 0);
  -                    insert_ins(prev, tmp);
  -                }
  -            nr = 0;
  -        }
  -        /* continue with/after last non JIT ins */
  -        if (last)
  -            ins = last;
  -        last = NULL;
  -    }
  -}
  -
   /*
    * Utility functions
    */
  
  
  
  1.50      +6 -0      parrot/languages/imcc/imcc.y
  
  Index: imcc.y
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/imcc.y,v
  retrieving revision 1.49
  retrieving revision 1.50
  diff -u -w -r1.49 -r1.50
  --- imcc.y    25 Feb 2003 10:25:45 -0000      1.49
  +++ imcc.y    28 Feb 2003 14:21:43 -0000      1.50
  @@ -121,6 +121,7 @@
   static Instruction * iLABEL(SymReg * r0) {
       Instruction *i = _mk_instruction("","%s:", R1(r0), 0);
       i->type = ITLABEL;
  +    r0->first_ins = i;
       i = emitb(i);
       clear_state();
       return i;
  @@ -356,6 +357,11 @@
                   ins->type = ITBRANCH | (1 << (nargs-1));
                   if (!strcmp(name, "branch") || !strcmp(name, "end"))
                       ins->type |= IF_goto;
  +                if (!strcmp(fullname, "jump_i") ||
  +                        !strcmp(fullname, "jsr_i") ||
  +                        !strcmp(fullname, "branch_i") ||
  +                        !strcmp(fullname, "bsr_i"))
  +                    dont_optimize = 1;
               }
           }
           else if (!strcmp(name, "set") && nargs == 2) {
  
  
  
  1.30      +22 -10    parrot/languages/imcc/instructions.c
  
  Index: instructions.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/instructions.c,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -w -r1.29 -r1.30
  --- instructions.c    25 Feb 2003 10:25:45 -0000      1.29
  +++ instructions.c    28 Feb 2003 14:21:43 -0000      1.30
  @@ -62,14 +62,17 @@
   void
   close_comp_unit(void)
   {
  +    free_reglist();
  +    clear_basic_blocks();       /* and cfg ... */
       if (!n_comp_units)
           fatal(1, "close_comp_unit", "non existent comp_unit\n");
       n_comp_units--;
       instructions = comp_unit[n_comp_units].instructions;
       last_ins = comp_unit[n_comp_units].last_ins;
       clear_tables();
  -    free(comp_unit[n_comp_units].hash[0]);
       if (n_comp_units) {
  +        free(comp_unit[n_comp_units].hash[0]);
  +        comp_unit[n_comp_units].hash[0] = NULL;
           hash = comp_unit[n_comp_units-1].hash[0];
       }
       else {
  @@ -98,7 +101,7 @@
                       new->type |= VT_REGP;
                       new->reg = p;
                       /* link in both dirs, so that usage can be determined */
  -                    p->reg = new;
  +                    /* p->reg = new; */
                       debug(DEBUG_LEXER, "found outer scope sym '%s'\n",
                               p->name);
                       return new;
  @@ -158,7 +161,6 @@
       };
       const char *writes[] = {
           "restoreall",
  -        "pushi", "pushn", "pushp", "pushs",
           "popi", "popn", "popp", "pops",
           "cleari", "clearn", "clearp", "clears",
       };
  @@ -217,18 +219,24 @@
   int instruction_reads(Instruction* ins, SymReg* r) {
       int f, i;
       SymReg *key;
  +    SymReg *ri;
   
       f = ins->flags;
  -    for (i = 0; ins->r[i] && i < IMCC_MAX_REGS; i++)
  +    for (i = 0; (ri = ins->r[i]) && i < IMCC_MAX_REGS; i++) {
        if (f & (1<<i)) {
  -            if (ins->r[i] == r)
  +            if (ri == r)
                   return 1;
  -            if ((ins->r[i]->type & VT_REGP) && ins->r[i]->reg == r)
  +            if ((ri->type & VT_REGP) && ri->reg == r)
                   return 1;
  -            for (key = ins->r[i]->nextkey; key; key = key->nextkey)
  +            /* this additional test for _kc ops seems to slow
  +             * down instruction_reads by a huge amount compared to the
  +             * _writes below
  +             */
  +            for (key = ri->nextkey; key; key = key->nextkey)
                   if (key->reg && key->reg == r)
                       return 1;
       }
  +    }
   
       return 0;
   }
  @@ -313,6 +321,7 @@
           ins->next = tmp;
           tmp->prev = ins;
           tmp->next = next;
  +        if (next)
           next->prev = tmp;
           if (!tmp->line)
               tmp->line = ins->line;
  @@ -491,8 +500,8 @@
   }
   
   Emitter emitters[2] = {
  -    {e_file_open, e_file_emit, e_file_close},
  -    {e_pbc_open, e_pbc_emit, e_pbc_close},
  +    {e_file_open, e_file_emit, (int (*)(void *))NULLfunc, e_file_close},
  +    {e_pbc_open, e_pbc_emit, e_pbc_new_sub, e_pbc_close},
   };
   
   static int emitter;
  @@ -501,6 +510,7 @@
   {
       emitter = type;
       has_compile = 0;
  +    dont_optimize = 0;
       return (emitters[emitter]).open(param);
       return 0;
   }
  @@ -526,6 +536,8 @@
           spill_ins = iNEW(interpreter, p31, str_dup("PerlArray"), 0);
           insert_ins(ins, spill_ins);
       }
  +    if (emitters[emitter].new_sub)
  +        (emitters[emitter]).new_sub(param);
       for (ins = instructions; ins; ins = ins->next) {
           (emitters[emitter]).emit(param, ins);
       }
  
  
  
  1.20      +3 -1      parrot/languages/imcc/instructions.h
  
  Index: instructions.h
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/instructions.h,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -w -r1.19 -r1.20
  --- instructions.h    25 Feb 2003 10:25:45 -0000      1.19
  +++ instructions.h    28 Feb 2003 14:21:43 -0000      1.20
  @@ -9,7 +9,8 @@
       ITALIAS = 0x100000, /*   set P,P  */
       ITADDR  = 0x200000, /*   set_addr P, addr*/
       ITSPILL = 0x400000, /*   set P31,x ; set x, p31 spilling */
  -    ITEXT   = 0x800000  /*   instruction is extcall in JIT */
  +    ITEXT   = 0x800000, /*   instruction is extcall in JIT */
  +    ITSAVES = 0x1000000  /*   saveall/restoreall in a bsr */
   };
   
   
  @@ -103,6 +104,7 @@
   typedef struct _emittert {
        int (*open)(void *param);
        int (*emit)(void *param, Instruction *ins);
  +     int (*new_sub)(void *param);
        int (*close)(void *param);
   } Emitter;
   
  
  
  
  1.22      +7 -3      parrot/languages/imcc/optimizer.c
  
  Index: optimizer.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/optimizer.c,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -w -r1.21 -r1.22
  --- optimizer.c       23 Feb 2003 13:17:34 -0000      1.21
  +++ optimizer.c       28 Feb 2003 14:21:43 -0000      1.22
  @@ -70,12 +70,15 @@
           subst_constants_c(interp);
           subst_constants_if(interp);
           strength_reduce(interp);
  +        if (!dont_optimize)
           if_branch(interp);
       }
   }
   
   int cfg_optimize(struct Parrot_Interp *interp) {
       UNUSED(interp);
  +    if (dont_optimize)
  +        return 0;
       if (optimizer_level & OPT_PRE) {
           info(2, "cfg_optimize\n");
           if (branch_branch())
  @@ -1004,7 +1007,7 @@
   is_invariant(Instruction *ins)
   {
       int ok = 0;
  -    int what;
  +    int what = 0;
       if (! strcmp(ins->op, "new") &&
               !strcmp(ins->r[1]->name, "PerlUndef")) {
           ok = 1;
  @@ -1022,6 +1025,7 @@
       return 0;
   }
   
  +#define MOVE_INS_1_BL
   #ifdef MOVE_INS_1_BL
   static Basic_block *
   find_outer(Basic_block * blk)
  @@ -1057,7 +1061,7 @@
           debug(DEBUG_OPT2, "outer loop not found (CFG?)\n");
           return 0;
       }
  -    out = pred->end->prev;
  +    out = pred->end;
       next = (*ins)->next;
       (*ins)->bbindex = pred->index;
       debug(DEBUG_OPT2, "inserting it in blk %d after %s\n", pred->index,
  
  
  
  1.29      +65 -4     parrot/languages/imcc/pbc.c
  
  Index: pbc.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/pbc.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -w -r1.28 -r1.29
  --- pbc.c     21 Feb 2003 12:26:40 -0000      1.28
  +++ pbc.c     28 Feb 2003 14:21:43 -0000      1.29
  @@ -41,6 +41,7 @@
   struct subs {
       size_t size;                        /* code size in ops */
       int ins_line;                       /* line# for debug */
  +    int n_basic_blocks;                 /* block count */
       SymReg * labels[HASH_SIZE];         /* label names */
       SymReg * bsrs[HASH_SIZE];           /* bsr, set_addr locations */
       struct subs *prev;
  @@ -50,6 +51,7 @@
   /* subs are kept per code segment */
   struct cs_t {
       struct PackFile_ByteCode *seg;      /* bytecode seg */
  +    struct PackFile_Segment *jit_info;  /* bblocks, register usage */
       struct subs *subs;                  /* current sub data */
       struct subs *first;                 /* first sub of code seg */
       struct cs_t *prev;                  /* prev cs */
  @@ -114,6 +116,7 @@
       cs->next = NULL;
       cs->subs = NULL;
       cs->first = NULL;
  +    cs->jit_info = NULL;
       if (!globals.first)
           globals.first = cs;
       else
  @@ -123,8 +126,46 @@
       return 0;
   }
   
  +/* get size/line of bytecode in ops till now */
  +static int
  +old_blocks(void)
  +{
  +    size_t size;
  +    struct subs *s;
  +
  +    size = 0;
  +    for (s = globals.cs->subs; s; s = s->prev) {
  +        size += s->n_basic_blocks;
  +    }
  +    return size;
  +}
  +
  +opcode_t *
  +make_jit_info(struct Parrot_Interp *interpreter)
  +{
  +    char *name;
  +    size_t size, old;
  +
  +    if (!globals.cs->jit_info) {
  +        name = malloc(strlen(globals.cs->seg->base.name) + 5);
  +        sprintf(name, "%s_JIT", globals.cs->seg->base.name);
  +        globals.cs->jit_info =
  +            PackFile_Segment_new_seg(interpreter->code, PF_UNKNOWN_SEG, name, 1);
  +        free(name);
  +    }
  +    size = n_basic_blocks + (old = old_blocks());
  +    /* store current size */
  +    globals.cs->subs->n_basic_blocks = n_basic_blocks;
  +    /* offset of block start and end, 4 * registers_used */
  +    globals.cs->jit_info->data = realloc(globals.cs->jit_info->data,
  +            size * sizeof(opcode_t) * 6);
  +    globals.cs->jit_info->size = size * 6;
  +    return globals.cs->jit_info->data + old * 6;
  +}
  +
   /* allocate a new globals.cs->subs structure */
  -static void make_new_sub(void)
  +static void
  +make_new_sub(struct Parrot_Interp *interpreter)
   {
       struct subs *s = mem_sys_allocate_zeroed(sizeof(struct subs));
       if (!s)
  @@ -136,6 +177,9 @@
       if (!globals.cs->first)
           globals.cs->first = s;
       globals.cs->subs = s;
  +    if ((optimizer_level & OPT_J)) {
  +        allocate_jit(interpreter);
  +    }
   }
   
   
  @@ -291,6 +335,8 @@
               /* XXX labels should be mangled with current subroutine name
                * they should only be reachable from eval's in current sub
                */
  +            debug(DEBUG_PBC_FIXUP, "write fixup '%s' offs %d\n",
  +                    ins->r[0]->name, ins->r[0]->color + oldsize);
               PackFile_FixupTable_new_entry_t0(interpreter,
                       ins->r[0]->name, ins->r[0]->color + oldsize);
           }
  @@ -568,6 +614,10 @@
                       *pc++ = PARROT_ARG_S;
                   else
                       fatal(1, "build_key", "wrong register set\n");
  +                /* don't emit mapped regs in key parts */
  +                if (r->color < 0)
  +                    *pc++ = -1 - r->color;
  +                else
                   *pc++ = r->color;
                   sprintf(s+strlen(s), "%c%d", r->set, r->color);
                   debug(DEBUG_PBC_CONST, " keypart reg %s %c%d\n",
  @@ -664,12 +714,24 @@
       }
   }
   
  +int
  +e_pbc_new_sub(void *param)
  +{
  +    struct Parrot_Interp *interpreter = (struct Parrot_Interp *)param;
  +
  +    if (!instructions)
  +        return 0;
  +    make_new_sub(interpreter);     /* we start a new compilation unit */
  +    return 0;
  +}
   
   /*
    * now let the fun begin, actually emit code for one ins
    */
   
  -int e_pbc_emit(void *param, Instruction * ins) {
  +int
  +e_pbc_emit(void *param, Instruction * ins)
  +{
       struct Parrot_Interp *interpreter = (struct Parrot_Interp *)param;
       int ok = 0;
       static opcode_t * pc, npc;
  @@ -684,7 +746,6 @@
           int oldsize;
           int bytes;
   
  -        make_new_sub();         /* we start a new compilation unit */
           oldsize = get_old_size(interpreter, &ins_line);
           code_size = store_labels(interpreter, &ins_size, oldsize);
           debug(DEBUG_PBC, "code_size(ops) %d  oldsize %d\n", code_size, oldsize);
  
  
  
  1.4       +3 -0      parrot/languages/imcc/pbc.h
  
  Index: pbc.h
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/pbc.h,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -w -r1.3 -r1.4
  --- pbc.h     31 Jan 2003 10:54:08 -0000      1.3
  +++ pbc.h     28 Feb 2003 14:21:43 -0000      1.4
  @@ -3,7 +3,10 @@
   
   int e_pbc_open(void *);
   int e_pbc_emit(void *, Instruction * ins);
  +int e_pbc_new_sub(void *);
   int e_pbc_close(void *);
   void fixup_bsrs(struct Parrot_Interp *interpreter);
  +void allocate_jit(struct Parrot_Interp *interpreter);
  +opcode_t * make_jit_info(struct Parrot_Interp *interpreter);
   
   #endif
  
  
  
  1.17      +5 -0      parrot/languages/imcc/symreg.c
  
  Index: symreg.c
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/symreg.c,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -w -r1.16 -r1.17
  --- symreg.c  17 Feb 2003 15:10:52 -0000      1.16
  +++ symreg.c  28 Feb 2003 14:21:43 -0000      1.17
  @@ -345,6 +345,11 @@
        }
           hash[i] = NULL;
       }
  +    for(i = 0; i < HASH_SIZE; i++) {
  +        for(p = ghash[i]; p; p = p->next)
  +            if (p->type & VTADDRESS)
  +                p->first_ins = p->last_ins = NULL;
  +    }
   }
   
   /* utility functions: */
  
  
  
  1.1                  parrot/languages/imcc/jit.c
  
  Index: jit.c
  ===================================================================
  /* imcc JIT optimizer
   *
   * This is a totally experimental hack to demonstrate, that we can
   * ran faster then -O3 compiled C (primes.pasm).
   * But it's incomplete and buggy - albeit it runs all parrot tests.
   *
   * The main problem is the incomplete CFG, mainly WRT subroutines
   * and the effects of saveall/restorall and such.
   * Further too many registers are saved/restored: rebuilding the
   * bb_list is done to get bb->start/end for jit_info, but then
   * life_info maybe out of sync and so all mapped get saved.
   *
   * NOTE: -Oj should always be used with branch/label optimization
   *           as -O1j. It needs a correct CFG, without nul blocks:
   *           e.g. t/op/basic_13.pasm
   *
   */
  #include <string.h>
  #include <assert.h>
  #include "imc.h"
  #include "pbc.h"
  #define JIT_IMCC
  #include "parrot/jit.h"
  #include "parrot/jit_emit.h"
  
  /* PASM registers are already in most used order, so now:
   * - consider the top N registers as processor registers
   * - look at the instruction stream and insert register load/store ins
   *   for e.g. calling out to unJITted functions
   *   This is of course processor dependend
   *
   * NOTE: rx_ ops may have a inout INT parameter for position/mark.
   *       Actually, the either branch or update the inout parameter
   *       so they are save.
   */
  
  #ifndef EXTCALL
  #  define EXTCALL(op) op_jit[*(op)].extcall
  #endif
  
  #ifndef INT_REGISTERS_TO_MAP
  #  define INT_REGISTERS_TO_MAP 0
  #endif
  
  #ifndef FLOAT_REGISTERS_TO_MAP
  #  define FLOAT_REGISTERS_TO_MAP 0
  #endif
  
  #ifndef PRESERVED_INT_REGS
  #  define PRESERVED_INT_REGS MAX_MAPPED
  #endif
  
  #ifndef PRESERVED_FLOAT_REGS
  #  define PRESERVED_FLOAT_REGS MAX_MAPPED
  #endif
  
  /*
   * check life range of all symbols, find the max used mapped
   */
  static int
  max_used(int bbi, char t, int typ, int mapped[])
  {
      int max, j, c;
      for (j = 0, max = 0; j < n_symbols; j++) {
          SymReg * r = reglist[j];
          if (r->set != t)
              continue;
          c = -1 - r->color;
          if (c < mapped[typ]) {
              Life_range *l = r->life_info[bbi];
              if (l->first_ins && c >= max)
                  max = c + 1;
          }
      }
      return max;
  }
  
  /* check life range of all symbols, which have
   * colors >= preserved and are mapped
   * if none found, don't emit load/store for preserved regs
   */
  static int
  min_used(int bbi, char t, int typ, int preserved[], int mapped[])
  {
      int max, j, c;
      for (j = 0, max = mapped[typ]; j < n_symbols; j++) {
          SymReg * r = reglist[j];
          if (r->set != t)
              continue;
          c = -1 - r->color;
          if (c >= preserved[typ] && c < mapped[typ]) {
              Life_range *l = r->life_info[bbi];
              if (l->first_ins && c < max)
                  max = c;
          }
      }
      return max;
  }
  
  void
  allocate_jit(struct Parrot_Interp *interpreter)
  {
      int c, i, j, k, typ;
      int to_map[4] = {0,0,0,0};
  #define MAX_MAPPED 32
      int preserved[] =
      {PRESERVED_INT_REGS, MAX_MAPPED, MAX_MAPPED, PRESERVED_FLOAT_REGS};
      const char *types = "IPSN";
      Instruction * ins, *tmp, *prev, *last;
      SymReg * r;
      SymReg * regs[IMCC_MAX_REGS];
      static SymReg  *cpu[4][MAX_MAPPED];
      static SymReg  *par[4][MAX_MAPPED];
      int reads[4][MAX_MAPPED], writes[4][MAX_MAPPED], nr, nw;
      int maxc[4] = {0,0,0,0};
      Basic_block *bb;
      opcode_t pc;
      static int nsubs;
      opcode_t * jit_info_ptr;
  
      assert(INT_REGISTERS_TO_MAP < MAX_MAPPED);
      assert(FLOAT_REGISTERS_TO_MAP < MAX_MAPPED);
  
      to_map[0] = INT_REGISTERS_TO_MAP;
      to_map[3] = FLOAT_REGISTERS_TO_MAP;
      /* make a list of mapped cpu regs */
      if (cpu[0][0] == NULL) {
          for (typ = 0; typ < 4; typ++)
              for (k = 0; k < to_map[typ]; k++) {
                  char name[16];
                  sprintf(name, "%c%d#c", types[typ], k);
                  cpu[typ][k] = mk_pasm_reg(str_dup(name));
                  cpu[typ][k]->color = -1 - k;
                  sprintf(name, "%c%d#p", types[typ], k);
                  par[typ][k] = mk_pasm_reg(str_dup(name));
              }
      }
      prev = last = NULL;
      nr = nw = 0;
      /* change all mappable registers to mapped ones
       * do nothing, if a compile was encountered
       * TODO not the compile is the problem, but the invoke of
       * compiled code - so track PMCs and invokes too
       */
      if (!has_compile && !dont_optimize) {
          for (j = 0; j < n_symbols; j++) {
              r = reglist[j];
              if (r->set == 'K')
                  continue;
              typ = strchr(types, r->set) - types;
              if (r->color < to_map[typ]) {
                  if (r->color >= maxc[typ])
                      maxc[typ] = r->color + 1;
                  r->color = -1 - r->color;
              }
  
          }
      }
      else {
          maxc[0] = maxc[3] = 0;
      }
      to_map[0] = maxc[0];
      to_map[3] = maxc[3];
      if (!nsubs++) {
          /* clear all used regs at beginning */
          last = instructions->type & ITLABEL ? instructions : NULL;
          for (typ = 0; typ < 4; typ++)
              for (j = 0; j < to_map[typ]; j++) {
                  regs[0] = cpu[typ][j];
                  regs[1] = par[typ][j];
                  tmp = INS(interpreter, "set", "%s, %s\t# init",
                          regs, 2, 0, 0);
                  insert_ins(last, tmp);
              }
      }
      /* now run through basic blocks
       * and insert register save/load instructions where needed
       */
      for (i=0; i < n_basic_blocks; i++) {
          bb = bb_list[i];
          /* TODO: set minimum register usage for this block */
  
          for (ins = bb->start; ins; ins = ins->next) {
              /* clear preserved regs, set rw of non preserved regs */
              for (typ = 0; ins != instructions && typ < 4; typ++)
                  for (k = 0; k < to_map[typ]; k++) {
                      reads[typ][k] = writes[typ][k] =
                          k >= min_used(i, types[typ], typ, preserved, to_map);
                  }
              /* if extern, go through regs and check the usage */
              if (ins->opnum >= 0 && EXTCALL(&ins->opnum)) {
                  nr = nw = 1;
                  /* go through block if extern code, but stop at
                   * basic block boundary
                   */
                  for (last = ins, prev = ins->prev;
                          ins && ins->opnum >= 0 && EXTCALL(&ins->opnum);
                          last = ins, ins = ins->next) {
                      ins->type |= ITEXT;
                      /* check register usage of all instructions
                       * if extern ins reads a reg, we save it to parrot's
                       * if a reg was writen, we reload it after the
                       * extern code block
                       */
                      for (j = 0; j < n_symbols; j++) {
                          r = reglist[j];
                          if (r->set == 'K')
                              continue;
                          if (r->color >= 0)
                              continue;
                          typ = strchr(types, r->set) - types;
                          c = -1 - r->color;
                          if (0 && !strcmp(ins->op, "bsr") &&
                                  (ins->type & ITSAVES)) {
                              int bb_sub =
                                  find_sym(ins->r[0]->name)->first_ins->bbindex;
                              if (max_used(bb_sub, types[typ], typ, to_map))
                                  reads[typ][c] = writes[typ][c] = nr = nw = 1;
                          }
                          if (instruction_reads(ins, r) ||
                                  (/* !(ins->type & ITSAVES) && */
                                   ins_reads2(ins, r->set))) {
                              reads[typ][c] = 1;
                              nr = 1;
                          }
                          if (instruction_writes(ins, r) ||
                                  (/* !(ins->type & ITSAVES) && */
                                   ins_writes2(ins, r->set))) {
                              writes[typ][c] = 1;
                              nw = 1;
                          }
                      }
                      /* changed mapped regs to parrot regs */
                      for (j = 0; (r = ins->r[j]) && j < IMCC_MAX_REGS; j++) {
                          typ = strchr(types, r->set) - types;
                          if ((r->type & VTREGISTER) && r->color < 0)
                              ins->r[j] = par[typ][-1 - r->color];
                      }
                      if (ins == bb->end) {
                          last = ins;
                          if (!strcmp(ins->op, "ret"))
                              last = ins->prev;
                          break;
                      }
                  }
              }
              /* a JITed end opcode, save registers to parrot's */
              else if (!ins->opnum) {
                  for (typ = 0; typ < 4; typ++)
                      for (j = 0; j < to_map[typ]; j++) {
                          reads[typ][j] = 1;
                          nr = 1;
                      }
              }
              /* insert load ins after non JIT block */
              if (nw) {
                  for (typ = 0; typ < 4; typ++)
                      for (j = 0; j < to_map[typ]; j++) {
                          if (!writes[typ][j])
                              continue;
                          regs[0] = cpu[typ][j];
                          regs[1] = par[typ][j];
                          tmp = INS(interpreter, "set", "%s, %s\t# load",
                                  regs, 2, 0, 0);
                          insert_ins(last, tmp);
                      }
                  nw = 0;
              }
              /* insert save ins before extern op */
              if (nr) {
                  for (typ = 0; typ < 4; typ++)
                      for (j = 0; j < to_map[typ]; j++) {
                          if (!reads[typ][j])
                              continue;
                          regs[0] = par[typ][j];
                          regs[1] = cpu[typ][j];
                          tmp = INS(interpreter, "set", "%s, %s\t# save",
                                  regs, 2, 0, 0);
                          insert_ins(prev, tmp);
                      }
                  nr = 0;
              }
              if (ins == bb->end)
                  break;
          }
      }
  
      find_basic_blocks();
      /* allocate a jit_info packfile segment holding
       * some CFG and register usage info
       */
      jit_info_ptr = make_jit_info(interpreter);
      /* write out minimal CFG and register_usage */
      for (i = 0, pc = 0; i < n_basic_blocks; i++) {
          int branch_target = 0;
          bb = bb_list[i];
          ins = bb->start;
          /* mark branch targets with hight bit set */
          if (ins->type & ITLABEL)
              branch_target = 0x80000000;
          *jit_info_ptr++ = (pc | branch_target);
          for ( ; ins; ins = ins->next) {
              pc += ins->opsize;
              if (ins == bb->end)
                  break;
          }
          *jit_info_ptr++ = pc - ins->opsize;
          /* TODO: dont't write block->end
           * put register usage in one op
           */
          for (typ = 0; typ < 4; typ++)
              *jit_info_ptr++ = to_map[typ];
          /*  = max_used(i, types[typ], typ, to_map); */
      }
  }
  
  
  /*
   * Local variables:
   * c-indentation-style: bsd
   * c-basic-offset: 4
   * indent-tabs-mode: nil
   * End:
   *
   * vim: expandtab shiftwidth=4:
  */
  
  
  

Reply via email to