]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Add "_jit_cache_get_end_method", to allow the end of a method's code
authorRhys Weatherley <rweather@southern-storm.com.au>
Sat, 8 May 2004 00:42:18 +0000 (00:42 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Sat, 8 May 2004 00:42:18 +0000 (00:42 +0000)
to be located without explicit marking.

ChangeLog
jit/jit-cache.c
jit/jit-cache.h
jit/jit-dump.c
jit/jit-interp.h
jit/jit-rules-interp.c

index 91968f30a37c9cdedf675293a097745efe77f80e..20a02ff97f0584d9b700d998f23e142fc7eddb2f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,10 @@
 
+2004-05-08  Rhys Weatherley  <rweather@southern-storm.com.au>
+
+       * jit/jit-cache.c, jit/jit-cache.h, jit/jit-dump.c, jit/jit-interp.h,
+       jit/jit-rules-interp.c: add "_jit_cache_get_end_method", to allow
+       the end of a method's code to be located without explicit marking.
+
 2004-05-07  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * dpas/dpas-function.c, dpas/dpas-internal.h, dpas/dpas-main.c,
index e27debca54aeb70557ba4bc11b2b150c7e104f56..251ccaa083137109a29db6bc810f56f8c5c3945d 100644 (file)
@@ -976,6 +976,149 @@ void *_jit_cache_get_method(jit_cache_t cache, void *pc, void **cookie)
        return 0;
 }
 
+/*
+ * Add a parent pointer to a list.  Returns null if out of memory.
+ */
+static int add_parent(jit_cache_method_t *parent_buf,
+                                         jit_cache_method_t **parents,
+                                         int *num_parents, int *max_parents,
+                                         jit_cache_method_t node)
+{
+       jit_cache_method_t *new_list;
+       if(*num_parents >= *max_parents)
+       {
+               if(*parents == parent_buf)
+               {
+                       new_list = (jit_cache_method_t *)jit_malloc
+                               ((*max_parents * 2) * sizeof(jit_cache_method_t));
+                       if(new_list)
+                       {
+                               jit_memcpy(new_list, *parents,
+                                                  (*num_parents) * sizeof(jit_cache_method_t));
+                       }
+               }
+               else
+               {
+                       new_list = (jit_cache_method_t *)jit_realloc
+                               (*parents, (*max_parents * 2) * sizeof(jit_cache_method_t));
+               }
+               if(!new_list)
+               {
+                       return 0;
+               }
+               *parents = new_list;
+               *max_parents *= 2;
+       }
+       (*parents)[*num_parents] = node;
+       ++(*num_parents);
+       return 1;
+}
+
+void *_jit_cache_get_end_method(jit_cache_t cache, void *pc)
+{
+       jit_cache_method_t parent_buf[16];
+       jit_cache_method_t *parents = parent_buf;
+       int num_parents = 0;
+       int max_parents = 16;
+       jit_cache_method_t node = cache->head.right;
+       jit_cache_method_t last;
+       jit_cache_method_t parent;
+       void *method;
+       while(node != &(cache->nil))
+       {
+               if(((unsigned char *)pc) < node->start)
+               {
+                       if(!add_parent(parent_buf, &parents, &num_parents,
+                          &max_parents, node))
+                       {
+                               break;
+                       }
+                       node = GetLeft(node);
+               }
+               else if(((unsigned char *)pc) >= node->end)
+               {
+                       if(!add_parent(parent_buf, &parents, &num_parents,
+                          &max_parents, node))
+                       {
+                               break;
+                       }
+                       node = GetRight(node);
+               }
+               else
+               {
+                       /* This is the node that contains the starting position.
+                          We now need to do an inorder traversal from this point
+                          to find the last node that mentions this method */
+                       method = node->method;
+                       last = node;
+                       do
+                       {
+                               if(GetRight(node) != &(cache->nil))
+                               {
+                                       /* Move down the left-most sub-tree of the right */
+                                       if(!add_parent(parent_buf, &parents, &num_parents,
+                                          &max_parents, node))
+                                       {
+                                               goto failed;
+                                       }
+                                       node = GetRight(node);
+                                       while(GetLeft(node) != &(cache->nil))
+                                       {
+                                               if(!add_parent(parent_buf, &parents, &num_parents,
+                                                  &max_parents, node))
+                                               {
+                                                       goto failed;
+                                               }
+                                               node = GetLeft(node);
+                                       }
+                               }
+                               else
+                               {
+                                       /* Find a parent or other ancestor that contains this
+                                          node within its left sub-tree */
+                                       for(;;)
+                                       {
+                                               if(num_parents == 0)
+                                               {
+                                                       node = 0;
+                                                       break;
+                                               }
+                                               parent = parents[--num_parents];
+                                               if(GetLeft(parent) == node)
+                                               {
+                                                       /* We are on our parent's left, so next is parent */
+                                                       node = parent;
+                                                       break;
+                                               }
+                                               node = parent;
+                                       }
+                                       if(!node)
+                                       {
+                                               /* We reached the root of the tree */
+                                               break;
+                                       }
+                               }
+                               if(node->method == method)
+                               {
+                                       last = node;
+                               }
+                       }
+                       while(node->method == method);
+                       if(parents != parent_buf)
+                       {
+                               jit_free(parents);
+                       }
+                       return last->end;
+               }
+       }
+failed:
+       if(parents != parent_buf)
+       {
+               jit_free(parents);
+       }
+       return 0;
+}
+
 /*
  * Count the number of methods in a sub-tree.
  */
index 03b339b513ecc29d893a0cab188cf4435895e2de..25cf30568c376ebf4073ae5fd952e1e984a7e6d8 100644 (file)
@@ -129,6 +129,12 @@ void _jit_cache_set_cookie(jit_cache_posn *posn, void *cookie);
  */
 void *_jit_cache_get_method(jit_cache_t cache, void *pc, void **cookie);
 
+/*
+ * Get the end of a method with a particular starting PC.
+ * Returns NULL if the PC could not be located.
+ */
+void *_jit_cache_get_end_method(jit_cache_t cache, void *pc);
+
 /*
  * Get a list of all method that are presently in the cache.
  * The list is terminated by a NULL, and must be free'd with
index 914e9b8d1816d2654c6bf45b03ab37954ea9b8db..85cad4c7f3834b0af4d37cba5f8b885587b2d1bf 100644 (file)
@@ -496,18 +496,14 @@ extern jit_opcode_info_t const _jit_interp_opcodes[JIT_OP_NUM_INTERP_OPCODES];
 /*
  * Dump the interpreted bytecode representation of a function.
  */
-static void dump_interp_code(FILE *stream, void **pc)
+static void dump_interp_code(FILE *stream, void **pc, void **end)
 {
        int opcode;
        const jit_opcode_info_t *info;
-       for(;;)
+       while(pc < end)
        {
                /* Fetch the next opcode */
                opcode = (int)(jit_nint)(*pc);
-               if(opcode == JIT_OP_END_MARKER)
-               {
-                       break;
-               }
 
                /* Dump the address of the opcode */
                fprintf(stream, "\t%08lX: ", (long)(jit_nint)pc);
@@ -546,31 +542,50 @@ static void dump_interp_code(FILE *stream, void **pc)
 
                        case JIT_OPCODE_CONST_LONG:
                        {
-                               /* TODO */
+                               jit_ulong value;
+                               jit_memcpy(&value, pc, sizeof(jit_ulong));
+                               pc += (sizeof(jit_ulong) + sizeof(void *) - 1) &
+                                         ~(sizeof(void *) - 1);
+                               fprintf(stream, " 0x%lX%08lX",
+                                               (long)((value >> 32) & jit_max_uint),
+                                               (long)(value & jit_max_uint));
                        }
                        break;
 
                        case JIT_OPCODE_CONST_FLOAT32:
                        {
-                               /* TODO */
+                               jit_float32 value;
+                               jit_memcpy(&value, pc, sizeof(jit_float32));
+                               pc += (sizeof(jit_float32) + sizeof(void *) - 1) &
+                                         ~(sizeof(void *) - 1);
+                               fprintf(stream, " %g", (double)value);
                        }
                        break;
 
                        case JIT_OPCODE_CONST_FLOAT64:
                        {
-                               /* TODO */
+                               jit_float64 value;
+                               jit_memcpy(&value, pc, sizeof(jit_float64));
+                               pc += (sizeof(jit_float64) + sizeof(void *) - 1) &
+                                         ~(sizeof(void *) - 1);
+                               fprintf(stream, " %g", (double)value);
                        }
                        break;
 
                        case JIT_OPCODE_CONST_NFLOAT:
                        {
-                               /* TODO */
+                               jit_nfloat value;
+                               jit_memcpy(&value, pc, sizeof(jit_nfloat));
+                               pc += (sizeof(jit_nfloat) + sizeof(void *) - 1) &
+                                         ~(sizeof(void *) - 1);
+                               fprintf(stream, " %g", (double)value);
                        }
                        break;
 
                        case JIT_OPCODE_CALL_INDIRECT_ARGS:
                        {
-                               /* TODO */
+                               fprintf(stream, " %ld", (long)(jit_nint)(pc[1]));
+                               pc += 2;
                        }
                        break;
 
@@ -738,6 +753,8 @@ void jit_dump_function(FILE *stream, jit_function_t func, const char *name)
        }
        else if(func->is_compiled)
        {
+               void *end = _jit_cache_get_end_method
+                       (func->context->cache, func->entry_point);
 #if defined(JIT_BACKEND_INTERP)
                /* Dump the interpreter's bytecode representation */
                jit_function_interp_t interp;
@@ -746,7 +763,7 @@ void jit_dump_function(FILE *stream, jit_function_t func, const char *name)
                                (long)(jit_nint)interp, (long)(jit_nint)func,
                                (int)(interp->args_size), (int)(interp->frame_size),
                                (int)(interp->working_area));
-               dump_interp_code(stream, (void **)(interp + 1));
+               dump_interp_code(stream, (void **)(interp + 1), (void **)end);
 #else
                /* TODO: use objdump to dump native code */
 #endif
index dc401349e135f80e606dc6c77acb08700abc980e..7a1250625b4a5825e93c086c9a1f2b22f374938e 100644 (file)
@@ -189,7 +189,7 @@ public:
 #define        JIT_OP_CALL_FINALLY                                     (JIT_OP_NUM_OPCODES + 0x0038)
 
 /*
- * Marker opcode for the end of a function.
+ * Marker opcode for the end of the interpreter-specific opcodes.
  */
 #define        JIT_OP_END_MARKER                                       (JIT_OP_NUM_OPCODES + 0x0039)
 
index 2d80cb59ad65c77aa8124f20f29dd441a46ed62c..7479933fa393e32a8d3ceb24521a4f8292313d59 100644 (file)
@@ -621,7 +621,7 @@ void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf)
 @*/
 void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
 {
-       jit_cache_opcode(&(gen->posn), JIT_OP_END_MARKER);
+       /* The interpreter doesn't use epilogs */
 }
 
 /*@