JIT: fast path for procedure impersonator w/o wrapper proc

Make the JIT-generated function-call dispatch recognize a call to
an impersonator that wraps a procedure only to hold properties.

This change also repairs handling for a arity-reducing wrapper
on a primitive, where the fast path incorrecty treated the
primitive as a JIT-generated function.
This commit is contained in:
Matthew Flatt 2015-12-22 15:03:49 -07:00
parent b794404333
commit 592ae853e3

View File

@ -66,6 +66,7 @@ static Scheme_Object *clear_runstack(Scheme_Object **rs, intptr_t amt, Scheme_Ob
static jit_insn *generate_proc_struct_retry(mz_jit_state *jitter, int num_rands, GC_CAN_IGNORE jit_insn *refagain)
{
GC_CAN_IGNORE jit_insn *ref2, *refz1, *refz2, *refz3, *refz4, *refz5;
GC_CAN_IGNORE jit_insn *refz6, *refz7, *refz8;
ref2 = jit_bnei_i(jit_forward(), JIT_R1, scheme_proc_struct_type);
jit_ldxi_p(JIT_R1, JIT_V1, &((Scheme_Structure *)0x0)->stype);
@ -109,11 +110,27 @@ static jit_insn *generate_proc_struct_retry(mz_jit_state *jitter, int num_rands,
(void)jit_jmpi(refagain);
CHECK_LIMIT();
mz_patch_branch(ref2);
/* check for a procedure impersonator that just keeps properties */
ref2 = jit_bnei_i(jit_forward(), JIT_R1, scheme_proc_chaperone_type);
jit_ldxi_p(JIT_R1, JIT_V1, &((Scheme_Chaperone *)0x0)->redirects);
refz6 = mz_bnei_t(jit_forward(), JIT_R1, scheme_vector_type, JIT_R2);
(void)jit_ldxi_l(JIT_R2, JIT_R1, &SCHEME_VEC_SIZE(0x0));
refz7 = jit_bmci_i(jit_forward(), JIT_R2, 0x1);
(void)jit_ldxi_l(JIT_R2, JIT_R1, &(SCHEME_VEC_ELS(0x0)[0]));
refz8 = jit_bnei_p(jit_forward(), JIT_R2, scheme_false);
/* Can extract the impersonated function and use it directly */
jit_ldxi_p(JIT_V1, JIT_V1, &((Scheme_Chaperone *)0x0)->prev);
(void)jit_jmpi(refagain);
mz_patch_branch(refz1);
mz_patch_branch(refz2);
mz_patch_branch(refz3);
mz_patch_branch(refz4);
mz_patch_branch(refz5);
mz_patch_branch(refz6);
mz_patch_branch(refz7);
mz_patch_branch(refz8);
return ref2;
}
@ -347,10 +364,12 @@ int scheme_generate_tail_call(mz_jit_state *jitter, int num_rands, int direct_na
must be >= 0 */
{
int i, r2_has_runstack = 0;
GC_CAN_IGNORE jit_insn *refagain, *ref, *ref2, *ref4, *ref5;
GC_CAN_IGNORE jit_insn *top_refagain, *refagain, *ref, *ref2, *ref4, *ref5;
__START_SHORT_JUMPS__(num_rands < 100);
top_refagain = jit_get_ip();
/* First, try fast direct jump to native code: */
if (!direct_native) {
ref = jit_bmsi_ul(jit_forward(), JIT_V1, 0x1);
@ -474,7 +493,7 @@ int scheme_generate_tail_call(mz_jit_state *jitter, int num_rands, int direct_na
/* Handle simple applicable struct: */
mz_patch_branch(ref2);
/* uses JIT_R1: */
ref2 = generate_proc_struct_retry(jitter, num_rands, refagain);
ref2 = generate_proc_struct_retry(jitter, num_rands, top_refagain);
CHECK_LIMIT();
}
@ -767,7 +786,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
if num_rands != -3, need to pop runstack before returning.
If num_rands == -1 or -3, skip prolog. */
GC_CAN_IGNORE jit_insn *ref, *ref2, *ref4, *ref5, *ref6, *ref7, *ref8, *ref9;
GC_CAN_IGNORE jit_insn *ref10, *refagain;
GC_CAN_IGNORE jit_insn *ref10, *refagain, *top_refagain;
GC_CAN_IGNORE jit_insn *refrts USED_ONLY_FOR_FUTURES;
#ifndef FUEL_AUTODECEREMENTS
GC_CAN_IGNORE jit_insn *ref11;
@ -785,6 +804,8 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
}
}
top_refagain = jit_get_ip();
/* Check for inlined native type */
if (!direct_native) {
ref = jit_bmsi_ul(jit_forward(), JIT_V1, 0x1);
@ -1029,7 +1050,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
if (!is_inlined && (num_rands >= 0)) {
mz_patch_branch(ref2);
/* uses JIT_R1 */
ref2 = generate_proc_struct_retry(jitter, num_rands, refagain);
ref2 = generate_proc_struct_retry(jitter, num_rands, top_refagain);
CHECK_LIMIT();
}
} else {