don't reorder some unsafe expressions that can depend on an effect
For example, an `unsafe-unbox` call should not be moved past the call to an unknown function that might change a box's content. Thanks to Sergey Pinaev for the report.
This commit is contained in:
parent
5a4391dd90
commit
88aa7fdeff
|
@ -1026,6 +1026,15 @@
|
|||
(set! x x))))
|
||||
#f)
|
||||
|
||||
;; Don't move a side-effecting experssion past an unsafe operation
|
||||
;; that observes effects:
|
||||
(test-comp '(lambda (b f)
|
||||
(let* ([x (f (lambda () b))])
|
||||
(cons (unsafe-unbox b) x)))
|
||||
'(lambda (b f)
|
||||
(cons (unsafe-unbox b) (f (lambda () b))))
|
||||
#f)
|
||||
|
||||
(test-comp '(module m racket/base
|
||||
(define (true) #t)
|
||||
(define no (if (true) (lambda (x) (cons x 'no)) display))
|
||||
|
|
|
@ -72,7 +72,8 @@ struct Optimize_Info
|
|||
/* Propagated up and down the chain: */
|
||||
int size;
|
||||
int vclock; /* virtual clock that ticks for a side effect, a branch,
|
||||
or a dependency on an earlier side-effect (such as a
|
||||
observation of a side effect (such as an unbox),
|
||||
or a dependency on an earlier side effect (such as a
|
||||
previous guard on an unsafe operation's argument);
|
||||
the clock is only compared between binding sites and
|
||||
uses, so we can rewind the clock at a join after an
|
||||
|
@ -2983,7 +2984,8 @@ static int is_nonmutating_nondependant_primitive(Scheme_Object *rator, int n)
|
|||
unsafe operation is defined */
|
||||
{
|
||||
if (SCHEME_PRIMP(rator)
|
||||
&& (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & (SCHEME_PRIM_IS_OMITABLE | SCHEME_PRIM_IS_OMITABLE_ALLOCATION))
|
||||
&& ((SCHEME_PRIM_PROC_OPT_FLAGS(rator) & (SCHEME_PRIM_IS_OMITABLE | SCHEME_PRIM_IS_OMITABLE_ALLOCATION))
|
||||
&& !(SCHEME_PRIM_PROC_OPT_FLAGS(rator) & (SCHEME_PRIM_IS_UNSAFE_OMITABLE)))
|
||||
&& (n >= ((Scheme_Primitive_Proc *)rator)->mina)
|
||||
&& (n <= ((Scheme_Primitive_Proc *)rator)->mu.maxa))
|
||||
return 1;
|
||||
|
|
|
@ -81,7 +81,8 @@
|
|||
#define SCHEME_PRIM_IS_NARY_INLINED (1 << 2)
|
||||
/* indicates that a primitive call can be dropped if it's result is not used;
|
||||
although the function never raises an exception, it should not be reordered
|
||||
past a test that might be a guard: */
|
||||
past a test that might be a guard or past an expression that might
|
||||
have a side effect: */
|
||||
#define SCHEME_PRIM_IS_UNSAFE_OMITABLE (1 << 3)
|
||||
/* indicates that a primitive call can be dropped if it's result is not used,
|
||||
because it has no side-effect and never raises an exception: */
|
||||
|
|
Loading…
Reference in New Issue
Block a user