dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] libjit ChangeLog jit/jit-function.c jit/jit-reg...


From: Aleksey Demakov
Subject: [dotgnu-pnet-commits] libjit ChangeLog jit/jit-function.c jit/jit-reg...
Date: Sun, 11 Feb 2007 23:28:44 +0000

CVSROOT:        /sources/dotgnu-pnet
Module name:    libjit
Changes by:     Aleksey Demakov <avd>   07/02/11 23:28:44

Modified files:
        .              : ChangeLog 
        jit            : jit-function.c jit-reg-alloc.h jit-reg-alloc.c 

Log message:
        more correctly handle compilation restart

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.302&r2=1.303
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-function.c?cvsroot=dotgnu-pnet&r1=1.28&r2=1.29
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.h?cvsroot=dotgnu-pnet&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.c?cvsroot=dotgnu-pnet&r1=1.52&r2=1.53

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.302
retrieving revision 1.303
diff -u -b -r1.302 -r1.303
--- ChangeLog   11 Feb 2007 22:54:25 -0000      1.302
+++ ChangeLog   11 Feb 2007 23:28:44 -0000      1.303
@@ -3,6 +3,18 @@
        * jit/jit-dump.c (jit_dump_function): flush the output stream upon
        dumping the function.
 
+       * jit/jit-function.c (cleanup_on_restart, reset_value): add new
+       functions to clean up the compilation state on restart.
+       (compile): replace the code that did cleanup on restart with a call
+       to cleanup_on_restart() which does this job more thoroughly.
+
+       * jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: remove _jit_regs_abort()
+       function as the new cleanup-on-restart code makes it superflows.
+
+       * jit/jit-reg-alloc.c (is_register_occupied): add new function;
+       (clobbers_register, spill_clobbered_register, _jit_regs_gen): fix
+       a problem that shows up with the new cleanup method.
+
 2007-02-10  Klaus Treichel  <address@hidden>
 
        * jit/jit-function.c: Use the on-demand compilation driver in

Index: jit/jit-function.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-function.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -b -r1.28 -r1.29
--- jit/jit-function.c  10 Feb 2007 19:12:29 -0000      1.28
+++ jit/jit-function.c  11 Feb 2007 23:28:44 -0000      1.29
@@ -625,6 +625,85 @@
 }
 
 /*
+ * Reset value on restart.
+ */
+static void
+reset_value(jit_value_t value)
+{
+       value->reg = -1;
+       value->in_register = 0;
+       value->in_global_register = 0;
+       value->in_frame = 0;
+}
+
+/*
+ * Clean up the compilation state on restart.
+ */
+static void
+cleanup_on_restart(jit_gencode_t gen, jit_function_t func)
+{
+       jit_block_t block;
+       jit_insn_iter_t iter;
+       jit_insn_t insn;
+
+#ifdef _JIT_COMPILE_DEBUG
+       printf("\n*** Restart compilation ***\n\n");
+#endif
+
+       block = 0;
+       while((block = jit_block_next(func, block)) != 0)
+       {
+               /* Clear the block addresses and fixup lists */
+               block->address = 0;
+               block->fixup_list = 0;
+               block->fixup_absolute_list = 0;
+
+               /* Reset values referred to by block instructions */
+               jit_insn_iter_init(&iter, block);
+               while((insn = jit_insn_iter_next(&iter)) != 0)
+               {
+                       if(insn->dest && (insn->flags & 
JIT_INSN_DEST_OTHER_FLAGS) == 0)
+                       {
+                               reset_value(insn->dest);
+                       }
+                       if(insn->value1 && (insn->flags & 
JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
+                       {
+                               reset_value(insn->value1);
+                       }
+                       if(insn->value2 && (insn->flags & 
JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
+                       {
+                               reset_value(insn->value2);
+                       }
+               }
+       }
+
+       /* Reset values referred to by builder */
+       if(func->builder->setjmp_value)
+       {
+               reset_value(func->builder->setjmp_value);
+       }
+       if(func->builder->parent_frame)
+       {
+               reset_value(func->builder->parent_frame);
+       }
+
+       /* Reset the "touched" registers mask. The first time compilation
+          might have followed wrong code paths and thus allocated wrong
+          registers. */
+       if(func->builder->has_tail_call)
+       {
+               /* For functions with tail calls _jit_regs_alloc_global()
+                  does not allocate any global registers. The "permanent"
+                  mask has all global registers set to prevent their use. */
+               gen->touched = jit_regused_init;
+       }
+       else
+       {
+               gen->touched = gen->permanent;
+       }
+}
+
+/*
  * Compile a function and return its entry point.
  */
 static int
@@ -764,17 +843,11 @@
                /* End the function's output process */
                result = _jit_cache_end_method(&(gen.posn));
 
-               /* If we need to restart on a different cache page, then clear
-                  the block addresses and fixup lists */
+               /* If we need to restart on a different cache page, then clean 
up
+                  the compilation state  */
                if(result == JIT_CACHE_END_RESTART)
                {
-                       block = 0;
-                       while((block = jit_block_next(func, block)) != 0)
-                       {
-                               block->address = 0;
-                               block->fixup_list = 0;
-                               block->fixup_absolute_list = 0;
-                       }
+                       cleanup_on_restart(&gen, func);
                }
        }
        while(result == JIT_CACHE_END_RESTART);

Index: jit/jit-reg-alloc.h
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- jit/jit-reg-alloc.h 17 Jan 2007 07:38:47 -0000      1.21
+++ jit/jit-reg-alloc.h 11 Feb 2007 23:28:44 -0000      1.22
@@ -175,7 +175,6 @@
 int _jit_regs_select(_jit_regs_t *regs);
 #endif
 void _jit_regs_commit(jit_gencode_t gen, _jit_regs_t *regs);
-void _jit_regs_abort(jit_gencode_t gen, _jit_regs_t *regs);
 
 int _jit_regs_get_dest(_jit_regs_t *regs);
 int _jit_regs_get_value1(_jit_regs_t *regs);

Index: jit/jit-reg-alloc.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -b -r1.52 -r1.53
--- jit/jit-reg-alloc.c 28 Jan 2007 20:14:57 -0000      1.52
+++ jit/jit-reg-alloc.c 11 Feb 2007 23:28:44 -0000      1.53
@@ -88,6 +88,8 @@
 #define CLOBBER_OTHER_REG      4
 
 #ifdef JIT_REG_DEBUG
+#include <stdlib.h>
+
 static void dump_regs(jit_gencode_t gen, const char *name)
 {
        int reg, index;
@@ -208,6 +210,9 @@
        return 0;
 }
 
+/*
+ * Exchange the content of two value descriptors.
+ */
 static void
 swap_values(_jit_regdesc_t *desc1, _jit_regdesc_t *desc2)
 {
@@ -367,6 +372,44 @@
 }
 
 /*
+ * Check if the register contains any values either dead or alive
+ * that may need to be evicted from it.
+ */
+static int
+is_register_occupied(jit_gencode_t gen, _jit_regs_t *regs, int reg)
+{
+       if(reg < 0)
+       {
+               return 0;
+       }
+
+       /* Assume that a global register is always alive unless it is to be
+          computed right away. */
+       if(jit_reg_is_used(gen->permanent, reg))
+       {
+               if(!regs->ternary
+                  && regs->descs[0].value
+                  && regs->descs[0].value->has_global_register
+                  && regs->descs[0].value->global_reg == reg)
+               {
+                       return 0;
+               }
+               return 1;
+       }
+
+       if(gen->contents[reg].is_long_end)
+       {
+               reg = get_long_pair_start(reg);
+       }
+       if(gen->contents[reg].num_values)
+       {
+               return 1;
+       }
+
+       return 0;
+}
+
+/*
  * Determine the effect of using a register for a value. This includes the
  * following:
  *  - whether the value is clobbered by the instruction;
@@ -439,11 +482,11 @@
                }
 
                flags = CLOBBER_NONE;
-               if(is_register_alive(gen, regs, reg))
+               if(is_register_occupied(gen, regs, reg))
                {
                        flags |= CLOBBER_REG;
                }
-               if(is_register_alive(gen, regs, other_reg))
+               if(is_register_occupied(gen, regs, other_reg))
                {
                        flags |= CLOBBER_OTHER_REG;
                }
@@ -492,11 +535,11 @@
                }
        }
 
-       if(is_register_alive(gen, regs, reg))
+       if(is_register_occupied(gen, regs, reg))
        {
                flags |= CLOBBER_REG;
        }
-       if(is_register_alive(gen, regs, other_reg))
+       if(is_register_occupied(gen, regs, other_reg))
        {
                flags |= CLOBBER_OTHER_REG;
        }
@@ -1729,6 +1772,14 @@
                still_in_frame = 0;
        }
 
+#ifdef JIT_REG_DEBUG
+       if(gen->contents[reg].num_values == JIT_MAX_REG_VALUES)
+       {
+               printf("*** Too many values for one register! ***\n");
+               abort();
+       }
+#endif
+
        gen->contents[reg].values[gen->contents[reg].num_values] = value;
        ++(gen->contents[reg].num_values);
        gen->contents[reg].age = gen->current_age;
@@ -2073,6 +2124,77 @@
        printf("spill_clobbered_register(reg = %d)\n", reg);
 #endif
 
+#ifdef JIT_REG_STACK
+       /* For a stack register spill it in two passes. First drop values that
+          reqiure neither spilling nor a generation of the free instruction.
+          Then lazily exchange the register with the top and spill or free it
+          as necessary. This approach might save a exch/free instructions in
+          certain cases. */
+       if(IS_STACK_REG(reg))
+       {
+               for(index = gen->contents[reg].num_values - 1; index >= 0; 
--index)
+               {
+                       if(gen->contents[reg].num_values == 1)
+                       {
+                               break;
+                       }
+
+                       value = gen->contents[reg].values[index];
+                       usage = value_usage(regs, value);
+                       if((usage & VALUE_INPUT) != 0)
+                       {
+                               continue;
+                       }
+                       if((usage & VALUE_DEAD) != 0 || value->in_frame)
+                       {
+                               unbind_value(gen, value, reg, -1);
+                       }
+               }
+               for(index = gen->contents[reg].num_values - 1; index >= 0; 
--index)
+               {
+                       int top;
+
+                       value = gen->contents[reg].values[index];
+                       usage = value_usage(regs, value);
+                       if((usage & VALUE_INPUT) != 0)
+                       {
+                               if((usage & VALUE_DEAD) != 0 || value->in_frame)
+                               {
+                                       continue;
+                               }
+
+                               top = gen->reg_stack_top - 1;
+                               if(reg != top)
+                               {
+                                       exch_stack_top(gen, reg, 0);
+                                       reg = top;
+                               }
+
+                               save_value(gen, value, reg, -1, 0);
+                       }
+                       else
+                       {
+                               top = gen->reg_stack_top - 1;
+                               if(reg != top)
+                               {
+                                       exch_stack_top(gen, reg, 0);
+                                       reg = top;
+                               }
+
+                               if((usage & VALUE_DEAD) != 0 || value->in_frame)
+                               {
+                                       free_value(gen, value, reg, -1, 0);
+                               }
+                               else
+                               {
+                                       save_value(gen, value, reg, -1, 1);
+                               }
+                       }
+               }
+       }
+       else
+#endif
+       {
        /* Find the other register in a long pair */
        if(gen->contents[reg].is_long_start)
        {
@@ -2088,24 +2210,6 @@
                other_reg = -1;
        }
 
-       /* Spill register contents in two passes. First free values that
-          do not reqiure spilling then spill those that do. This approach
-          is only useful in case a stack register contains both kinds of
-          values and the last value is one that does not require spilling.
-          This way we may save one free instruction. */
-       if(IS_STACK_REG(reg))
-       {
-               for(index = gen->contents[reg].num_values - 1; index >= 0; 
--index)
-               {
-                       value = gen->contents[reg].values[index];
-                       usage = value_usage(regs, value);
-                       if((usage & VALUE_INPUT) == 0
-                          && ((usage & VALUE_DEAD) != 0 || value->in_frame))
-                       {
-                               free_value(gen, value, reg, other_reg, 0);
-                       }
-               }
-       }
        for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
        {
                value = gen->contents[reg].values[index];
@@ -2129,6 +2233,7 @@
                        }
                }
        }
+       }
 }
 
 static void
@@ -2352,43 +2457,6 @@
 }
 #endif
 
-static void
-abort_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
-{
-       _jit_regdesc_t *desc;
-       int reg, other_reg;
-
-#ifdef JIT_REG_DEBUG
-       printf("abort_input_value(%d)\n", index);
-#endif
-
-       desc = &regs->descs[index];
-       if(!desc->value || desc->duplicate)
-       {
-               return;
-       }
-
-       if(desc->load && desc->value->in_register)
-       {
-               reg = desc->value->reg;
-               if(gen->contents[reg].is_long_start)
-               {
-                       other_reg = OTHER_REG(reg);
-               }
-               else
-               {
-                       other_reg = -1;
-               }
-               unbind_value(gen, desc->value, reg, other_reg);
-#ifdef JIT_REG_STACK
-               if(IS_STACK_REG(reg))
-               {
-                       --(gen->reg_stack_top);
-               }
-#endif
-       }
-}
-
 #ifdef JIT_REG_STACK
 static void
 pop_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
@@ -3437,28 +3505,20 @@
                if(IS_STACK_REG(reg))
                {
                        int top = gen->reg_stack_top - 1;
-
                        /* spill top registers if there are any that needs to 
be */
-                       for(; top > reg && jit_reg_is_used(regs->clobber, top); 
top--)
+                       for(; top >= reg && jit_reg_is_used(regs->clobber, 
top); top--)
                        {
                                spill_clobbered_register(gen, regs, top);
                                /* If an input value is on the top then it 
stays there
-                                  and the top does not change. */
+                                  and the top position does not change. */
                                if(gen->contents[top].num_values > 0)
                                {
                                        break;
                                }
                        }
-                       /* If the top register was not spilled then exchange it 
with
-                          the current register. */
                        if(top > reg)
                        {
-                               exch_stack_top(gen, reg, 0);
-                       }
-                       /* Finally spill the register */
-                       if(top >= JIT_REG_STACK_START)
-                       {
-                               spill_clobbered_register(gen, regs, top);
+                               spill_clobbered_register(gen, regs, reg);
                        }
                }
                else
@@ -3694,17 +3754,6 @@
 #endif
 }
 
-void
-_jit_regs_abort(jit_gencode_t gen, _jit_regs_t *regs)
-{
-       abort_input_value(gen, regs, 2);
-       abort_input_value(gen, regs, 1);
-       if(regs->ternary)
-       {
-               abort_input_value(gen, regs, 0);
-       }
-}
-
 unsigned char *
 _jit_regs_inst_ptr(jit_gencode_t gen, int space)
 {
@@ -3723,8 +3772,6 @@
 unsigned char *
 _jit_regs_begin(jit_gencode_t gen, _jit_regs_t *regs, int space)
 {
-       unsigned char *inst;
-
        if(!_jit_regs_assign(gen, regs))
        {
                return 0;
@@ -3734,13 +3781,7 @@
                return 0;
        }
 
-       inst = _jit_regs_inst_ptr(gen, space);
-       if(!inst)
-       {
-               _jit_regs_abort(gen, regs);
-       }
-
-       return inst;
+       return _jit_regs_inst_ptr(gen, space);
 }
 
 void




reply via email to

[Prev in Thread] Current Thread [Next in Thread]