improve JIT support for property reference with failure value

For a non-procedure failure value, stay in the fast path and
return that value.
This commit is contained in:
Matthew Flatt 2017-12-22 18:12:29 -07:00
parent 9092d31c29
commit 8444b70bc1
2 changed files with 39 additions and 4 deletions

View File

@ -1222,18 +1222,36 @@
(let ()
(define-values (prop:a a? a-ref) (make-struct-type-property 'a))
(define (mk-prop)
(define-values (prop:b b? b-ref) (make-struct-type-property 'b))
prop:b)
(struct posn (x y)
#:property prop:a 'yes)
(struct posn2 posn ()
#:property (mk-prop) 0
#:property (mk-prop) 1
#:property (mk-prop) 2
#:property (mk-prop) 3
#:property (mk-prop) 4
#:property (mk-prop) 5)
(define (f p)
(and (a? p)
(a-ref p 'no)))
(define (g p get-no)
(a-ref p get-no))
(set! f f)
(set! g g)
(test 'yes f (posn 1 2))
(test 'yes f (posn2 1 2))
(test 'yes f (chaperone-struct (posn 1 2) posn-x (lambda (p x) x)))
(test 'yes f struct:posn)
(test #f f 5))
(test #f f struct:arity-at-least)
(test #f f 5)
(test 'nope g 5 (lambda () 'nope))
(test 'nope g struct:arity-at-least (lambda () 'nope)))
;; ----------------------------------------

View File

@ -2072,7 +2072,7 @@ static int common4b(mz_jit_state *jitter, void *_data)
for (i = 0; i < 3; i++) {
for (ii = 0; ii < 3; ii++) { /* single, multi, or tail */
void *code;
GC_CAN_IGNORE jit_insn *ref, *ref2, *ref3, *refno, *refslow, *refloop;
GC_CAN_IGNORE jit_insn *ref, *ref2, *ref3, *ref4, *refno, *refslow, *refloop;
int prim_other_type;
code = jit_get_ip();
@ -2153,6 +2153,23 @@ static int common4b(mz_jit_state *jitter, void *_data)
(void)jit_movi_p(JIT_R0, scheme_false);
mz_epilog(JIT_V1);
CHECK_LIMIT();
} else if (i == 1) {
refno = jit_get_ip();
jit_ldr_p(JIT_V1, JIT_RUNSTACK);
/* If the failure argument is not a procedure, we can
return it directly, otherwise take slow path. */
jit_ldxi_s(JIT_R2, JIT_V1, &((Scheme_Object *)0x0)->type);
__START_INNER_TINY__(1);
ref4 = jit_blti_i(jit_forward(), JIT_R2, scheme_prim_type);
__END_INNER_TINY__(1);
(void)jit_blei_i(refslow, JIT_R2, scheme_proc_chaperone_type);
__START_INNER_TINY__(1);
mz_patch_branch(ref4);
__END_INNER_TINY__(1);
jit_movr_p(JIT_R0, JIT_V1);
jit_addi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(1));
mz_epilog(JIT_V1);
CHECK_LIMIT();
} else
refno = refslow;
@ -2170,7 +2187,7 @@ static int common4b(mz_jit_state *jitter, void *_data)
__START_INNER_TINY__(1);
ref2 = jit_beqi_i(jit_forward(), JIT_R2, scheme_structure_type);
__END_INNER_TINY__(1);
if (i == 2) {
if (i != 0) { /* for i == 0 mode, `refno` is already `refslow` */
(void)jit_beqi_i(refslow, JIT_R2, scheme_proc_chaperone_type);
(void)jit_beqi_i(refslow, JIT_R2, scheme_chaperone_type);
(void)jit_beqi_i(refslow, JIT_R2, scheme_struct_type_type);
@ -2188,7 +2205,7 @@ static int common4b(mz_jit_state *jitter, void *_data)
/* negative count means use the hash table (in the slow path);
zero count means we've run out */
if (i == 2) {
if (i != 0) {
(void)jit_blei_i(refslow, JIT_V1, 0);
}
refloop = jit_get_ip();