Author: leo
Date: Thu Feb  9 09:10:27 2006
New Revision: 11487

Modified:
   trunk/src/pic_jit.c
Log:
PIC/JIT - verfiy, if sub is JITtable 3

* add sanity checks
  - check if all opcodes are JITtable
  - verify, that if the sub calls a sub, it's recursive
  - verify that all JITtable opcode only are I or N regs
* remove explicit test for the sub name __pic_test  



Modified: trunk/src/pic_jit.c
==============================================================================
--- trunk/src/pic_jit.c (original)
+++ trunk/src/pic_jit.c Thu Feb  9 09:10:27 2006
@@ -137,6 +137,136 @@ args_match_params(Interp *interpreter, P
     return 0;
 }
 
+static int
+returns_match_results(Interp *interpreter, PMC *sig_ret, PMC *sig_result)
+{
+    int n, type;
+    
+    n = parrot_pic_check_sig(interpreter, sig_ret, sig_result, &type);
+    if (n == -1 && !SIG_ELEMS(sig_ret)) {
+        /* XXX we currently have a spurious set_returns after a
+         * tail_call -O1 would get rid of that dead block but is 
+         * broken currently - work around ignore empty set_returns
+         */
+        return 1;
+    }
+    if (n == -1) {
+        /* arg count mismatch */
+        return 0;
+    }
+    if (!n) {
+        /* no args - this would be save, if the JIT code could already
+         * deal with no args
+         * TODO
+         */
+        return 0;
+    }
+    type &= ~PARROT_ARG_CONSTANT;
+    switch (type) {
+        case PARROT_ARG_INTVAL:
+        case PARROT_ARG_FLOATVAL:
+            return 1;
+    }
+    return 0;
+}
+
+static int
+call_is_safe(Interp *interpreter, PMC *sub, opcode_t **set_args)
+{
+    opcode_t *pc;
+    PMC *sig_args, *called, *sig_results;
+    int i;
+
+    pc = *set_args;
+    sig_args = PMC_sub(sub)->seg->const_table->constants[pc[1]]->u.key;
+    /* ignore the signature for now */
+    pc += 2 + SIG_ELEMS(sig_args);
+    if (*pc != PARROT_OP_set_p_pc)
+       return 0; 
+    called = PMC_sub(sub)->seg->const_table->constants[pc[2]]->u.key;
+    if (called != sub) {
+        /* we can JIT just recursive subs for now */
+        return 0;
+    }
+    pc += 3;
+    if (*pc != PARROT_OP_get_results_pc)
+        return 0;
+    sig_results = PMC_sub(sub)->seg->const_table->constants[pc[1]]->u.key;
+    pc += 2 + SIG_ELEMS(sig_results);
+    if (*pc != PARROT_OP_invokecc_p)
+        return 0;
+    pc += 2;
+    *set_args = pc;
+    return 1;
+}
+
+static int
+ops_jittable(Interp *interpreter, PMC *sub, PMC *sig_results, 
+        struct PackFile_ByteCode *seg,
+        opcode_t *pc, opcode_t *end)
+{
+    op_info_t *op_info;
+    int i, n, op;
+    PMC *sig_ret;
+
+    while (pc < end) {
+        op = *pc;
+        /*
+         * some special opcodes, which are handled, but not marked
+         * as JITtable
+         */
+        op_info = interpreter->op_info_table + op;
+        n = op_info->op_count;
+
+        switch (op) {
+            case PARROT_OP_returncc:
+            case PARROT_OP_get_params_pc:
+                goto op_is_ok;
+                break;
+            case PARROT_OP_set_returns_pc:
+                sig_ret = seg->const_table->constants[pc[1]]->u.key;
+                if (!returns_match_results(interpreter, sig_ret, sig_results))
+                    return 0;
+                goto op_is_ok;
+                break;
+            case PARROT_OP_set_args_pc:
+                /* verify call, return address after the call */
+                if (!call_is_safe(interpreter, sub, &pc))
+                    return 0;
+                continue;
+            default:
+                if (op_jit[op].extcall != 0) {
+                    /* non-jitted or JITted vtable */
+                    return 0;
+                }
+                break;
+        }
+        /*
+         * there are some JITted opcodes like set_s_s, which we can't
+         * handle (yet)
+         */
+        for (i = 1; i < n; i++) {
+            opcode_t arg = pc[i];
+            int type;
+
+            type = op_info->types[i - 1];
+            switch (type) {
+                case PARROT_ARG_I:
+                case PARROT_ARG_N:
+                case PARROT_ARG_IC:
+                case PARROT_ARG_NC:
+                    break;
+                default:
+                    return 0;
+            }
+        }
+op_is_ok:
+        ADD_OP_VAR_PART(interpreter, seg, pc, n);
+        pc += n;
+    }
+    return 1;
+}
+
 int
 parrot_pic_is_save_to_jit(Interp *interpreter, PMC *sub,
        PMC *sig_args, PMC *sig_results)
@@ -171,9 +301,14 @@ parrot_pic_is_save_to_jit(Interp *interp
     if (!args_match_params(interpreter, sig_args, PMC_sub(sub)->seg, start))
         return 0;
 
-    /* XXX test code */
-    if (memcmp((char*) name->strstart, "__pic_test", 10) != 0)
-       return 0;
+    /*
+     * 3) verify if all opcodes are JITtable, also check set_returns
+     *   if it's reached
+     */
+    if (!ops_jittable(interpreter, sub, sig_results, 
+                PMC_sub(sub)->seg, start, end))
+        return 0;
+
     return 1;
 }
 

Reply via email to