* src/pbc_merge.c:
[parrot.git] / src / pic.c
blob0f235e04221d18a7b494366cfb4ac36e4215a92e
1 /*
2 Copyright (C) 2004-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pic.c - Polymorphic Inline Cache
9 =head1 DESCRIPTION
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
16 is basically:
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
24 Given this bytecode:
26 0 1 2 3 4 5
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:
35 0 1 2 3 4 5
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:
43 0 1 2
44 +---+---+---+
45 | 1 | | 2 |
46 +---+---+---+
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:
52 0 1 2 3
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:
59 0 1 2 3
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 (mmaped) bytecode can't be rewritten in this way, the
69 lookup of the cache has to be done in the opcode itself.
71 =head2 Functions
73 =over 4
75 =cut
79 #include "parrot/parrot.h"
80 #include "parrot/oplib/ops.h"
81 #ifdef HAVE_COMPUTED_GOTO
82 # include "parrot/oplib/core_ops_cgp.h"
83 #endif
85 #ifdef HAS_JIT
86 # include "parrot/exec.h"
87 # include "jit.h"
88 #endif
90 /* needs a Makefile dependency */
91 /* #include "pmc/pmc_integer.h" */
93 /* XXX Define this in a header file */
94 extern void Parrot_Integer_i_subtract_Integer(Interp* , PMC* pmc, PMC* value);
97 * hack to turn on inlining - just sub_p_p for mops done
100 #define ENABLE_INLINING 0
102 /* HEADERIZER HFILE: include/parrot/pic.h */
104 /* HEADERIZER BEGIN: static */
105 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
107 static int is_pic_func(PARROT_INTERP,
108 ARGIN(void **pc),
109 ARGOUT(Parrot_MIC *mic),
110 int core_type)
111 __attribute__nonnull__(1)
112 __attribute__nonnull__(2)
113 __attribute__nonnull__(3)
114 FUNC_MODIFIES(*mic);
116 static int is_pic_param(PARROT_INTERP,
117 ARGIN(void **pc),
118 ARGOUT(Parrot_MIC *mic),
119 opcode_t op)
120 __attribute__nonnull__(1)
121 __attribute__nonnull__(2)
122 __attribute__nonnull__(3)
123 FUNC_MODIFIES(*mic);
125 static void parrot_pic_move(PARROT_INTERP, ARGMOD(Parrot_MIC *mic))
126 __attribute__nonnull__(1)
127 __attribute__nonnull__(2)
128 FUNC_MODIFIES(*mic);
130 static int pass_int(SHIM_INTERP,
131 ARGIN(const PMC *sig),
132 ARGIN(const char *src_base),
133 ARGIN(const void **src),
134 ARGOUT(char *dest_base),
135 ARGIN(void * const *dest))
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,
144 ARGIN(const PMC *sig),
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(SHIM_INTERP,
158 ARGIN(const PMC *sig),
159 ARGIN(const char *src_base),
160 ARGIN(const void **src),
161 ARGOUT(char *dest_base),
162 ARGIN(void * const *dest))
163 __attribute__nonnull__(2)
164 __attribute__nonnull__(3)
165 __attribute__nonnull__(4)
166 __attribute__nonnull__(5)
167 __attribute__nonnull__(6)
168 FUNC_MODIFIES(*dest_base);
170 static int pass_pmc(SHIM_INTERP,
171 ARGIN(const PMC *sig),
172 ARGIN(const char *src_base),
173 ARGIN(const void **src),
174 ARGOUT(char *dest_base),
175 ARGIN(void * const *dest))
176 __attribute__nonnull__(2)
177 __attribute__nonnull__(3)
178 __attribute__nonnull__(4)
179 __attribute__nonnull__(5)
180 __attribute__nonnull__(6)
181 FUNC_MODIFIES(*dest_base);
183 static int pass_str(SHIM_INTERP,
184 ARGIN(const PMC *sig),
185 ARGIN(const char *src_base),
186 ARGIN(const void **src),
187 ARGOUT(char *dest_base),
188 ARGIN(void * const *dest))
189 __attribute__nonnull__(2)
190 __attribute__nonnull__(3)
191 __attribute__nonnull__(4)
192 __attribute__nonnull__(5)
193 __attribute__nonnull__(6)
194 FUNC_MODIFIES(*dest_base);
196 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
197 /* HEADERIZER END: static */
202 =item C<void parrot_PIC_alloc_store>
204 Initialize the PIC storage for the given code segment with the capacitiy of
205 holding at least C<n> MIC entries. The PIC_store itself, room for C<n> MICs and
206 some space for PICs is allocated as one piece. MICs are returned from the start
207 of usable memory, PICs from the rear.
209 =cut
213 void
214 parrot_PIC_alloc_store(ARGOUT(struct PackFile_ByteCode *cs), size_t n)
216 size_t size, poly;
217 Parrot_PIC_store *store;
220 * estimated 95% of calls are monomorphic, 5% are polymorphic
221 * we need therefore:
223 #define POLYMORPHIC 0.05
225 poly = (size_t)(n * POLYMORPHIC) * sizeof (Parrot_PIC);
226 if (!poly)
227 poly = 2 * sizeof (Parrot_PIC);
228 size = n * sizeof (Parrot_MIC) + poly + sizeof (Parrot_PIC_store);
230 store = (Parrot_PIC_store *)mem_sys_allocate_zeroed(size);
231 store->prev = NULL;
232 cs->pic_store = store;
234 store->pic = (Parrot_PIC*)((char *)store + size);
235 store->usable = poly;
236 store->mic = (Parrot_MIC*)((char*)store + sizeof (Parrot_PIC_store));
237 store->n_mics = n;
242 =item C<void parrot_PIC_destroy>
244 Free memory for the PIC storage.
246 =cut
250 void
251 parrot_PIC_destroy(ARGMOD(struct PackFile_ByteCode *cs))
253 Parrot_PIC_store *store = cs->pic_store;
255 while (store) {
256 Parrot_PIC_store * const prev = store->prev;
257 mem_sys_free(store);
258 store = prev;
260 cs->pic_store = NULL;
265 =item C<int parrot_PIC_op_is_cached>
267 Return true, if the opcode needs a PIC slot.
269 =cut
273 PARROT_CONST_FUNCTION
275 parrot_PIC_op_is_cached(int op_code)
277 switch (op_code) {
278 case PARROT_OP_infix_ic_p_p:
279 case PARROT_OP_get_params_pc:
280 case PARROT_OP_set_returns_pc:
281 case PARROT_OP_set_args_pc:
282 return 1;
283 default:
284 return 0;
290 =item C<Parrot_MIC* parrot_PIC_alloc_mic>
292 Allocate a new MIC structure for the C<n>th cached opcode in this
293 bytecode segement.
295 =cut
299 PARROT_WARN_UNUSED_RESULT
300 PARROT_CANNOT_RETURN_NULL
301 Parrot_MIC*
302 parrot_PIC_alloc_mic(const PARROT_INTERP, size_t n)
304 Parrot_PIC_store * const store = interp->code->pic_store;
305 PARROT_ASSERT(n < store->n_mics);
306 return store->mic + n;
311 =item C<Parrot_PIC* parrot_PIC_alloc_pic>
313 Allocate a new PIC structure for the C<n>th cached opcode in this
314 bytecode segement.
316 =cut
320 PARROT_WARN_UNUSED_RESULT
321 PARROT_CANNOT_RETURN_NULL
322 Parrot_PIC*
323 parrot_PIC_alloc_pic(PARROT_INTERP)
325 Parrot_PIC_store *store = interp->code->pic_store;
326 Parrot_PIC_store *new_store;
328 if (store->usable < sizeof (Parrot_PIC)) {
329 size_t size =
330 (size_t)(store->n_mics * POLYMORPHIC) * sizeof (Parrot_PIC);
331 if (size == 0)
332 size = 2 * sizeof (Parrot_PIC);
333 new_store = (Parrot_PIC_store *)mem_sys_allocate_zeroed(size + sizeof (Parrot_PIC_store));
334 new_store->prev = store;
335 interp->code->pic_store = new_store;
337 new_store->pic = (Parrot_PIC*)((char *)new_store + size +
338 sizeof (Parrot_PIC_store));
339 new_store->usable = size;
341 * the addon store has only poly-morphic slots
342 * point the monomorphic to the old store
344 new_store->mic = store->mic;
345 new_store->n_mics = store->n_mics;
346 store = new_store;
348 store->usable -= sizeof (Parrot_PIC);
349 return --store->pic;
354 =item C<void * parrot_pic_opcode>
356 RT#48260: Not yet documented!!!
358 =cut
362 PARROT_WARN_UNUSED_RESULT
363 PARROT_CAN_RETURN_NULL
364 void *
365 parrot_pic_opcode(PARROT_INTERP, INTVAL op)
367 const int core = interp->run_core;
368 #ifdef HAVE_COMPUTED_GOTO
369 op_lib_t *cg_lib;
370 #endif
372 if (core == PARROT_SWITCH_CORE || core == PARROT_SWITCH_JIT_CORE)
373 return (void*) op;
374 #ifdef HAVE_COMPUTED_GOTO
375 cg_lib = PARROT_CORE_CGP_OPLIB_INIT(1);
376 return ((void**)cg_lib->op_func_table)[op];
377 #else
378 return NULL;
379 #endif
384 =item C<static int pass_int>
386 RT#48260: Not yet documented!!!
388 =cut
392 static int
393 pass_int(SHIM_INTERP, ARGIN(const PMC *sig), ARGIN(const char *src_base),
394 ARGIN(const void **src), ARGOUT(char *dest_base), ARGIN(void * const *dest))
396 int n = SIG_ELEMS(sig);
397 int i;
399 for (i = 2 ; n; ++i, --n) {
400 const INTVAL arg = *(const INTVAL *)(src_base + ((const opcode_t*)src)[i]);
401 *(INTVAL *)(dest_base + ((const opcode_t*)dest)[i]) = arg;
403 return i;
408 =item C<static int pass_num>
410 RT#48260: Not yet documented!!!
412 =cut
416 static int
417 pass_num(SHIM_INTERP, ARGIN(const PMC *sig), ARGIN(const char *src_base),
418 ARGIN(const void **src), ARGOUT(char *dest_base), ARGIN(void * const *dest))
420 int n = SIG_ELEMS(sig);
421 int i;
423 for (i = 2 ; n; ++i, --n) {
424 const FLOATVAL arg = *(const FLOATVAL *)(src_base + ((const opcode_t*)src)[i]);
425 *(FLOATVAL *)(dest_base + ((const opcode_t*)dest)[i]) = arg;
427 return i;
432 =item C<static int pass_str>
434 RT#48260: Not yet documented!!!
436 =cut
440 static int
441 pass_str(SHIM_INTERP, ARGIN(const PMC *sig), ARGIN(const char *src_base),
442 ARGIN(const void **src), ARGOUT(char *dest_base), ARGIN(void * const *dest))
444 int n = SIG_ELEMS(sig);
445 int i;
447 for (i = 2 ; n; ++i, --n) {
448 STRING * const arg = *(STRING* const *)(src_base + ((const opcode_t*)src)[i]);
449 *(STRING* *)(dest_base + ((const opcode_t*)dest)[i])= arg;
451 return i;
456 =item C<static int pass_pmc>
458 RT#48260: Not yet documented!!!
460 =cut
464 static int
465 pass_pmc(SHIM_INTERP, ARGIN(const PMC *sig), ARGIN(const char *src_base),
466 ARGIN(const void **src), ARGOUT(char *dest_base), ARGIN(void * const *dest))
468 int n = SIG_ELEMS(sig);
469 int i;
471 for (i = 2 ; n; ++i, --n) {
472 PMC * const arg = *(PMC* const *)(src_base + ((const opcode_t*)src)[i]);
473 *(PMC* *)(dest_base + ((const opcode_t*)dest)[i])= arg;
475 return i;
480 =item C<static int pass_mixed>
482 RT#48260: Not yet documented!!!
484 =cut
488 static int
489 pass_mixed(PARROT_INTERP, ARGIN(const PMC *sig), ARGIN(const char *src_base),
490 ARGIN(void * const *src), ARGOUT(char *dest_base), ARGIN(void * const *dest))
492 int n = SIG_ELEMS(sig);
493 int i;
494 INTVAL *bitp;
496 ASSERT_SIG_PMC(sig);
497 bitp = SIG_ARRAY(sig);
498 for (i = 2 ; n; ++i, --n) {
499 const INTVAL bits = *bitp++;
500 switch (bits) {
501 case PARROT_ARG_INTVAL:
503 const INTVAL argI = *(const INTVAL *)(src_base + ((const opcode_t*)src)[i]);
504 *(INTVAL *)(dest_base + ((const opcode_t*)dest)[i])= argI;
506 break;
507 case PARROT_ARG_INTVAL|PARROT_ARG_CONSTANT:
508 *(INTVAL *)(dest_base + ((const opcode_t*)dest)[i]) = (INTVAL)(src)[i];
509 break;
510 case PARROT_ARG_FLOATVAL:
512 const FLOATVAL argN = *(const FLOATVAL *)(src_base + ((const opcode_t*)src)[i]);
513 *(FLOATVAL *)(dest_base + ((const opcode_t*)dest)[i])= argN;
515 break;
516 case PARROT_ARG_FLOATVAL|PARROT_ARG_CONSTANT:
518 const FLOATVAL argN = *(const FLOATVAL*)(src)[i];
519 *(FLOATVAL *)(dest_base + ((const opcode_t*)dest)[i])= argN;
521 break;
522 case PARROT_ARG_STRING:
524 STRING * const argS = *(STRING * const *)(src_base + ((const opcode_t*)src)[i]);
525 *(STRING* *)(dest_base + ((const opcode_t*)dest)[i])= argS;
527 break;
528 case PARROT_ARG_STRING|PARROT_ARG_CONSTANT:
530 STRING * const argS = (STRING*)(src)[i];
531 *(STRING* *)(dest_base + ((const opcode_t*)dest)[i])= argS;
533 break;
534 case PARROT_ARG_PMC:
536 PMC* const argP = *(PMC * const *)(src_base + ((const opcode_t*)src)[i]);
537 *(PMC* *)(dest_base + ((const opcode_t*)dest)[i])= argP;
539 break;
540 case PARROT_ARG_PMC|PARROT_ARG_CONSTANT:
542 PMC* const argP = (PMC*)(src)[i];
543 *(PMC* *)(dest_base + ((const opcode_t*)dest)[i])= argP;
545 break;
546 default:
547 Parrot_ex_throw_from_c_args(interp, NULL, 1,
548 "bogus signature 0x%x", bits);
549 break;
552 return i;
557 =item C<int parrot_pic_check_sig>
559 return argument count and type of the signature or -1 if not pic-able
560 the type PARROT_ARG_CONSTANT stands for mixed types or constants
562 =cut
566 PARROT_WARN_UNUSED_RESULT
568 parrot_pic_check_sig(ARGIN(const PMC *sig1), ARGIN(const PMC *sig2),
569 ARGOUT(int *type))
571 int i, n, t0;
573 ASSERT_SIG_PMC(sig1);
574 ASSERT_SIG_PMC(sig2);
575 n = SIG_ELEMS(sig1);
576 if (n != SIG_ELEMS(sig2))
577 return -1;
578 if (!n) {
579 *type = 0;
580 return 0;
582 for (i = 0; i < n; ++i) {
583 int t1 = SIG_ITEM(sig1, i);
584 int t2 = SIG_ITEM(sig2, i);
586 if (i) {
587 t0 = 0;
589 else {
590 t0 = t1 & PARROT_ARG_TYPE_MASK;
591 *type = t0;
593 if (t1 & PARROT_ARG_CONSTANT) {
594 *type = PARROT_ARG_CONSTANT;
595 t1 &= ~PARROT_ARG_CONSTANT;
597 if (t1 & ~PARROT_ARG_TYPE_MASK)
598 return -1;
599 if (t2 & PARROT_ARG_CONSTANT) {
600 *type = PARROT_ARG_CONSTANT;
601 t2 &= ~PARROT_ARG_CONSTANT;
603 if (t2 & ~PARROT_ARG_TYPE_MASK)
604 return -1;
605 if (t2 != t1)
606 return -1;
607 if (t1 != t0)
608 *type = PARROT_ARG_CONSTANT;
610 return n;
615 =item C<static int is_pic_param>
617 RT#48260: Not yet documented!!!
619 =cut
623 static int
624 is_pic_param(PARROT_INTERP, ARGIN(void **pc), ARGOUT(Parrot_MIC *mic), opcode_t op)
626 PMC *sig2;
627 parrot_context_t *caller_ctx;
628 opcode_t *args;
629 PMC * const sig1 = (PMC *)(pc[1]);
630 const parrot_context_t * const ctx = CONTEXT(interp);
631 int type = 0;
633 /* check params */
635 if (op == PARROT_OP_set_returns_pc) {
636 PMC * const ccont = ctx->current_cont;
637 if (!PMC_cont(ccont)->address)
638 return 0;
639 caller_ctx = PMC_cont(ccont)->to_ctx;
640 args = caller_ctx->current_results;
642 else {
643 caller_ctx = ctx->caller_ctx;
644 args = interp->current_args;
647 if (args) {
648 const INTVAL const_nr = args[1];
649 int n;
651 /* check current_args signature */
652 sig2 = caller_ctx->constants[const_nr]->u.key;
653 n = parrot_pic_check_sig(sig1, sig2, &type);
655 if (n == -1)
656 return 0;
658 else {
659 if (SIG_ELEMS(sig1))
660 return 0;
662 sig2 = NULL;
665 switch (type) {
666 case PARROT_ARG_INTVAL:
667 mic->lru.f.real_function = (funcptr_t)pass_int;
668 break;
669 case PARROT_ARG_FLOATVAL:
670 mic->lru.f.real_function = (funcptr_t)pass_num;
671 break;
672 case PARROT_ARG_STRING:
673 mic->lru.f.real_function = (funcptr_t)pass_str;
674 break;
675 case PARROT_ARG_PMC:
676 mic->lru.f.real_function = (funcptr_t)pass_pmc;
677 break;
678 case PARROT_ARG_CONSTANT:
679 mic->lru.f.real_function = (funcptr_t)pass_mixed;
680 break;
681 default:
682 return 0;
685 mic->m.sig = sig1;
687 /* remember this sig2 - it has to match the other end at call time */
688 mic->lru.u.signature = sig2;
690 return 1;
696 =item C<static int is_pic_func>
698 RT#48260: Not yet documented!!!
700 =cut
704 static int
705 is_pic_func(PARROT_INTERP, ARGIN(void **pc), ARGOUT(Parrot_MIC *mic), int core_type)
708 * if we have these opcodes
710 * set_args '..' ...
711 * set_p_pc Px, PFunx
712 * get_results '..' ...
713 * invokecc_p Px
715 * and all args are matching the called sub and we don't have
716 * too many args, and only INTVAL or FLOATVAL, the
717 * whole sequence is replaced by the C<callr> pic opcode.
719 * Oh, I forgot to mention - the to-be-called C function is of
720 * course compiled on-the-fly by the JIT compiler ;)
722 * pc is at set_args
725 PMC *sub, *sig_results;
726 opcode_t *op, n;
727 int flags;
729 parrot_context_t * const ctx = CONTEXT(interp);
730 PMC * const sig_args = (PMC*)(pc[1]);
732 ASSERT_SIG_PMC(sig_args);
733 n = SIG_ELEMS(sig_args);
734 interp->current_args = (opcode_t*)pc + ctx->pred_offset;
735 pc += 2 + n;
736 op = (opcode_t*)pc + ctx->pred_offset;
737 if (*op != PARROT_OP_set_p_pc)
738 return 0;
739 do_prederef(pc, interp, core_type);
740 sub = (PMC*)(pc[2]);
741 PARROT_ASSERT(PObj_is_PMC_TEST(sub));
742 if (sub->vtable->base_type != enum_class_Sub)
743 return 0;
744 pc += 3; /* results */
745 op = (opcode_t*)pc + ctx->pred_offset;
746 if (*op != PARROT_OP_get_results_pc)
747 return 0;
748 do_prederef(pc, interp, core_type);
749 sig_results = (PMC*)(pc[1]);
750 ASSERT_SIG_PMC(sig_results);
752 ctx->current_results = (opcode_t*)pc + ctx->pred_offset;
753 if (!parrot_pic_is_safe_to_jit(interp, sub,
754 sig_args, sig_results, &flags))
755 return 0;
756 mic->lru.f.real_function = parrot_pic_JIT_sub(interp, sub, flags);
757 mic->m.sig = sig_args;
758 return 1;
763 =item C<void parrot_PIC_prederef>
765 Define either the normal prederef function or the PIC stub, if PIC for
766 this opcode function is available. Called from C<do_prederef>.
768 =cut
772 void
773 parrot_PIC_prederef(PARROT_INTERP, opcode_t op, ARGOUT(void **pc_pred), int core)
775 op_func_t * const prederef_op_func = interp->op_lib->op_func_table;
776 opcode_t * const cur_opcode = (opcode_t*)pc_pred;
777 Parrot_MIC *mic = NULL;
779 if (parrot_PIC_op_is_cached(op)) {
780 const PackFile_ByteCode * const cs = interp->code;
781 size_t n = cur_opcode - (opcode_t*)cs->prederef.code;
783 * pic_index is half the size of the code
784 * XXX if it's there - pbc_merge needs updates
786 PARROT_ASSERT(cs->pic_index);
787 n = cs->pic_index->data[n / 2];
788 mic = parrot_PIC_alloc_mic(interp, n);
791 switch (op) {
792 case PARROT_OP_new_p_sc:
794 INTVAL type;
795 STRING * const _class = (STRING *)cur_opcode[2];
796 type = pmc_type(interp, _class);
797 if (!type)
798 type = pmc_type(interp, _class);
800 if (type <= 0)
801 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_NO_CLASS,
802 "Class '%Ss' not found", _class);
804 pc_pred[2] = (void*)type;
805 op = PARROT_OP_new_p_ic;
807 break;
808 case PARROT_OP_infix_ic_p_p:
809 mic->m.func_nr = (INTVAL) cur_opcode[1];
810 pc_pred[1] = (void*) mic;
811 op = PARROT_OP_pic_infix___ic_p_p;
812 break;
813 case PARROT_OP_get_params_pc:
814 if (is_pic_param(interp, pc_pred, mic, op)) {
815 pc_pred[1] = (void*) mic;
816 op = PARROT_OP_pic_get_params___pc;
818 break;
819 case PARROT_OP_set_returns_pc:
820 if (is_pic_param(interp, pc_pred, mic, op)) {
821 pc_pred[1] = (void*) mic;
822 op = PARROT_OP_pic_set_returns___pc;
824 break;
825 case PARROT_OP_set_args_pc:
826 if (is_pic_func(interp, pc_pred, mic, core)) {
827 pc_pred[1] = (void*) mic;
828 op = PARROT_OP_pic_callr___pc;
830 break;
831 default:
832 break;
835 /* rewrite opcode */
836 if (core == PARROT_SWITCH_CORE || core == PARROT_SWITCH_JIT_CORE)
837 *pc_pred = (void **)op;
838 else
839 *pc_pred = ((void **)prederef_op_func)[op];
844 =item C<static void parrot_pic_move>
846 RT#48260: Not yet documented!!!
848 =cut
852 static void
853 parrot_pic_move(PARROT_INTERP, ARGMOD(Parrot_MIC *mic))
856 * MIC slot is empty - use it
858 if (!mic->lru.u.type)
859 return;
861 * need more cache slots - allocate one PIC
863 if (!mic->pic) {
864 mic->pic = parrot_PIC_alloc_pic(interp);
866 else {
868 * PIC was already used - shift slots up
870 Parrot_PIC * const pic = mic->pic;
872 pic->lru[2].u.type = pic->lru[1].u.type;
873 pic->lru[2].f.sub = pic->lru[1].f.sub;
874 pic->lru[1].u.type = pic->lru[0].u.type;
875 pic->lru[1].f.sub = pic->lru[0].f.sub;
876 pic->lru[0].u.type = mic->lru.u.type;
877 pic->lru[0].f.sub = mic->lru.f.sub;
878 mic->lru.u.type = 0;
884 =item C<void parrot_pic_find_infix_v_pp>
886 RT#48260: Not yet documented!!!
888 =cut
892 void
893 parrot_pic_find_infix_v_pp(PARROT_INTERP, ARGIN(PMC *left), ARGIN(PMC *right),
894 ARGOUT(Parrot_MIC *mic), ARGOUT(opcode_t *cur_opcode))
896 funcptr_t func;
897 int is_pmc;
898 INTVAL left_type, right_type;
900 * if 2 threads are entering here, there is a chance
901 * that one moves the lru structure under the other thread
902 * and vv - just lock in case
904 * TODO
906 * if (TRY_LOCK_INTERPRETER(i) == EBUSY)
907 * return; - reexec
909 LOCK_INTERPRETER(interp);
911 * move entries back and set topmost entry
913 parrot_pic_move(interp, mic);
915 * get real dispatch function
917 left_type = VTABLE_type(interp, left);
918 right_type = VTABLE_type(interp, right);
919 func = get_mmd_dispatch_type(interp,
920 mic->m.func_nr, left_type, right_type, &is_pmc);
921 if (is_pmc) {
922 const size_t offs = cur_opcode - (opcode_t *)interp->code->prederef.code;
923 opcode_t* const real_op = interp->code->base.data + offs + 1;
924 /* set prederef code address to orig slot for now
926 ((void**)cur_opcode)[0] =
927 parrot_pic_opcode(interp, PARROT_OP_infix_ic_p_p);
928 /* restore 1st operand i.e. .MMD_func_nr */
929 ((void**)cur_opcode)[1] = (void*)*real_op;
930 mic->lru.f.sub = (PMC*)F2DPTR(func);
932 else {
933 INTVAL op = PARROT_OP_pic_infix___ic_p_p;
935 #if ENABLE_INLINING
936 if (func == (funcptr_t)Parrot_Integer_i_subtract_Integer && !mic->pic)
937 op = PARROT_OP_pic_inline_sub___ic_p_p;
938 #endif
939 ((void**)cur_opcode)[0] =
940 parrot_pic_opcode(interp, op);
941 mic->lru.f.real_function = func;
943 mic->lru.u.type = (left_type << 16) | right_type;
944 UNLOCK_INTERPRETER(interp);
949 =back
951 =head1 AUTHOR
953 Leopold Toetsch with many hints from Ken Fox.
955 =head1 SEE ALSO
957 F<src/mmd.c>, F<src/object.c>, F<src/interpreter.c>, F<ops/core_ops_cgp.c>,
958 F<include/parrot/pic.h>, F<ops/pic.ops>
960 =cut
966 * Local variables:
967 * c-file-style: "parrot"
968 * End:
969 * vim: expandtab shiftwidth=4: