2 Copyright (C) 2004-2009, Parrot Foundation.
7 src/pic.c - Polymorphic Inline Cache
11 The PIC supports inline caching for MMD and object method lookups in
12 prederefed run cores. Additionally opcodes that do some kind of lookup
13 like C<new_p_sc> are changed to faster variants.
15 For non-prederefed run-cores there's a less efficient variant which
18 * the bytecode segment has an index per cached opcode (code->pic_index)
19 * this index points into pic_store
20 * TODO use the cache in opcodes
22 =head1 OPERATION SCHEME
27 +--------------+---------------+----+----+-----------------+----------+
28 | infix_ic_p_p | .MMD_SUBTRACT | P5 | P6 | callmethodcc_sc | "method" |
29 +--------------+---------------+----+----+-----------------+----------+
31 In init_prederef the opcodes are replaced with prederef__, operands
32 are replaced with their addresses (&) in the const table or offsets
33 (+) in the register frame:
36 +--------------+---------------+----+----+-----------------+----------+
37 | prederef__ | .MMD_SUBTRACT | +P5| +P6| prederef__ |&"method" |
38 +--------------+---------------+----+----+-----------------+----------+
40 we have code->pic_index with an index into pic_store - the pic_index is
41 half the size of the bytecode and addressed with pc_offset/2:
48 During predereferencing the opcode gets rewritten to the PIC variant,
49 the constant infix operation number is replaced with a pointer to the MIC
50 in the pic_store at the index pic_index:
53 +--------------------+-----+----+----+-----------------------+-----+
54 | pic_infix___ic_p_p | MIC1|+P5 |+P6 | pic_callmethodcc___sc | MIC2|
55 +--------------------+-----+----+----+-----------------------+-----+
57 This can be further optimized due to static inlining:
60 +--------------------+-----+----+----+-----------------------+-----+
61 | pic_inline_sub_p_p | MIC1|+P5 |+P6 | pic_callmethodcc___sc | MIC2|
62 +--------------------+-----+----+----+-----------------------+-----+
64 The opcode is an opcode number for the switched core or the actual code address
65 for the direct-threaded CGP core. With a little help of the JIT system we could
66 also dynamicall create inlined code.
68 Runcores with r/o (mmapped) bytecode can't be rewritten in this way, the
69 lookup of the cache has to be done in the opcode itself.
79 #include "parrot/parrot.h"
80 #include "parrot/oplib/ops.h"
81 #include "parrot/runcore_api.h"
82 #include "pmc/pmc_fixedintegerarray.h"
83 #include "pmc/pmc_continuation.h"
84 #ifdef HAVE_COMPUTED_GOTO
85 # include "parrot/oplib/core_ops_cgp.h"
89 # include "parrot/exec.h"
93 /* needs a Makefile dependency */
94 /* #include "pmc/pmc_integer.h" */
96 /* XXX Define this in a header file */
97 extern void Parrot_Integer_i_subtract_Integer(Interp
* , PMC
* pmc
, PMC
* value
);
100 * hack to turn on inlining - just sub_p_p for mops done
103 #define ENABLE_INLINING 0
105 /* HEADERIZER HFILE: include/parrot/pic.h */
107 /* HEADERIZER BEGIN: static */
108 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
110 static int is_pic_func(PARROT_INTERP
,
112 ARGOUT(Parrot_MIC
*mic
),
113 ARGIN(Parrot_runcore_t
*runcore
))
114 __attribute__nonnull__(1)
115 __attribute__nonnull__(2)
116 __attribute__nonnull__(3)
117 __attribute__nonnull__(4)
120 static int is_pic_param(PARROT_INTERP
,
122 ARGOUT(Parrot_MIC
*mic
),
124 __attribute__nonnull__(1)
125 __attribute__nonnull__(2)
126 __attribute__nonnull__(3)
129 static int pass_int(PARROT_INTERP
,
131 ARGIN(const char *src_base
),
132 ARGIN(const void **src
),
133 ARGOUT(char *dest_base
),
134 ARGIN(void * const *dest
))
135 __attribute__nonnull__(1)
136 __attribute__nonnull__(2)
137 __attribute__nonnull__(3)
138 __attribute__nonnull__(4)
139 __attribute__nonnull__(5)
140 __attribute__nonnull__(6)
141 FUNC_MODIFIES(*dest_base
);
143 static int pass_mixed(PARROT_INTERP
,
145 ARGIN(const char *src_base
),
146 ARGIN(void * const *src
),
147 ARGOUT(char *dest_base
),
148 ARGIN(void * const *dest
))
149 __attribute__nonnull__(1)
150 __attribute__nonnull__(2)
151 __attribute__nonnull__(3)
152 __attribute__nonnull__(4)
153 __attribute__nonnull__(5)
154 __attribute__nonnull__(6)
155 FUNC_MODIFIES(*dest_base
);
157 static int pass_num(PARROT_INTERP
,
159 ARGIN(const char *src_base
),
160 ARGIN(const void **src
),
161 ARGOUT(char *dest_base
),
162 ARGIN(void * const *dest
))
163 __attribute__nonnull__(1)
164 __attribute__nonnull__(2)
165 __attribute__nonnull__(3)
166 __attribute__nonnull__(4)
167 __attribute__nonnull__(5)
168 __attribute__nonnull__(6)
169 FUNC_MODIFIES(*dest_base
);
171 static int pass_pmc(PARROT_INTERP
,
173 ARGIN(const char *src_base
),
174 ARGIN(const void **src
),
175 ARGOUT(char *dest_base
),
176 ARGIN(void * const *dest
))
177 __attribute__nonnull__(1)
178 __attribute__nonnull__(2)
179 __attribute__nonnull__(3)
180 __attribute__nonnull__(4)
181 __attribute__nonnull__(5)
182 __attribute__nonnull__(6)
183 FUNC_MODIFIES(*dest_base
);
185 static int pass_str(PARROT_INTERP
,
187 ARGIN(const char *src_base
),
188 ARGIN(const void **src
),
189 ARGOUT(char *dest_base
),
190 ARGIN(void * const *dest
))
191 __attribute__nonnull__(1)
192 __attribute__nonnull__(2)
193 __attribute__nonnull__(3)
194 __attribute__nonnull__(4)
195 __attribute__nonnull__(5)
196 __attribute__nonnull__(6)
197 FUNC_MODIFIES(*dest_base
);
199 #define ASSERT_ARGS_is_pic_func __attribute__unused__ int _ASSERT_ARGS_CHECK = \
200 PARROT_ASSERT_ARG(interp) \
201 || PARROT_ASSERT_ARG(pc) \
202 || PARROT_ASSERT_ARG(mic) \
203 || PARROT_ASSERT_ARG(runcore)
204 #define ASSERT_ARGS_is_pic_param __attribute__unused__ int _ASSERT_ARGS_CHECK = \
205 PARROT_ASSERT_ARG(interp) \
206 || PARROT_ASSERT_ARG(pc) \
207 || PARROT_ASSERT_ARG(mic)
208 #define ASSERT_ARGS_pass_int __attribute__unused__ int _ASSERT_ARGS_CHECK = \
209 PARROT_ASSERT_ARG(interp) \
210 || PARROT_ASSERT_ARG(sig) \
211 || PARROT_ASSERT_ARG(src_base) \
212 || PARROT_ASSERT_ARG(src) \
213 || PARROT_ASSERT_ARG(dest_base) \
214 || PARROT_ASSERT_ARG(dest)
215 #define ASSERT_ARGS_pass_mixed __attribute__unused__ int _ASSERT_ARGS_CHECK = \
216 PARROT_ASSERT_ARG(interp) \
217 || PARROT_ASSERT_ARG(sig) \
218 || PARROT_ASSERT_ARG(src_base) \
219 || PARROT_ASSERT_ARG(src) \
220 || PARROT_ASSERT_ARG(dest_base) \
221 || PARROT_ASSERT_ARG(dest)
222 #define ASSERT_ARGS_pass_num __attribute__unused__ int _ASSERT_ARGS_CHECK = \
223 PARROT_ASSERT_ARG(interp) \
224 || PARROT_ASSERT_ARG(sig) \
225 || PARROT_ASSERT_ARG(src_base) \
226 || PARROT_ASSERT_ARG(src) \
227 || PARROT_ASSERT_ARG(dest_base) \
228 || PARROT_ASSERT_ARG(dest)
229 #define ASSERT_ARGS_pass_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = \
230 PARROT_ASSERT_ARG(interp) \
231 || PARROT_ASSERT_ARG(sig) \
232 || PARROT_ASSERT_ARG(src_base) \
233 || PARROT_ASSERT_ARG(src) \
234 || PARROT_ASSERT_ARG(dest_base) \
235 || PARROT_ASSERT_ARG(dest)
236 #define ASSERT_ARGS_pass_str __attribute__unused__ int _ASSERT_ARGS_CHECK = \
237 PARROT_ASSERT_ARG(interp) \
238 || PARROT_ASSERT_ARG(sig) \
239 || PARROT_ASSERT_ARG(src_base) \
240 || PARROT_ASSERT_ARG(src) \
241 || PARROT_ASSERT_ARG(dest_base) \
242 || PARROT_ASSERT_ARG(dest)
243 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
244 /* HEADERIZER END: static */
249 =item C<void parrot_PIC_alloc_store(PackFile_ByteCode *cs, size_t n)>
251 Initialize the PIC storage for the given code segment with the capacitiy of
252 holding at least C<n> MIC entries. The PIC_store itself, room for C<n> MICs and
253 some space for PICs is allocated as one piece. MICs are returned from the start
254 of usable memory, PICs from the rear.
261 parrot_PIC_alloc_store(ARGOUT(PackFile_ByteCode
*cs
), size_t n
)
263 ASSERT_ARGS(parrot_PIC_alloc_store
)
264 Parrot_PIC_store
*store
;
268 * estimated 95% of calls are monomorphic, 5% are polymorphic
271 #define POLYMORPHIC 0.05
272 size_t poly
= (size_t)(n
* POLYMORPHIC
) * sizeof (Parrot_PIC
);
275 poly
= 2 * sizeof (Parrot_PIC
);
277 size
= n
* sizeof (Parrot_MIC
) + poly
+ sizeof (Parrot_PIC_store
);
279 store
= (Parrot_PIC_store
*)mem_sys_allocate_zeroed(size
);
281 cs
->pic_store
= store
;
282 store
->pic
= (Parrot_PIC
*)((char *)store
+ size
);
283 store
->usable
= poly
;
284 store
->mic
= (Parrot_MIC
*)((char*)store
+ sizeof (Parrot_PIC_store
));
290 =item C<void parrot_PIC_destroy(PackFile_ByteCode *cs)>
292 Free memory for the PIC storage.
299 parrot_PIC_destroy(ARGMOD(PackFile_ByteCode
*cs
))
301 ASSERT_ARGS(parrot_PIC_destroy
)
302 Parrot_PIC_store
*store
= cs
->pic_store
;
305 Parrot_PIC_store
* const prev
= store
->prev
;
310 cs
->pic_store
= NULL
;
315 =item C<int parrot_PIC_op_is_cached(int op_code)>
317 Return true, if the opcode needs a PIC slot.
323 PARROT_CONST_FUNCTION
325 parrot_PIC_op_is_cached(int op_code
)
327 ASSERT_ARGS(parrot_PIC_op_is_cached
)
329 case PARROT_OP_get_params_pc
:
330 case PARROT_OP_set_returns_pc
:
331 case PARROT_OP_set_args_pc
:
340 =item C<Parrot_MIC* parrot_PIC_alloc_mic(const PARROT_INTERP, size_t n)>
342 Allocate a new MIC structure for the C<n>th cached opcode in this
349 PARROT_WARN_UNUSED_RESULT
350 PARROT_CANNOT_RETURN_NULL
352 parrot_PIC_alloc_mic(const PARROT_INTERP
, size_t n
)
354 ASSERT_ARGS(parrot_PIC_alloc_mic
)
355 Parrot_PIC_store
* const store
= interp
->code
->pic_store
;
356 PARROT_ASSERT(n
< store
->n_mics
);
357 return store
->mic
+ n
;
362 =item C<Parrot_PIC* parrot_PIC_alloc_pic(PARROT_INTERP)>
364 Allocate a new PIC structure for the C<n>th cached opcode in this
371 PARROT_WARN_UNUSED_RESULT
372 PARROT_CANNOT_RETURN_NULL
374 parrot_PIC_alloc_pic(PARROT_INTERP
)
376 ASSERT_ARGS(parrot_PIC_alloc_pic
)
377 Parrot_PIC_store
*store
= interp
->code
->pic_store
;
378 Parrot_PIC_store
*new_store
;
380 if (store
->usable
< sizeof (Parrot_PIC
)) {
382 (size_t)(store
->n_mics
* POLYMORPHIC
) * sizeof (Parrot_PIC
);
385 size
= 2 * sizeof (Parrot_PIC
);
387 new_store
= (Parrot_PIC_store
*)
388 mem_sys_allocate_zeroed(size
+ sizeof (Parrot_PIC_store
));
389 new_store
->prev
= store
;
390 interp
->code
->pic_store
= new_store
;
392 new_store
->pic
= (Parrot_PIC
*)((char *)new_store
+ size
393 + sizeof (Parrot_PIC_store
));
394 new_store
->usable
= size
;
396 /* the addon store has only poly-morphic slots
397 * point the monomorphic to the old store */
398 new_store
->mic
= store
->mic
;
399 new_store
->n_mics
= store
->n_mics
;
402 store
->usable
-= sizeof (Parrot_PIC
);
408 =item C<void * parrot_pic_opcode(PARROT_INTERP, INTVAL op)>
414 PARROT_WARN_UNUSED_RESULT
415 PARROT_CAN_RETURN_NULL
417 parrot_pic_opcode(PARROT_INTERP
, INTVAL op
)
419 ASSERT_ARGS(parrot_pic_opcode
)
420 #ifdef HAVE_COMPUTED_GOTO
423 const Parrot_runcore_t
*core
= interp
->run_core
;
425 if (PARROT_RUNCORE_PREDEREF_OPS_TEST(core
)
426 && !PARROT_RUNCORE_CGOTO_OPS_TEST(core
))
428 #ifdef HAVE_COMPUTED_GOTO
429 cg_lib
= PARROT_CORE_CGP_OPLIB_INIT(1);
430 return ((void **)cg_lib
->op_func_table
)[op
];
439 =item C<static int pass_int(PARROT_INTERP, PMC *sig, const char *src_base, const
440 void **src, char *dest_base, void * const *dest)>
447 pass_int(PARROT_INTERP
, ARGIN(PMC
*sig
), ARGIN(const char *src_base
),
448 ARGIN(const void **src
), ARGOUT(char *dest_base
), ARGIN(void * const *dest
))
450 ASSERT_ARGS(pass_int
)
452 int n
= VTABLE_elements(interp
, sig
);
454 for (i
= 2; n
; ++i
, --n
) {
455 const INTVAL arg
= *(const INTVAL
*)(src_base
+ ((const opcode_t
*)src
)[i
]);
456 *(INTVAL
*)(dest_base
+ ((const opcode_t
*)dest
)[i
]) = arg
;
463 =item C<static int pass_num(PARROT_INTERP, PMC *sig, const char *src_base, const
464 void **src, char *dest_base, void * const *dest)>
471 pass_num(PARROT_INTERP
, ARGIN(PMC
*sig
), ARGIN(const char *src_base
),
472 ARGIN(const void **src
), ARGOUT(char *dest_base
), ARGIN(void * const *dest
))
474 ASSERT_ARGS(pass_num
)
476 int n
= VTABLE_elements(interp
, sig
);
478 for (i
= 2; n
; ++i
, --n
) {
479 const FLOATVAL arg
= *(const FLOATVAL
*)(src_base
+ ((const opcode_t
*)src
)[i
]);
480 *(FLOATVAL
*)(dest_base
+ ((const opcode_t
*)dest
)[i
]) = arg
;
487 =item C<static int pass_str(PARROT_INTERP, PMC *sig, const char *src_base, const
488 void **src, char *dest_base, void * const *dest)>
495 pass_str(PARROT_INTERP
, ARGIN(PMC
*sig
), ARGIN(const char *src_base
),
496 ARGIN(const void **src
), ARGOUT(char *dest_base
), ARGIN(void * const *dest
))
498 ASSERT_ARGS(pass_str
)
500 int n
= VTABLE_elements(interp
, sig
);
502 for (i
= 2; n
; ++i
, --n
) {
503 STRING
* const arg
= *(STRING
* const *)(src_base
+ ((const opcode_t
*)src
)[i
]);
504 *(STRING
* *)(dest_base
+ ((const opcode_t
*)dest
)[i
]) = arg
;
512 =item C<static int pass_pmc(PARROT_INTERP, PMC *sig, const char *src_base, const
513 void **src, char *dest_base, void * const *dest)>
520 pass_pmc(PARROT_INTERP
, ARGIN(PMC
*sig
), ARGIN(const char *src_base
),
521 ARGIN(const void **src
), ARGOUT(char *dest_base
), ARGIN(void * const *dest
))
523 ASSERT_ARGS(pass_pmc
)
525 int n
= VTABLE_elements(interp
, sig
);
527 for (i
= 2; n
; ++i
, --n
) {
528 PMC
* const arg
= *(PMC
* const *)(src_base
+ ((const opcode_t
*)src
)[i
]);
529 *(PMC
* *)(dest_base
+ ((const opcode_t
*)dest
)[i
])= arg
;
536 =item C<static int pass_mixed(PARROT_INTERP, PMC *sig, const char *src_base,
537 void * const *src, char *dest_base, void * const *dest)>
544 pass_mixed(PARROT_INTERP
, ARGIN(PMC
*sig
), ARGIN(const char *src_base
),
545 ARGIN(void * const *src
), ARGOUT(char *dest_base
), ARGIN(void * const *dest
))
547 ASSERT_ARGS(pass_mixed
)
550 int n
= VTABLE_elements(interp
, sig
);
553 GETATTR_FixedIntegerArray_int_array(interp
, sig
, bitp
);
555 for (i
= 2; n
; ++i
, --n
) {
556 const INTVAL bits
= *bitp
++;
558 case PARROT_ARG_INTVAL
:
560 const INTVAL argI
= *(const INTVAL
*)(src_base
+ ((const opcode_t
*)src
)[i
]);
561 *(INTVAL
*)(dest_base
+ ((const opcode_t
*)dest
)[i
])= argI
;
564 case PARROT_ARG_INTVAL
|PARROT_ARG_CONSTANT
:
565 *(INTVAL
*)(dest_base
+ ((const opcode_t
*)dest
)[i
]) = (INTVAL
)(src
)[i
];
567 case PARROT_ARG_FLOATVAL
:
569 const FLOATVAL argN
= *(const FLOATVAL
*)(src_base
+ ((const opcode_t
*)src
)[i
]);
570 *(FLOATVAL
*)(dest_base
+ ((const opcode_t
*)dest
)[i
])= argN
;
573 case PARROT_ARG_FLOATVAL
|PARROT_ARG_CONSTANT
:
575 const FLOATVAL argN
= *(const FLOATVAL
*)(src
)[i
];
576 *(FLOATVAL
*)(dest_base
+ ((const opcode_t
*)dest
)[i
])= argN
;
579 case PARROT_ARG_STRING
:
581 STRING
*argS
= *(STRING
* const *)(src_base
+ ((const opcode_t
*)src
)[i
]);
583 if (argS
&& PObj_constant_TEST(argS
))
584 argS
= Parrot_str_new_COW(interp
, argS
);
586 *(STRING
**)(dest_base
+ ((const opcode_t
*)dest
)[i
]) = argS
;
589 case PARROT_ARG_STRING
|PARROT_ARG_CONSTANT
:
591 STRING
*argS
= (STRING
*)(src
)[i
];
592 if (argS
&& PObj_constant_TEST(argS
))
593 argS
= Parrot_str_new_COW(interp
, argS
);
594 *(STRING
**)(dest_base
+ ((const opcode_t
*)dest
)[i
]) = argS
;
599 PMC
* const argP
= *(PMC
* const *)(src_base
+ ((const opcode_t
*)src
)[i
]);
600 *(PMC
* *)(dest_base
+ ((const opcode_t
*)dest
)[i
])= argP
;
603 case PARROT_ARG_PMC
|PARROT_ARG_CONSTANT
:
605 PMC
* const argP
= (PMC
*)(src
)[i
];
606 *(PMC
* *)(dest_base
+ ((const opcode_t
*)dest
)[i
])= argP
;
610 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
611 "bogus signature 0x%x", bits
);
620 =item C<int parrot_pic_check_sig(PARROT_INTERP, PMC *sig1, PMC *sig2, int
623 return argument count and type of the signature or -1 if not pic-able
624 the type PARROT_ARG_CONSTANT stands for mixed types or constants
630 PARROT_WARN_UNUSED_RESULT
632 parrot_pic_check_sig(PARROT_INTERP
, ARGIN(PMC
*sig1
), ARGIN(PMC
*sig2
),
635 ASSERT_ARGS(parrot_pic_check_sig
)
638 ASSERT_SIG_PMC(sig1
);
639 ASSERT_SIG_PMC(sig2
);
641 n
= VTABLE_elements(interp
, sig1
);
643 if (n
!= VTABLE_elements(interp
, sig2
))
651 for (i
= 0; i
< n
; ++i
) {
652 int t1
= VTABLE_get_integer_keyed_int(interp
, sig1
, i
);
653 int t2
= VTABLE_get_integer_keyed_int(interp
, sig2
, i
);
659 t0
= t1
& PARROT_ARG_TYPE_MASK
;
663 if (t1
& PARROT_ARG_CONSTANT
) {
664 *type
= PARROT_ARG_CONSTANT
;
665 t1
&= ~PARROT_ARG_CONSTANT
;
668 if (t1
& ~PARROT_ARG_TYPE_MASK
)
671 if (t2
& PARROT_ARG_CONSTANT
) {
672 *type
= PARROT_ARG_CONSTANT
;
673 t2
&= ~PARROT_ARG_CONSTANT
;
676 if (t2
& ~PARROT_ARG_TYPE_MASK
)
683 *type
= PARROT_ARG_CONSTANT
;
691 =item C<static int is_pic_param(PARROT_INTERP, void **pc, Parrot_MIC *mic,
699 is_pic_param(PARROT_INTERP
, ARGIN(void **pc
), ARGOUT(Parrot_MIC
*mic
), opcode_t op
)
701 ASSERT_ARGS(is_pic_param
)
705 PMC
* const sig1
= (PMC
*)(pc
[1]);
706 PMC
*ctx
= CURRENT_CONTEXT(interp
);
711 if (op
== PARROT_OP_set_returns_pc
) {
712 PMC
* const ccont
= Parrot_pcc_get_continuation(interp
, ctx
);
713 if (!PMC_cont(ccont
)->address
)
715 caller_ctx
= PMC_cont(ccont
)->to_ctx
;
716 args
= Parrot_pcc_get_results(interp
, caller_ctx
);
719 caller_ctx
= Parrot_pcc_get_caller_ctx(interp
, ctx
);
720 args
= interp
->current_args
;
724 const INTVAL const_nr
= args
[1];
727 /* check current_args signature */
728 sig2
= Parrot_pcc_get_pmc_constant(interp
, caller_ctx
, const_nr
);
729 n
= parrot_pic_check_sig(interp
, sig1
, sig2
, &type
);
735 if (VTABLE_elements(interp
, sig1
) == 0) {
744 case PARROT_ARG_INTVAL
:
745 mic
->lru
.f
.real_function
= (funcptr_t
)pass_int
;
747 case PARROT_ARG_FLOATVAL
:
748 mic
->lru
.f
.real_function
= (funcptr_t
)pass_num
;
750 case PARROT_ARG_STRING
:
751 mic
->lru
.f
.real_function
= (funcptr_t
)pass_str
;
754 mic
->lru
.f
.real_function
= (funcptr_t
)pass_pmc
;
756 case PARROT_ARG_CONSTANT
:
757 mic
->lru
.f
.real_function
= (funcptr_t
)pass_mixed
;
765 /* remember this sig2 - it has to match the other end at call time */
766 mic
->lru
.u
.signature
= sig2
;
774 =item C<static int is_pic_func(PARROT_INTERP, void **pc, Parrot_MIC *mic,
775 Parrot_runcore_t *runcore)>
782 is_pic_func(PARROT_INTERP
, ARGIN(void **pc
), ARGOUT(Parrot_MIC
*mic
),
783 ARGIN(Parrot_runcore_t
*runcore
))
785 ASSERT_ARGS(is_pic_func
)
787 * if we have these opcodes
791 * get_results '..' ...
794 * and all args are matching the called sub and we don't have
795 * too many args, and only INTVAL or FLOATVAL, the
796 * whole sequence is replaced by the C<callr> pic opcode.
798 * Oh, I forgot to mention - the to-be-called C function is of
799 * course compiled on-the-fly by the JIT compiler ;)
804 PMC
*sub
, *sig_results
;
808 PMC
* const ctx
= CURRENT_CONTEXT(interp
);
809 PMC
* const sig_args
= (PMC
*)(pc
[1]);
811 ASSERT_SIG_PMC(sig_args
);
812 n
= VTABLE_elements(interp
, sig_args
);
813 interp
->current_args
= (opcode_t
*)pc
+ Parrot_pcc_get_pred_offset(interp
, ctx
);
815 op
= (opcode_t
*)pc
+ Parrot_pcc_get_pred_offset(interp
, ctx
);
817 if (*op
!= PARROT_OP_set_p_pc
)
820 do_prederef(pc
, interp
, runcore
);
821 sub
= (PMC
*)(pc
[2]);
823 PARROT_ASSERT(PObj_is_PMC_TEST(sub
));
825 if (sub
->vtable
->base_type
!= enum_class_Sub
)
828 pc
+= 3; /* results */
829 op
= (opcode_t
*)pc
+ Parrot_pcc_get_pred_offset(interp
, ctx
);
831 if (*op
!= PARROT_OP_get_results_pc
)
834 do_prederef(pc
, interp
, runcore
);
835 sig_results
= (PMC
*)(pc
[1]);
836 ASSERT_SIG_PMC(sig_results
);
838 Parrot_pcc_set_results(interp
, ctx
, (opcode_t
*)pc
+ Parrot_pcc_get_pred_offset(interp
, ctx
));
839 if (!parrot_pic_is_safe_to_jit(interp
, sub
, sig_args
, sig_results
, &flags
))
842 mic
->lru
.f
.real_function
= parrot_pic_JIT_sub(interp
, sub
, flags
);
843 mic
->m
.sig
= sig_args
;
850 =item C<void parrot_PIC_prederef(PARROT_INTERP, opcode_t op, void **pc_pred,
851 Parrot_runcore_t *core)>
853 Define either the normal prederef function or the PIC stub, if PIC for
854 this opcode function is available. Called from C<do_prederef>.
861 parrot_PIC_prederef(PARROT_INTERP
, opcode_t op
, ARGOUT(void **pc_pred
),
862 ARGIN(Parrot_runcore_t
*core
))
864 ASSERT_ARGS(parrot_PIC_prederef
)
865 op_func_t
* const prederef_op_func
= interp
->op_lib
->op_func_table
;
866 opcode_t
* const cur_opcode
= (opcode_t
*)pc_pred
;
867 Parrot_MIC
*mic
= NULL
;
869 if (parrot_PIC_op_is_cached(op
)) {
870 const PackFile_ByteCode
* const cs
= interp
->code
;
871 size_t n
= cur_opcode
872 - (opcode_t
*)cs
->prederef
.code
;
875 * pic_index is half the size of the code
876 * XXX if it's there - pbc_merge needs updates
878 PARROT_ASSERT(cs
->pic_index
);
879 n
= cs
->pic_index
->data
[n
/ 2];
880 mic
= parrot_PIC_alloc_mic(interp
, n
);
884 case PARROT_OP_get_params_pc
:
885 if (is_pic_param(interp
, pc_pred
, mic
, op
)) {
886 pc_pred
[1] = (void *)mic
;
887 op
= PARROT_OP_pic_get_params___pc
;
890 case PARROT_OP_set_returns_pc
:
891 if (is_pic_param(interp
, pc_pred
, mic
, op
)) {
892 pc_pred
[1] = (void *)mic
;
893 op
= PARROT_OP_pic_set_returns___pc
;
896 case PARROT_OP_set_args_pc
:
897 if (is_pic_func(interp
, pc_pred
, mic
, core
)) {
898 pc_pred
[1] = (void *)mic
;
899 op
= PARROT_OP_pic_callr___pc
;
907 if (PARROT_RUNCORE_PREDEREF_OPS_TEST(core
)
908 && !PARROT_RUNCORE_CGOTO_OPS_TEST(core
))
909 *pc_pred
= (void **)op
;
911 *pc_pred
= ((void **)prederef_op_func
)[op
];
916 =item C<void parrot_pic_find_infix_v_pp(PARROT_INTERP, PMC *left, PMC *right,
917 Parrot_MIC *mic, opcode_t *cur_opcode)>
924 parrot_pic_find_infix_v_pp(PARROT_INTERP
, ARGIN(PMC
*left
), ARGIN(PMC
*right
),
925 ARGOUT(Parrot_MIC
*mic
), ARGOUT(opcode_t
*cur_opcode
))
927 ASSERT_ARGS(parrot_pic_find_infix_v_pp
)
928 /* unused; deprecated */
937 Leopold Toetsch with many hints from Ken Fox.
941 L<src/multidispatch.c>, L<src/object.c>, L<src/interp/interpreter.c>,
942 L<ops/core_ops_cgp.c>, L<include/parrot/pic.h>, L<ops/pic.ops>
951 * c-file-style: "parrot"
953 * vim: expandtab shiftwidth=4: