Make odd? and even? future-safe
This commit is contained in:
parent
323fc273ad
commit
05e0836b88
|
@ -31,6 +31,7 @@
|
||||||
jitcompile-event?
|
jitcompile-event?
|
||||||
synchronization-event?
|
synchronization-event?
|
||||||
runtime-synchronization-event?
|
runtime-synchronization-event?
|
||||||
|
runtime-block-event?
|
||||||
gc-event?
|
gc-event?
|
||||||
work-event?
|
work-event?
|
||||||
final-event?
|
final-event?
|
||||||
|
@ -183,8 +184,8 @@
|
||||||
(define (runtime-synchronization-event? evt)
|
(define (runtime-synchronization-event? evt)
|
||||||
(and (synchronization-event? evt) (= (process-id evt) RT-THREAD-ID)))
|
(and (synchronization-event? evt) (= (process-id evt) RT-THREAD-ID)))
|
||||||
|
|
||||||
;;runtime-block-evt? : (or event indexed-future-event future-event) -> bool
|
;;runtime-block-event? : (or event indexed-future-event future-event) -> bool
|
||||||
(define (runtime-block-evt? evt)
|
(define (runtime-block-event? evt)
|
||||||
(and (runtime-thread-evt? evt) (equal? (what evt) 'block)))
|
(and (runtime-thread-evt? evt) (equal? (what evt) 'block)))
|
||||||
|
|
||||||
;;runtime-sync-evt? : (or event indexed-future-event future-event) -> bool
|
;;runtime-sync-evt? : (or event indexed-future-event future-event) -> bool
|
||||||
|
@ -443,7 +444,7 @@
|
||||||
(define sync-hash (make-hash))
|
(define sync-hash (make-hash))
|
||||||
(define rt-hash (make-hash))
|
(define rt-hash (make-hash))
|
||||||
(for ([evt (in-list (filter runtime-synchronization-event? evts))])
|
(for ([evt (in-list (filter runtime-synchronization-event? evts))])
|
||||||
(define isblock (runtime-block-evt? evt))
|
(define isblock (runtime-block-event? evt))
|
||||||
(define ophash (if isblock block-hash sync-hash))
|
(define ophash (if isblock block-hash sync-hash))
|
||||||
(hash-update! ophash
|
(hash-update! ophash
|
||||||
(event-prim-name evt)
|
(event-prim-name evt)
|
||||||
|
|
|
@ -2,7 +2,14 @@
|
||||||
|
|
||||||
(require scheme/future
|
(require scheme/future
|
||||||
scheme/list
|
scheme/list
|
||||||
rackunit)
|
rackunit
|
||||||
|
(only-in future-visualizer/trace trace-futures)
|
||||||
|
(only-in future-visualizer/private/visualizer-data runtime-block-event?))
|
||||||
|
|
||||||
|
;Test whether a futures program hits any barricades
|
||||||
|
(define-syntax-rule (blocks? e ...)
|
||||||
|
(let ([log (trace-futures e ...)])
|
||||||
|
(> (length (filter runtime-block-event? log)) 0)))
|
||||||
|
|
||||||
#|Need to add expressions which raise exceptions inside a
|
#|Need to add expressions which raise exceptions inside a
|
||||||
future thunk which can be caught at the touch site
|
future thunk which can be caught at the touch site
|
||||||
|
@ -860,6 +867,62 @@ We should also test deep continuations.
|
||||||
(func (lambda () (list-ref l 50000)))))
|
(func (lambda () (list-ref l 50000)))))
|
||||||
(for/list ([i 10]) 50001)))
|
(for/list ([i 10]) 50001)))
|
||||||
|
|
||||||
|
;Basic odd?/even? tests
|
||||||
|
(let ([fa (func (λ ()
|
||||||
|
(and (odd? 33) (odd? 103.0))))]
|
||||||
|
[fb (func (λ ()
|
||||||
|
(or (odd? 32) (odd? 102.0))))]
|
||||||
|
[fc (func (λ ()
|
||||||
|
(and (even? 32) (even? 32.0))))]
|
||||||
|
[fd (func (λ ()
|
||||||
|
(or (even? 33) (even? 103.0))))])
|
||||||
|
(sleep 0.2)
|
||||||
|
(check-true (touch fa))
|
||||||
|
(check-false (touch fb))
|
||||||
|
(check-true (touch fc))
|
||||||
|
(check-false (touch fd)))
|
||||||
|
|
||||||
|
;Stress test for odd?/even?
|
||||||
|
(define N 1000)
|
||||||
|
(define MAX 1000)
|
||||||
|
(define (rnd x)
|
||||||
|
(case (random 3)
|
||||||
|
[(0)
|
||||||
|
(define n (random MAX))
|
||||||
|
(case (random 2)
|
||||||
|
[(0) (- 0 n)] ;negative
|
||||||
|
[(1) n])] ;positive
|
||||||
|
[(1) ;float
|
||||||
|
(+ (random MAX) .0)]
|
||||||
|
[(2) ;bignum
|
||||||
|
(expt 2 (+ (random MAX) 65))]))
|
||||||
|
|
||||||
|
(define (test-even-odd)
|
||||||
|
(define ns (build-list N rnd))
|
||||||
|
(define fs (for/list ([n (in-list ns)])
|
||||||
|
(func (λ ()
|
||||||
|
(or (odd? n) (even? n))))))
|
||||||
|
(map touch fs))
|
||||||
|
|
||||||
|
;Only test for non-blocking when actually running parallel futures
|
||||||
|
(when (eq? func future)
|
||||||
|
(check-false (blocks? (void (test-even-odd)))))
|
||||||
|
|
||||||
|
;Make sure we don't crash in error cases for odd?/even?
|
||||||
|
(let ([fa (func (λ ()
|
||||||
|
(even? 43.33)))]
|
||||||
|
[fb (func (λ ()
|
||||||
|
(odd? 7.0+3.2i)))]
|
||||||
|
[fc (func (λ ()
|
||||||
|
(even? -inf.0)))]
|
||||||
|
[fd (func (λ ()
|
||||||
|
(odd? +inf.0)))])
|
||||||
|
(sleep 0.2)
|
||||||
|
(check-exn exn:fail:contract? (λ () (touch fa)))
|
||||||
|
(check-exn exn:fail:contract? (λ () (touch fb)))
|
||||||
|
(check-exn exn:fail:contract? (λ () (touch fc)))
|
||||||
|
(check-exn exn:fail:contract? (λ () (touch fd))))
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
(run-tests future)
|
(run-tests future)
|
||||||
|
|
|
@ -2778,6 +2778,18 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts,
|
||||||
/* Fetch the future descriptor for this thread */
|
/* Fetch the future descriptor for this thread */
|
||||||
future = fts->thread->current_ft;
|
future = fts->thread->current_ft;
|
||||||
|
|
||||||
|
if (!for_overflow) {
|
||||||
|
/* Check if this prim in fact does have a
|
||||||
|
safe C version */
|
||||||
|
if (func == scheme_even_p || func == scheme_odd_p) {
|
||||||
|
prim_iS_s f = (prim_iS_s)func;
|
||||||
|
Scheme_Object *ret;
|
||||||
|
ret = f(future->arg_i0, future->arg_S1);
|
||||||
|
future->retval_s = ret;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check whether we are in slow-path trace mode */
|
/* Check whether we are in slow-path trace mode */
|
||||||
if (fts->is_runtime_thread) {
|
if (fts->is_runtime_thread) {
|
||||||
/* On runtime thread - must be slow-path tracing */
|
/* On runtime thread - must be slow-path tracing */
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "jit_ts_protos.h"
|
||||||
|
|
||||||
#ifdef USE_SINGLE_FLOATS_AS_DEFAULT
|
#ifdef USE_SINGLE_FLOATS_AS_DEFAULT
|
||||||
# ifndef MZ_USE_SINGLE_FLOATS
|
# ifndef MZ_USE_SINGLE_FLOATS
|
||||||
# undef USE_SINGLE_FLOATS_AS_DEFAULT
|
# undef USE_SINGLE_FLOATS_AS_DEFAULT
|
||||||
|
@ -68,7 +70,7 @@ static Scheme_Object *single_flonum_p (int argc, Scheme_Object *argv[]);
|
||||||
static Scheme_Object *real_to_single_flonum (int argc, Scheme_Object *argv[]);
|
static Scheme_Object *real_to_single_flonum (int argc, Scheme_Object *argv[]);
|
||||||
static Scheme_Object *real_to_double_flonum (int argc, Scheme_Object *argv[]);
|
static Scheme_Object *real_to_double_flonum (int argc, Scheme_Object *argv[]);
|
||||||
static Scheme_Object *exact_p (int argc, Scheme_Object *argv[]);
|
static Scheme_Object *exact_p (int argc, Scheme_Object *argv[]);
|
||||||
static Scheme_Object *even_p (int argc, Scheme_Object *argv[]);
|
Scheme_Object *scheme_even_p (int argc, Scheme_Object *argv[]);
|
||||||
static Scheme_Object *bitwise_or (int argc, Scheme_Object *argv[]);
|
static Scheme_Object *bitwise_or (int argc, Scheme_Object *argv[]);
|
||||||
static Scheme_Object *bitwise_xor (int argc, Scheme_Object *argv[]);
|
static Scheme_Object *bitwise_xor (int argc, Scheme_Object *argv[]);
|
||||||
static Scheme_Object *bitwise_not (int argc, Scheme_Object *argv[]);
|
static Scheme_Object *bitwise_not (int argc, Scheme_Object *argv[]);
|
||||||
|
@ -410,7 +412,7 @@ scheme_init_number (Scheme_Env *env)
|
||||||
SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED;
|
SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED;
|
||||||
scheme_add_global_constant("odd?", p, env);
|
scheme_add_global_constant("odd?", p, env);
|
||||||
|
|
||||||
p = scheme_make_folding_prim(even_p, "even?", 1, 1, 1);
|
p = scheme_make_folding_prim(scheme_even_p, "even?", 1, 1, 1);
|
||||||
SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED;
|
SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED;
|
||||||
scheme_add_global_constant("even?", p, env);
|
scheme_add_global_constant("even?", p, env);
|
||||||
|
|
||||||
|
@ -1486,9 +1488,16 @@ scheme_inexact_p (int argc, Scheme_Object *argv[])
|
||||||
return (v ? scheme_true : scheme_false);
|
return (v ? scheme_true : scheme_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scheme_Object *odd_p_error(int argc, Scheme_Object *argv[])
|
||||||
|
{
|
||||||
|
NEED_INTEGER(odd?);
|
||||||
|
|
||||||
|
ESCAPED_BEFORE_HERE;
|
||||||
|
}
|
||||||
|
|
||||||
Scheme_Object *
|
Scheme_Object *
|
||||||
scheme_odd_p (int argc, Scheme_Object *argv[])
|
scheme_odd_p (int argc, Scheme_Object *argv[])
|
||||||
|
XFORM_SKIP_PROC
|
||||||
{
|
{
|
||||||
Scheme_Object *v = argv[0];
|
Scheme_Object *v = argv[0];
|
||||||
|
|
||||||
|
@ -1504,13 +1513,23 @@ scheme_odd_p (int argc, Scheme_Object *argv[])
|
||||||
return (fmod(d, 2.0) == 0.0) ? scheme_false : scheme_true;
|
return (fmod(d, 2.0) == 0.0) ? scheme_false : scheme_true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NEED_INTEGER(odd?);
|
/* Otherwise, bail to the unsafe (error) path: */
|
||||||
|
if (scheme_use_rtcall)
|
||||||
|
return scheme_rtcall_iS_s("[odd?]", SIG_iS_s, odd_p_error, argc, argv);
|
||||||
|
else
|
||||||
|
return odd_p_error(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Scheme_Object *even_p_error(int argc, Scheme_Object *argv[])
|
||||||
|
{
|
||||||
|
NEED_INTEGER(even?);
|
||||||
|
|
||||||
ESCAPED_BEFORE_HERE;
|
ESCAPED_BEFORE_HERE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *
|
Scheme_Object *
|
||||||
even_p (int argc, Scheme_Object *argv[])
|
scheme_even_p (int argc, Scheme_Object *argv[])
|
||||||
|
XFORM_SKIP_PROC
|
||||||
{
|
{
|
||||||
Scheme_Object *v = argv[0];
|
Scheme_Object *v = argv[0];
|
||||||
|
|
||||||
|
@ -1526,9 +1545,11 @@ even_p (int argc, Scheme_Object *argv[])
|
||||||
return (fmod(d, 2.0) == 0.0) ? scheme_true : scheme_false;
|
return (fmod(d, 2.0) == 0.0) ? scheme_true : scheme_false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NEED_INTEGER(even?);
|
/* Otherwise, bail to the unsafe (error) path: */
|
||||||
|
if (scheme_use_rtcall)
|
||||||
ESCAPED_BEFORE_HERE;
|
return scheme_rtcall_iS_s("[even?]", SIG_iS_s, even_p_error, argc, argv);
|
||||||
|
else
|
||||||
|
return even_p_error(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object *bin_lcm (Scheme_Object *n1, Scheme_Object *n2);
|
static Scheme_Object *bin_lcm (Scheme_Object *n1, Scheme_Object *n2);
|
||||||
|
|
|
@ -2052,6 +2052,7 @@ int scheme_bin_lt_eq(const Scheme_Object *n1, const Scheme_Object *n2);
|
||||||
Scheme_Object *scheme_sub1(int argc, Scheme_Object *argv[]);
|
Scheme_Object *scheme_sub1(int argc, Scheme_Object *argv[]);
|
||||||
Scheme_Object *scheme_add1(int argc, Scheme_Object *argv[]);
|
Scheme_Object *scheme_add1(int argc, Scheme_Object *argv[]);
|
||||||
Scheme_Object *scheme_odd_p(int argc, Scheme_Object *argv[]);
|
Scheme_Object *scheme_odd_p(int argc, Scheme_Object *argv[]);
|
||||||
|
Scheme_Object *scheme_even_p(int argc, Scheme_Object *argv[]);
|
||||||
Scheme_Object *scheme_expt(int argc, Scheme_Object *argv[]);
|
Scheme_Object *scheme_expt(int argc, Scheme_Object *argv[]);
|
||||||
Scheme_Object *scheme_modulo(int argc, Scheme_Object *argv[]);
|
Scheme_Object *scheme_modulo(int argc, Scheme_Object *argv[]);
|
||||||
Scheme_Object *scheme_sqrt(int argc, Scheme_Object *argv[]);
|
Scheme_Object *scheme_sqrt(int argc, Scheme_Object *argv[]);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user