From 6ce5e3d34ab1b9c8127061746ef4ccf7c236e432 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Wed, 16 Apr 2014 06:26:01 -0600 Subject: [PATCH] optimizer repair related to use-before-defined Don't optimize away a use-before-definition in an early compiler pass. (More specifically, adjust the meaning of a flag within an optimization helper function so that it works for decisions before the letrec-fixing pass.) --- .../racket-test/tests/racket/optimize.rktl | 11 ++++++++++ racket/src/racket/src/optimize.c | 22 ++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/pkgs/racket-pkgs/racket-test/tests/racket/optimize.rktl b/pkgs/racket-pkgs/racket-test/tests/racket/optimize.rktl index 403f17bb4a..9c30adff74 100644 --- a/pkgs/racket-pkgs/racket-test/tests/racket/optimize.rktl +++ b/pkgs/racket-pkgs/racket-test/tests/racket/optimize.rktl @@ -3415,6 +3415,17 @@ (eval (parameterize ([read-accept-compiled #t]) (read (open-input-bytes (get-output-bytes o)))))) +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Check that an unsufe opertion's argument is +;; not "optimized" away if it's a use of +;; a variable before definition: + +(err/rt-test (let () + (unsafe-fx+ x 1) + (define x 3) + x) + exn:fail:contract:variable?) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/racket/src/racket/src/optimize.c b/racket/src/racket/src/optimize.c index 91ef629d6c..ad6e74ff19 100644 --- a/racket/src/racket/src/optimize.c +++ b/racket/src/racket/src/optimize.c @@ -249,8 +249,10 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved, for "functional" bodies. If warn_info is supplied, complain when a mismatch is detected. If no_id is 1, then an identifier doesn't count as omittable, - unless the identifier is a consistent top-level; currently, this - is used to imply the absence of a continuation-mark impersonator. */ + unless the identifier is a consistent top-level; the no_id mode + is used by the "compile" phase before letrec checks are inserted + (where referencing a variable might raise an exception) and to + imply the absence of a continuation-mark impersonator. */ { Scheme_Type vtype; @@ -315,7 +317,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved, if (vtype == scheme_branch_type) { Scheme_Branch_Rec *b; b = (Scheme_Branch_Rec *)o; - return (scheme_omittable_expr(b->test, 1, fuel - 1, resolved, opt_info, warn_info, deeper_than, 0) + return (scheme_omittable_expr(b->test, 1, fuel - 1, resolved, opt_info, warn_info, deeper_than, no_id) && scheme_omittable_expr(b->tbranch, vals, fuel - 1, resolved, opt_info, warn_info, deeper_than, no_id) && scheme_omittable_expr(b->fbranch, vals, fuel - 1, resolved, opt_info, warn_info, deeper_than, no_id)); } @@ -345,7 +347,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved, && (lv2->position == 0) && scheme_omittable_expr(lv2->value, 1, fuel - 1, resolved, opt_info, warn_info, deeper_than + 1 + lv->count, - 0)) { + no_id)) { o = lv2->body; deeper_than += 1; } else @@ -362,7 +364,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved, if ((lh->count == 1) && (lh->num_clauses == 1)) { if (SAME_TYPE(SCHEME_TYPE(lh->body), scheme_compiled_let_value_type)) { Scheme_Compiled_Let_Value *lv = (Scheme_Compiled_Let_Value *)lh->body; - if (scheme_omittable_expr(lv->value, 1, fuel - 1, resolved, opt_info, warn_info, deeper_than + 1, 0)) { + if (scheme_omittable_expr(lv->value, 1, fuel - 1, resolved, opt_info, warn_info, deeper_than + 1, no_id)) { o = lv->body; deeper_than++; goto try_again; @@ -389,7 +391,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved, int i; for (i = app->num_args; i--; ) { if (!scheme_omittable_expr(app->args[i + 1], 1, fuel - 1, resolved, opt_info, warn_info, - deeper_than + (resolved ? app->num_args : 0), 0)) + deeper_than + (resolved ? app->num_args : 0), no_id)) return 0; } return 1; @@ -409,7 +411,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved, if (scheme_is_functional_primitive(app->rator, 1, vals) || scheme_is_struct_functional(app->rator, 1, opt_info, vals)) { if (scheme_omittable_expr(app->rand, 1, fuel - 1, resolved, opt_info, warn_info, - deeper_than + (resolved ? 1 : 0), 0)) + deeper_than + (resolved ? 1 : 0), no_id)) return 1; } else if (SCHEME_PRIMP(app->rator)) { if (!(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT) @@ -425,9 +427,9 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved, if (scheme_is_functional_primitive(app->rator, 2, vals) || scheme_is_struct_functional(app->rator, 2, opt_info, vals)) { if (scheme_omittable_expr(app->rand1, 1, fuel - 1, resolved, opt_info, warn_info, - deeper_than + (resolved ? 2 : 0), 0) + deeper_than + (resolved ? 2 : 0), no_id) && scheme_omittable_expr(app->rand2, 1, fuel - 1, resolved, opt_info, warn_info, - deeper_than + (resolved ? 2 : 0), 0)) + deeper_than + (resolved ? 2 : 0), no_id)) return 1; } else if (SCHEME_PRIMP(app->rator)) { if (!(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT)) { @@ -459,7 +461,7 @@ int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int resolved, 5); if (auto_e) { if (scheme_omittable_expr(auto_e, 1, fuel - 1, resolved, opt_info, warn_info, - deeper_than + auto_e_depth, 0)) + deeper_than + auto_e_depth, no_id)) return 1; } }