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;