to be located without explicit marking.
+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,
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.
*/
*/
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
/*
* 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);
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;
}
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;
(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
#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)
@*/
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 */
}
/*@