2 Copyright (C) 2006-2007, The Perl Foundation.
7 src/pic_jit.c - Polymorphic Inline Cache to JIT compilation
11 Some statically known and simple subroutines are replaced by
12 their JITted variants, if
14 - JIT is supported and can JIT subroutines
15 - arguments passing is simple
16 - the code is fully JITtable
17 - and more such checks
21 - save jit_info in sub
22 - check for multiple calls to the same sub
23 either reuse code or create new
24 - handle void calls/returns
34 #include "parrot/parrot.h"
35 #include "parrot/oplib/ops.h"
37 /* HEADERIZER HFILE: include/parrot/pic.h */
39 /* HEADERIZER BEGIN: static */
41 PARROT_WARN_UNUSED_RESULT
42 static int args_match_params(
43 ARGIN(const PMC
*sig_args
),
44 ARGIN(const PackFile_ByteCode
*seg
),
45 ARGIN(const opcode_t
*start
))
46 __attribute__nonnull__(1)
47 __attribute__nonnull__(2)
48 __attribute__nonnull__(3);
50 PARROT_WARN_UNUSED_RESULT
51 static int call_is_safe(ARGIN(const PMC
*sub
), ARGMOD(opcode_t
**set_args
))
52 __attribute__nonnull__(1)
53 __attribute__nonnull__(2)
54 FUNC_MODIFIES(*set_args
);
56 PARROT_WARN_UNUSED_RESULT
57 static int jit_can_compile_sub(PARROT_INTERP
, ARGIN(const PMC
*sub
))
58 __attribute__nonnull__(1)
59 __attribute__nonnull__(2);
61 PARROT_WARN_UNUSED_RESULT
62 static int ops_jittable(PARROT_INTERP
,
63 ARGIN(const PMC
*sub
),
64 ARGIN(const PMC
*sig_results
),
65 ARGIN(const PackFile_ByteCode
*seg
),
67 ARGIN(const opcode_t
*end
),
69 __attribute__nonnull__(1)
70 __attribute__nonnull__(2)
71 __attribute__nonnull__(3)
72 __attribute__nonnull__(4)
73 __attribute__nonnull__(5)
74 __attribute__nonnull__(6)
75 __attribute__nonnull__(7)
76 FUNC_MODIFIES(*flags
);
78 PARROT_WARN_UNUSED_RESULT
79 PARROT_CAN_RETURN_NULL
80 static opcode_t
* pic_test_func(PARROT_INTERP
,
81 SHIM(INTVAL
*sig_bits
),
83 __attribute__nonnull__(1)
84 __attribute__nonnull__(3)
87 PARROT_WARN_UNUSED_RESULT
88 static int returns_match_results(
89 ARGIN(const PMC
*sig_ret
),
90 ARGIN(const PMC
*sig_result
))
91 __attribute__nonnull__(1)
92 __attribute__nonnull__(2);
94 /* HEADERIZER END: static */
97 #ifdef HAVE_COMPUTED_GOTO
98 # include "parrot/oplib/core_ops_cgp.h"
102 # include "parrot/exec.h"
107 * just for testing the whole scheme ...
113 i = __pic_test(i, 10)
123 ... prints 42, if PIC_TEST is 1, because the C function is called
124 with -C and -S runcores.
129 =item C<static opcode_t * pic_test_func>
131 RT#48260: Not yet documented!!!
137 PARROT_WARN_UNUSED_RESULT
138 PARROT_CAN_RETURN_NULL
140 pic_test_func(PARROT_INTERP
, SHIM(INTVAL
*sig_bits
), ARGOUT(void **args
))
142 INTVAL
* const result
= (INTVAL
*) args
[0];
143 INTVAL
const i
= (INTVAL
) args
[1];
144 INTVAL
const j
= (INTVAL
) args
[2];
154 =item C<static int jit_can_compile_sub>
156 RT#48260: Not yet documented!!!
162 PARROT_WARN_UNUSED_RESULT
164 jit_can_compile_sub(PARROT_INTERP
, ARGIN(const PMC
*sub
))
166 const jit_arch_info
* const info
= Parrot_jit_init(interp
);
167 const jit_arch_regs
* const regs
= info
->regs
+ JIT_CODE_SUB_REGS_ONLY
;
168 INTVAL
* const n_regs_used
= PMC_sub(sub
)->n_regs_used
;
170 /* if the sub is using more regs than the arch has
171 * we don't JIT it at all
173 if (n_regs_used
[REGNO_INT
] > regs
->n_mapped_I
)
176 if (n_regs_used
[REGNO_NUM
] > regs
->n_mapped_F
)
179 /* if the Sub is using S regs, we can't JIT it yet */
180 if (n_regs_used
[REGNO_STR
])
183 /* if the Sub is using more than 1 P reg, we can't JIT it yet
184 * the P reg could be a (recursive) call to a sub
186 if (n_regs_used
[REGNO_PMC
] > 1)
195 =item C<static int args_match_params>
197 RT#48260: Not yet documented!!!
203 PARROT_WARN_UNUSED_RESULT
205 args_match_params(ARGIN(const PMC
*sig_args
), ARGIN(const PackFile_ByteCode
*seg
),
206 ARGIN(const opcode_t
*start
))
208 const PMC
*sig_params
;
211 if (*start
!= PARROT_OP_get_params_pc
)
214 sig_params
= seg
->const_table
->constants
[start
[1]]->u
.key
;
216 /* verify that we actually can pass arguments */
217 ASSERT_SIG_PMC(sig_params
);
219 n
= parrot_pic_check_sig(sig_args
, sig_params
, &type
);
221 /* arg count mismatch */
225 /* no args - this would be safe, if the JIT code could already
232 switch (type
& ~PARROT_ARG_CONSTANT
) {
233 case PARROT_ARG_INTVAL
:
234 case PARROT_ARG_FLOATVAL
:
243 =item C<static int returns_match_results>
245 RT#48260: Not yet documented!!!
251 PARROT_WARN_UNUSED_RESULT
253 returns_match_results(ARGIN(const PMC
*sig_ret
), ARGIN(const PMC
*sig_result
))
256 const int n
= parrot_pic_check_sig(sig_ret
, sig_result
, &type
);
258 /* arg count mismatch */
262 /* no args - this would be safe, if the JIT code could already
269 switch (type
& ~PARROT_ARG_CONSTANT
) {
270 case PARROT_ARG_INTVAL
:
271 case PARROT_ARG_FLOATVAL
:
280 =item C<static int call_is_safe>
282 RT#48260: Not yet documented!!!
288 PARROT_WARN_UNUSED_RESULT
290 call_is_safe(ARGIN(const PMC
*sub
), ARGMOD(opcode_t
**set_args
))
292 PMC
*called
, *sig_results
;
294 opcode_t
* pc
= *set_args
;
295 PMC
* const sig_args
=
296 PMC_sub(sub
)->seg
->const_table
->constants
[pc
[1]]->u
.key
;
298 /* ignore the signature for now */
299 pc
+= 2 + SIG_ELEMS(sig_args
);
301 if (*pc
!= PARROT_OP_set_p_pc
)
304 called
= PMC_sub(sub
)->seg
->const_table
->constants
[pc
[2]]->u
.key
;
306 /* we can JIT just recursive subs for now */
312 if (*pc
!= PARROT_OP_get_results_pc
)
315 sig_results
= PMC_sub(sub
)->seg
->const_table
->constants
[pc
[1]]->u
.key
;
316 pc
+= 2 + SIG_ELEMS(sig_results
);
318 if (*pc
!= PARROT_OP_invokecc_p
)
329 =item C<static int ops_jittable>
331 RT#48260: Not yet documented!!!
337 PARROT_WARN_UNUSED_RESULT
339 ops_jittable(PARROT_INTERP
, ARGIN(const PMC
*sub
), ARGIN(const PMC
*sig_results
),
340 ARGIN(const PackFile_ByteCode
*seg
), ARGIN(opcode_t
*pc
),
341 ARGIN(const opcode_t
*end
), ARGOUT(int *flags
))
344 /* special opcodes which are handled, but not marked as JITtable */
348 const op_info_t
* const op_info
= interp
->op_info_table
+ op
;
349 int n
= op_info
->op_count
;
352 case PARROT_OP_returncc
:
353 case PARROT_OP_get_params_pc
:
356 case PARROT_OP_set_returns_pc
:
358 const PMC
* const sig_ret
= seg
->const_table
->constants
[pc
[1]]->u
.key
;
359 if (!returns_match_results(sig_ret
, sig_results
))
364 case PARROT_OP_set_args_pc
:
365 /* verify call, return address after the call */
366 if (!call_is_safe(sub
, &pc
))
368 *flags
|= JIT_CODE_RECURSIVE
;
371 /* non-jitted or JITted vtable */
372 if (op_jit
[op
].extcall
!= 0)
377 * there are some JITted opcodes like set_s_s, which we can't
380 for (i
= 1; i
< n
; i
++) {
381 const int type
= op_info
->types
[i
- 1];
393 ADD_OP_VAR_PART(interp
, seg
, pc
, n
);
404 =item C<int parrot_pic_is_safe_to_jit>
406 RT#48260: Not yet documented!!!
412 PARROT_WARN_UNUSED_RESULT
414 parrot_pic_is_safe_to_jit(PARROT_INTERP
, ARGIN(const PMC
*sub
), ARGIN(const PMC
*sig_args
),
415 ARGIN(const PMC
*sig_results
), ARGOUT(int *flags
))
418 opcode_t
*base
, *start
, *end
;
423 * 0) if runcore setting doesn't contain JIT
426 if (!(interp
->run_core
& PARROT_JIT_CORE
))
429 /* 1) if the JIT system can't JIT_CODE_SUB_REGS_ONLY
430 * or the sub is using too many registers
432 if (!jit_can_compile_sub(interp
, sub
))
436 * 2) check if get_params is matching set_args
439 base
= PMC_sub(sub
)->seg
->base
.data
;
440 start
= base
+ PMC_sub(sub
)->start_offs
;
441 end
= base
+ PMC_sub(sub
)->end_offs
;
443 if (!args_match_params(sig_args
, PMC_sub(sub
)->seg
, start
))
447 * 3) verify if all opcodes are JITtable, also check set_returns
450 if (!ops_jittable(interp
, sub
, sig_results
,
451 PMC_sub(sub
)->seg
, start
, end
, flags
))
468 =item C<funcptr_t parrot_pic_JIT_sub>
470 RT#48260: Not yet documented!!!
477 parrot_pic_JIT_sub(PARROT_INTERP
, ARGIN(const PMC
*sub
), int flags
)
483 return (funcptr_t
) pic_test_func
;
486 * create JIT code - just a test
488 opcode_t
* const base
= PMC_sub(sub
)->seg
->base
.data
;
489 opcode_t
* const start
= base
+ PMC_sub(sub
)->start_offs
;
490 opcode_t
* const end
= base
+ PMC_sub(sub
)->end_offs
;
493 Parrot_jit_info_t
* jit_info
= parrot_build_asm(interp
,
494 start
, end
, NULL
, JIT_CODE_SUB_REGS_ONLY
| flags
);
499 return (funcptr_t
) jit_info
->arena
.start
;
521 F<src/pic.c>, F<src/jit.c>, F<ops/core_ops_cgp.c>,
522 F<include/parrot/pic.h>, F<ops/pic.ops>
530 * c-file-style: "parrot"
532 * vim: expandtab shiftwidth=4: