hello people,
I've implemented some print opcodes in JIT (for i386), but I would
like to know your opinion about these before submitting a patch.
in reality, there isn't a big performance boost, because I'm just
calling printf as the C opcode does. it just saves some
push/pop/call/ret instructions. the advantage is that such hack is
portable across platform. implementing a more low-level print
mechanism (involving system calls probably) would require several
#ifdef..#endif, I suppose.
anyway, this implements a new function in jit_emit.h which makes
a call to a C function (an absolute address, that is). this is the
function I've added to jit_emit.h:
void emit_call_abs(Parrot_jit_info *jit_info,
long absaddr, int putback)
{
Parrot_jit_newfixup(jit_info);
jit_info->fixups->type = JIT_X86CALL;
jit_info->fixups->param.fptr = (void (*)(void)) absaddr;
emitm_calll(jit_info->native_ptr, 0xdeafc0de);
emitm_addl_i_r(jit_info->native_ptr, putback, emit_ESP);
}
this is very similar to Parrot_jit_normal_op, except that the
address is stored 'as it is' and the bytes to be added to ESP are
variable.
and this is how print_ic is implemented in core.jit:
Parrot_print_ic {
emitm_pushl_i(NATIVECODE, *INT_CONST[1]);
emitm_pushl_i(NATIVECODE, (long) INTVAL_FMT);
emit_call_abs(jit_info, (long) printf, 8);
}
print_nc looks like this (I needed to define a private long because
simply saying (&NUM_CONST[1])+4 doesn't work):
Parrot_print_nc {
long mydouble = (long) &NUM_CONST[1];
NATIVECODE = emit_pushl_m(NATIVECODE, emit_None, emit_None,
emit_None, mydouble+4);
NATIVECODE = emit_pushl_m(NATIVECODE, emit_None, emit_None,
emit_None, mydouble);
emitm_pushl_i(NATIVECODE, (long) FLOATVAL_FMT);
emit_call_abs(jit_info, (long) printf, 12);
}
also print_sc is similar, except that there isn't a STRINGVAL_FMT
defined in config.h:
Parrot_print_sc {
NATIVECODE = emit_pushl_m(NATIVECODE, emit_None, emit_None,
emit_None, (long) &STRING_CONST[1]->bufstart);
emitm_pushl_i(NATIVECODE, (long) "%s");
emit_call_abs(jit_info, (long) printf, 8);
}
another little thing I've done, but I'm not sure if there's need
for this, is having added these lines to jit.c in the build_asm
routine, just before returning:
if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) {
fprintf(stderr, "*** Parrot VM: JITted code at 0x%08x. ***\n",
jit_info.arena_start);
}
this way when I start 'parrot -j -d something' it tells me where
to find the JIT, and I can goto there directly in the debugger.
it's really a time saver for me.
cheers,
Aldo
__END__
$_=q,just perl,,s, , another ,,s,$, hacker,,print;