Author: leo
Date: Wed Feb  8 05:06:52 2006
New Revision: 11472

Modified:
   trunk/src/jit.c
   trunk/src/jit/i386/core.jit
   trunk/src/jit/i386/jit_emit.h
   trunk/src/pic.c
Log:
PIC/JIT - x86: heureka - running ack.pir

* add codegen for calling a recursive function incl arg passing and
  fetching the result

$ time ./parrot -Oc -C ack.pir 11         real    0m0.567s
$ time ./ack 11       (C -O3)             real    0m0.980s

See also mail on p6i for more details.


Modified: trunk/src/jit.c
==============================================================================
--- trunk/src/jit.c     (original)
+++ trunk/src/jit.c     Wed Feb  8 05:06:52 2006
@@ -192,11 +192,15 @@ make_branch_list(Interp *interpreter,
         /* if op_info->jump is not 0 this opcode may jump,
          * so mark this opcode as a branch source */
         rel_offset = cur_op - code_start;
-        if (op_info->jump)
-            branch[rel_offset] |= JIT_BRANCH_SOURCE;
 
         n = op_info->op_count;
 
+        if (op == PARROT_OP_set_args_pc ||
+                op == PARROT_OP_set_returns_pc ||
+                op == PARROT_OP_get_results_pc)
+            goto no_branch;    
+        if (op_info->jump)
+            branch[rel_offset] |= JIT_BRANCH_SOURCE;
         for (i = 1; i < n; ++i) {
             /* If it's not a constant, no joy */
             if (op_info->types[i-1] == PARROT_ARG_IC && op_info->labels[i-1]) {
@@ -241,6 +245,7 @@ make_branch_list(Interp *interpreter,
              */
             optimizer->has_unpredictable_jump = 1;
         }
+no_branch:
         /* Move to the next opcode */
         ADD_OP_VAR_PART(interpreter, interpreter->code, cur_op, n);
         cur_op += n;
@@ -1410,6 +1415,8 @@ parrot_build_asm(Interp *interpreter, 
     if (jit_type == JIT_CODE_SUB_REGS_ONLY) {
         op_func[PARROT_OP_set_returns_pc].extcall = 0;
         op_func[PARROT_OP_get_params_pc].extcall = 0;
+        op_func[PARROT_OP_get_params_pc].extcall = 0;
+        op_func[PARROT_OP_invokecc_p].extcall = 0;
     }
     /* get register mappings and such */
     arch_info = jit_info->arch_info = Parrot_jit_init(interpreter);
@@ -1609,6 +1616,34 @@ parrot_build_asm(Interp *interpreter, 
             jit_info->op_i += n;
             jit_info->cur_op += n;
 
+            if (*jit_info->prev_op == PARROT_OP_set_args_pc &&
+                    jit_type == JIT_CODE_SUB_REGS_ONLY) {
+                assert(*cur_op == PARROT_OP_set_p_pc);
+                cur_op += 3;    /* skip it */
+                jit_info->op_i += 3;
+                jit_info->cur_op += 3;
+                jit_info->arena.op_map[jit_info->op_i].offset =
+                    jit_info->native_ptr - jit_info->arena.start;
+                assert(*cur_op == PARROT_OP_get_results_pc);
+                /* now emit the call - use special op for this */
+                (op_func[PARROT_OP_pic_callr___pc].fn)(jit_info, interpreter);
+                /* and the get_results */
+                (op_func[*cur_op].fn)(jit_info, interpreter);
+                op_info = &interpreter->op_info_table[*cur_op];
+                n = op_info->op_count;
+                ADD_OP_VAR_PART(interpreter, interpreter->code, cur_op, n);
+                cur_op += n;
+                /* update op_i and cur_op accordingly */
+                jit_info->op_i += n;
+                jit_info->cur_op += n;
+                jit_info->arena.op_map[jit_info->op_i].offset =
+                    jit_info->native_ptr - jit_info->arena.start;
+                /* now at invoke */
+                assert(*cur_op == PARROT_OP_invokecc_p);
+                cur_op += 2;    /* skip it */
+                jit_info->op_i += 2;
+                jit_info->cur_op += 2;
+            }
             /* if this is a branch target, align it */
 #ifdef jit_emit_noop
 #  if JUMP_ALIGN
@@ -1629,7 +1664,6 @@ parrot_build_asm(Interp *interpreter, 
         /* Save mapped registers back to the Parrot registers */
         if (!jit_seg && cur_section->isjit && needs_fs)
             Parrot_jit_save_registers(jit_info, interpreter, 0);
-
         /* update the offset for saved registers */
         jit_info->arena.op_map[jit_info->op_i].offset =
             jit_info->native_ptr - jit_info->arena.start;

Modified: trunk/src/jit/i386/core.jit
==============================================================================
--- trunk/src/jit/i386/core.jit (original)
+++ trunk/src/jit/i386/core.jit Wed Feb  8 05:06:52 2006
@@ -1426,9 +1426,15 @@ Parrot_ord_i_sc_i {
 ; which adds unneeded overhead - convert to normal ops
 ; or just JIT the 2 easy ones
 Parrot_set_args_pc {
-    Parrot_jit_emit_get_INTERP(jit_info->native_ptr, emit_EAX);
-    emitm_movl_i_m(NATIVECODE, jit_info->cur_op, emit_EAX, emit_None, 1,
-            offsetof(Interp, current_args));
+    if (jit_info->code_type == JIT_CODE_FILE) {
+        Parrot_jit_emit_get_INTERP(jit_info->native_ptr, emit_EAX);
+        emitm_movl_i_m(NATIVECODE, jit_info->cur_op, emit_EAX, emit_None, 1,
+                offsetof(Interp, current_args));
+    }
+    else  {
+        jit_set_args_pc(jit_info, interpreter, 
+            jit_info->flags & JIT_CODE_RECURSIVE);
+    }
 }
 
 extern Parrot_set_returns_pc {
@@ -1446,7 +1452,7 @@ extern Parrot_returncc {
     else {
         /* restore pushed regs if any */
         if (!(jit_info->flags & JIT_CODE_RECURSIVE)) {
-            jit_restore_regs(jit_info, interpreter);
+            jit_restore_regs(jit_info, interpreter, -1);
             emitm_movl_m_r(NATIVECODE, emit_EAX, emit_EBP, emit_None, 1, 16);
             /* retval = pc is at 4 + n_args * 4 */
             emitm_movl_m_r(NATIVECODE, emit_EAX, emit_EAX, emit_None, 1, 
@@ -1457,6 +1463,35 @@ extern Parrot_returncc {
     }
 }
 
+Parrot_pic_callr___pc {
+    int offset, here, op_i;
+    struct PackFile_Constant ** constants;
+    PMC *sig_params, *sig_result;
+    opcode_t *params;
+    int skip;
+
+    constants = CONTEXT(interpreter->ctx)->constants;
+    params = jit_info->optimizer->sections->begin;
+    sig_params = constants[params[1]]->u.key;
+    op_i = 2 + PMC_int_val(sig_params);
+
+    offset = jit_info->arena.op_map[op_i].offset;
+    /* TODO preserve necessary regs */
+    assert(*CUR_OPCODE == PARROT_OP_get_results_pc);
+    constants = CONTEXT(interpreter->ctx)->constants;
+    sig_result = constants[CUR_OPCODE[1]]->u.key;
+    if (!PMC_int_val(sig_result))
+        skip = -1;
+    else 
+        skip = MAP(2);      /* skip result - save rest */
+    jit_save_regs(jit_info, interpreter, skip);
+
+    here = NATIVECODE - jit_info->arena.start;
+    emitm_calll(NATIVECODE, offset - here - 5);
+
+    jit_restore_regs(jit_info, interpreter, skip);
+}
+
 extern Parrot_get_params_pc {
     if (jit_info->code_type == JIT_CODE_FILE)
         Parrot_jit_normal_op(jit_info, interpreter);
@@ -1466,11 +1501,24 @@ extern Parrot_get_params_pc {
 }
 
 Parrot_get_results_pc {
-    Parrot_jit_emit_get_INTERP(jit_info->native_ptr, emit_EAX);
-    emitm_movl_m_r(NATIVECODE, emit_EAX, emit_EAX, emit_None, 1,
-            offsetof(Interp, ctx.state));
-    emitm_movl_i_m(NATIVECODE, jit_info->cur_op, emit_EAX, emit_None, 1,
-            offsetof(parrot_context_t, current_results));
+    if (jit_info->code_type == JIT_CODE_FILE) {
+        Parrot_jit_emit_get_INTERP(jit_info->native_ptr, emit_EAX);
+        emitm_movl_m_r(NATIVECODE, emit_EAX, emit_EAX, emit_None, 1,
+                offsetof(Interp, ctx.state));
+        emitm_movl_i_m(NATIVECODE, jit_info->cur_op, emit_EAX, emit_None, 1,
+                offsetof(parrot_context_t, current_results));
+    }
+    else {
+        struct PackFile_Constant ** constants;
+        PMC *sig_result;
+
+        constants = CONTEXT(interpreter->ctx)->constants;
+        sig_result = constants[CUR_OPCODE[1]]->u.key;
+        if (!PMC_int_val(sig_result))
+            return;
+        /* result is eax TODO Nums */
+        jit_emit_mov_rr_i(NATIVECODE, MAP(2), emit_EAX);
+    }
 }
 ; TODO or,and,not,cmp
 

Modified: trunk/src/jit/i386/jit_emit.h
==============================================================================
--- trunk/src/jit/i386/jit_emit.h       (original)
+++ trunk/src/jit/i386/jit_emit.h       Wed Feb  8 05:06:52 2006
@@ -2783,8 +2783,31 @@ jit_get_params_pc(Parrot_jit_info_t *jit
                 1, 4 + i*4);
 }
 
+/*
+ * preserve registers
+ * a) all callee saved on function entry (skip == -1)
+ * b) all used register around a call (skip >= 0 := return result
+ *    TODO save N regs for b) too
+ */
+static void 
+jit_save_regs(Parrot_jit_info_t *jit_info, Interp * interpreter, int skip)
+{
+    int i, used_i, save_i;
+    const jit_arch_regs *reg_info;
+
+    used_i = CONTEXT(interpreter->ctx)->n_regs_used[REGNO_INT];
+    reg_info = &jit_info->arch_info->regs[jit_info->code_type]; 
+    save_i = skip >= 0 ? 0 : reg_info->n_preserved_I;
+    for (i = save_i; i < used_i; ++i) {
+        if (reg_info->map_I[i] == skip)
+            continue;
+        emitm_pushl_r(jit_info->native_ptr, reg_info->map_I[i]);
+    }
+}
+
+/* restore saved regs, see above */
 static void 
-jit_restore_regs(Parrot_jit_info_t *jit_info, Interp * interpreter)
+jit_restore_regs(Parrot_jit_info_t *jit_info, Interp * interpreter, int skip)
 {
 
     int i, used_i, save_i;
@@ -2792,10 +2815,13 @@ jit_restore_regs(Parrot_jit_info_t *jit_
 
     used_i = CONTEXT(interpreter->ctx)->n_regs_used[REGNO_INT];
     reg_info = &jit_info->arch_info->regs[jit_info->code_type]; 
-    save_i = reg_info->n_preserved_I;
-    /* note - reversed order of Parrot_jit_begin_sub_regs */
-    for (i = used_i - 1; i >= save_i; --i)
+    save_i = skip >= 0 ? 0 : reg_info->n_preserved_I;
+    /* note - reversed order of jit_save_regs  */
+    for (i = used_i - 1; i >= save_i; --i) {
+        if (reg_info->map_I[i] == skip)
+            continue;
         emitm_popl_r(jit_info->native_ptr, reg_info->map_I[i]);
+    }
 }
 
 static void
@@ -2806,6 +2832,8 @@ jit_set_returns_pc(Parrot_jit_info_t *ji
     INTVAL *sig_bits, sig;
 
     sig_pmc = CONTEXT(interpreter->ctx)->constants[CUR_OPCODE[1]]->u.key;
+    if (!PMC_int_val(sig_pmc))
+        return;
     sig_bits = PMC_data(sig_pmc);
     sig = sig_bits[0];
     if (!recursive) {
@@ -2833,10 +2861,55 @@ jit_set_returns_pc(Parrot_jit_info_t *ji
             }
             break;
         default:
-            internal_exception(1, "set_returns_jit - unknown tyep");
+            internal_exception(1, "set_returns_jit - unknown typ");
             break;
     }
 }
+
+static void
+jit_set_args_pc(Parrot_jit_info_t *jit_info, Interp * interpreter, 
+        int recursive)
+{
+    PMC *sig_args, *sig_params;
+    INTVAL *sig_bits, sig, i, n;
+    struct PackFile_Constant ** constants;
+    opcode_t *params;
+    char params_map;
+
+    if (!recursive) {
+        /* create args array */
+        internal_exception(1, "set_args_jit - can't do that yet ");
+    }
+
+    constants = CONTEXT(interpreter->ctx)->constants;
+    sig_args = constants[CUR_OPCODE[1]]->u.key;
+    if (!PMC_int_val(sig_args))
+        return;
+    params = jit_info->optimizer->sections->begin;
+    sig_params = constants[params[1]]->u.key;
+    assert(PObj_is_PMC_TEST(sig_params));
+    assert(sig_params->vtable->base_type == enum_class_FixedIntegerArray);
+    sig_bits = PMC_data(sig_args);
+    n = PMC_int_val(sig_args);  
+    for (i = 0; i < n; ++i) {
+        sig = sig_bits[i];
+        /* move args to params regs */
+        params_map = jit_info->optimizer->map_branch[2 + i];
+        /* TODO check for overlaps/collision */
+        switch (sig & (PARROT_ARG_TYPE_MASK|PARROT_ARG_CONSTANT)) {
+            case PARROT_ARG_INTVAL:
+                jit_emit_mov_rr_i(NATIVECODE, params_map, MAP(2 + i));
+                break;
+            case PARROT_ARG_INTVAL|PARROT_ARG_CONSTANT:
+                jit_emit_mov_ri_i(NATIVECODE, params_map, CUR_OPCODE[2 + i]);
+                break;
+            default:
+                internal_exception(1, "set_args_jit - unknown typ");
+                break;
+        }
+    }
+}
+
 #if JIT_EMIT == 0
 
 static void
@@ -3023,9 +3096,6 @@ static void
 Parrot_jit_begin_sub_regs(Parrot_jit_info_t *jit_info,
                  Interp * interpreter)
 {
-    int i, used_i, save_i;
-    const jit_arch_regs *reg_info;
-    
     jit_emit_stack_frame_enter(jit_info->native_ptr);
     /* stack:
      *  16   args
@@ -3040,11 +3110,7 @@ Parrot_jit_begin_sub_regs(Parrot_jit_inf
      * check register usage of the subroutine
      * how many we have to preserve
      */ 
-    used_i = CONTEXT(interpreter->ctx)->n_regs_used[REGNO_INT];
-    reg_info = &jit_info->arch_info->regs[jit_info->code_type]; 
-    save_i = reg_info->n_preserved_I;
-    for (i = save_i; i < used_i; ++i)
-        emitm_pushl_r(jit_info->native_ptr, reg_info->map_I[i]);
+    jit_save_regs(jit_info, interpreter, -1);
     /* when it's a recursive sub, we fetch params to registers
      * and all a inner helper sub, which run with registers only
      */
@@ -3064,7 +3130,7 @@ Parrot_jit_begin_sub_regs(Parrot_jit_inf
         emitm_movl_m_r(NATIVECODE, emit_EAX, emit_EDX, emit_None, 1, 
                     4 + jit_info->n_args * 4);
         /* restore pushed callee saved */
-        jit_restore_regs(jit_info, interpreter);
+        jit_restore_regs(jit_info, interpreter, -1);
         jit_emit_stack_frame_leave(NATIVECODE);
         emitm_ret(NATIVECODE);
         /* fixup call statement */

Modified: trunk/src/pic.c
==============================================================================
--- trunk/src/pic.c     (original)
+++ trunk/src/pic.c     Wed Feb  8 05:06:52 2006
@@ -592,7 +592,7 @@ is_pic_func(Interp *interpreter, void **
         /* TODO pass Sub */
 
         jit_info = parrot_build_asm(interpreter, start, end, NULL,
-            JIT_CODE_SUB_REGS_ONLY);
+            JIT_CODE_SUB_REGS_ONLY_REC);
         if (!jit_info)
             return 0;
         

Reply via email to