From 6d4ff3090941b0a780e472e9b1a20aeb072614b9 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sat, 28 Sep 2013 17:38:45 -0400 Subject: [PATCH] fix JIT bug related to unboxed arguments in self tail calls --- pkgs/math/tests/stress/beta-test.rkt | 18 ++++++++++++++++++ racket/src/racket/src/jit.h | 2 +- racket/src/racket/src/jitcall.c | 11 ++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 pkgs/math/tests/stress/beta-test.rkt diff --git a/pkgs/math/tests/stress/beta-test.rkt b/pkgs/math/tests/stress/beta-test.rkt new file mode 100644 index 0000000000..1ded34aa6c --- /dev/null +++ b/pkgs/math/tests/stress/beta-test.rkt @@ -0,0 +1,18 @@ +#lang racket + +;; This is a stress test for Racket, not for math. +;; (Producing a smaller test for Racket is difficult.) + +(require math/special-functions + math/statistics) + +(define (f x) + (flbeta-inc 2.0 3.0 x #f #t)) + +(define-values (l r) + (count-samples + (for/list ([_ (in-range 100000)]) + (f #i40/499)))) + +(unless (= 1 (length l)) + (error "failed: ~s ~s\n" l r)) diff --git a/racket/src/racket/src/jit.h b/racket/src/racket/src/jit.h index 803a9ddeb1..0dd237eadb 100644 --- a/racket/src/racket/src/jit.h +++ b/racket/src/racket/src/jit.h @@ -1549,7 +1549,7 @@ int scheme_is_non_gc(Scheme_Object *obj, int depth); int scheme_jit_check_closure_flonum_bit(Scheme_Closure_Data *data, int pos, int delta); # define CLOSURE_ARGUMENT_IS_FLONUM(data, pos) scheme_jit_check_closure_flonum_bit(data, pos, 0) # define CLOSURE_CONTENT_IS_FLONUM(data, pos) scheme_jit_check_closure_flonum_bit(data, pos, data->num_params) - int scheme_jit_check_closure_extflonum_bit(Scheme_Closure_Data *data, int pos, int delta); +int scheme_jit_check_closure_extflonum_bit(Scheme_Closure_Data *data, int pos, int delta); # define CLOSURE_ARGUMENT_IS_EXTFLONUM(data, pos) scheme_jit_check_closure_extflonum_bit(data, pos, 0) # define CLOSURE_CONTENT_IS_EXTFLONUM(data, pos) scheme_jit_check_closure_extflonum_bit(data, pos, data->num_params) #endif diff --git a/racket/src/racket/src/jitcall.c b/racket/src/racket/src/jitcall.c index 39319d5faa..003d95034d 100644 --- a/racket/src/racket/src/jitcall.c +++ b/racket/src/racket/src/jitcall.c @@ -1191,6 +1191,7 @@ static int generate_self_tail_call(Scheme_Object *rator, mz_jit_state *jitter, i rand = (alt_rands ? alt_rands[i+1+args_already_in_place] : app->args[i+1+args_already_in_place]); + arg_tmp_offset += MZ_FPUSEL(extfl, 2*sizeof(double), sizeof(double)); /* Boxing definitely isn't needed if the value was from a local that doesn't hold an unboxed value, otherwise we generate code to check dynamically. */ if (!SAME_TYPE(SCHEME_TYPE(rand), scheme_local_type) @@ -1198,7 +1199,6 @@ static int generate_self_tail_call(Scheme_Object *rator, mz_jit_state *jitter, i || (extfl && (SCHEME_GET_LOCAL_TYPE(rand) == SCHEME_LOCAL_TYPE_EXTFLONUM))) { GC_CAN_IGNORE jit_insn *iref; int aoffset; - arg_tmp_offset += MZ_FPUSEL(extfl, 2*sizeof(double), sizeof(double)); aoffset = JIT_FRAME_FLOSTACK_OFFSET - arg_tmp_offset; if (i != num_rands - 1) mz_pushr_p(JIT_R0); @@ -1235,6 +1235,15 @@ static int generate_self_tail_call(Scheme_Object *rator, mz_jit_state *jitter, i /* Arguments already in place may also need to be boxed. */ arg_tmp_offset = jitter->self_restart_offset; + for (i = jitter->self_data->closure_size; i--; ) { + /* Skip over flonums unpacked from the closure. I think this never + happens, because I think that a self-call with already-in-place + flonum arguments will only happen when the closure is empty. */ + if (CLOSURE_CONTENT_IS_FLONUM(jitter->self_data, i)) + arg_tmp_offset -= sizeof(double); + else if (CLOSURE_CONTENT_IS_EXTFLONUM(jitter->self_data, i)) + arg_tmp_offset -= 2*sizeof(double); + } for (i = 0; i < args_already_in_place; i++) { if (CLOSURE_ARGUMENT_IS_FLONUM(jitter->self_data, i) || CLOSURE_ARGUMENT_IS_EXTFLONUM(jitter->self_data, i)) {