change bytecode optimizer's representation of `let'

- represent RHSes as before allocating stack positions
   for bindings, instead of after, which makes certain
   transformations simpler; this does not effect the
   final bytecode form that's is saved in a ".zo"
This commit is contained in:
Matthew Flatt 2010-08-11 08:57:15 -06:00
parent 2f9431552e
commit a6ec6a7e30
4 changed files with 155 additions and 60 deletions

View File

@ -3513,7 +3513,7 @@ Scheme_Object *scheme_optimize_reverse(Optimize_Info *info, int pos, int unless_
while (1) { while (1) {
if (pos < info->new_frame) if (pos < info->new_frame)
break; break;
pos -= info->new_frame; pos -= info->new_frame;
delta += info->original_frame; delta += info->original_frame;
info = info->next; info = info->next;
} }
@ -3626,6 +3626,8 @@ static Scheme_Object *do_optimize_info_lookup(Optimize_Info *info, int pos, int
n = SCHEME_VEC_ELS(p)[1]; n = SCHEME_VEC_ELS(p)[1];
if (SCHEME_INT_VAL(n) == pos) { if (SCHEME_INT_VAL(n) == pos) {
n = SCHEME_VEC_ELS(p)[2]; n = SCHEME_VEC_ELS(p)[2];
if (info->flags & SCHEME_POST_BIND_FRAME)
delta += info->new_frame;
if (SCHEME_RPAIRP(n)) { if (SCHEME_RPAIRP(n)) {
/* This was a letrec-bound identifier that may or may not be ready, /* This was a letrec-bound identifier that may or may not be ready,
but which wasn't replaced with more information. */ but which wasn't replaced with more information. */
@ -3644,9 +3646,8 @@ static Scheme_Object *do_optimize_info_lookup(Optimize_Info *info, int pos, int
if (SAME_TYPE(SCHEME_TYPE(n), scheme_compiled_unclosed_procedure_type)) { if (SAME_TYPE(SCHEME_TYPE(n), scheme_compiled_unclosed_procedure_type)) {
if (!closure_offset) if (!closure_offset)
break; break;
else { else
*closure_offset = delta; *closure_offset = delta;
}
} else if (SAME_TYPE(SCHEME_TYPE(n), scheme_compiled_toplevel_type)) { } else if (SAME_TYPE(SCHEME_TYPE(n), scheme_compiled_toplevel_type)) {
/* Ok */ /* Ok */
} else if (closure_offset) { } else if (closure_offset) {
@ -3668,7 +3669,9 @@ static Scheme_Object *do_optimize_info_lookup(Optimize_Info *info, int pos, int
pos = SCHEME_LOCAL_POS(n); pos = SCHEME_LOCAL_POS(n);
if (info->flags & SCHEME_LAMBDA_FRAME) if (info->flags & SCHEME_LAMBDA_FRAME)
j--; /* because it will get re-added on recur */ j--; /* because it will get re-added on recur */
else if (info->flags & SCHEME_POST_BIND_FRAME)
info = info->next; /* bindings are relative to next frame */
/* Marks local as used; we don't expect to get back /* Marks local as used; we don't expect to get back
a value, because chaining would normally happen on the a value, because chaining would normally happen on the
propagate-call side. Chaining there also means that we propagate-call side. Chaining there also means that we
@ -3677,6 +3680,7 @@ static Scheme_Object *do_optimize_info_lookup(Optimize_Info *info, int pos, int
if (!*single_use) if (!*single_use)
single_use = NULL; single_use = NULL;
} }
n = do_optimize_info_lookup(info, pos, j, NULL, single_use, NULL, 0, context, potential_size); n = do_optimize_info_lookup(info, pos, j, NULL, single_use, NULL, 0, context, potential_size);
if (!n) { if (!n) {

View File

@ -2671,7 +2671,7 @@ Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int a
if (nested_count) { if (nested_count) {
sub_info = scheme_optimize_info_add_frame(info, nested_count, nested_count, 0); sub_info = scheme_optimize_info_add_frame(info, nested_count, nested_count, 0);
sub_info->vclock++; sub_info->vclock++;
/* We could propagate bound values in sub_info , but relevant inlining /* We could propagate bound values in sub_info, but relevant inlining
and propagatation has probably already happened when the rator was and propagatation has probably already happened when the rator was
optimized. */ optimized. */
} else } else
@ -3316,8 +3316,7 @@ static Scheme_Object *check_unbox_rotation(Scheme_Object *_app, Scheme_Object *r
lv->iso.so.type = scheme_compiled_let_value_type; lv->iso.so.type = scheme_compiled_let_value_type;
lv->count = 1; lv->count = 1;
lv->position = 0; lv->position = 0;
new_rand = scheme_optimize_shift(rand, 1, 0); lv->value = rand;
lv->value = new_rand;
flags = (int *)scheme_malloc_atomic(sizeof(int)); flags = (int *)scheme_malloc_atomic(sizeof(int));
flags[0] = (SCHEME_WAS_USED | (1 << SCHEME_USE_COUNT_SHIFT)); flags[0] = (SCHEME_WAS_USED | (1 << SCHEME_USE_COUNT_SHIFT));
@ -4545,7 +4544,8 @@ Scheme_Object *scheme_optimize_clone(int dup_ok, Scheme_Object *expr, Optimize_I
Scheme_Object *body; Scheme_Object *body;
Scheme_Compiled_Let_Value *lv, *lv2, *prev = NULL; Scheme_Compiled_Let_Value *lv, *lv2, *prev = NULL;
int i, *flags, sz; int i, *flags, sz;
int post_bind = !(SCHEME_LET_FLAGS(head) & (SCHEME_LET_RECURSIVE | SCHEME_LET_STAR));
head2 = MALLOC_ONE_TAGGED(Scheme_Let_Header); head2 = MALLOC_ONE_TAGGED(Scheme_Let_Header);
head2->iso.so.type = scheme_compiled_let_void_type; head2->iso.so.type = scheme_compiled_let_void_type;
head2->count = head->count; head2->count = head->count;
@ -4568,7 +4568,8 @@ Scheme_Object *scheme_optimize_clone(int dup_ok, Scheme_Object *expr, Optimize_I
lv2->position = lv->position; lv2->position = lv->position;
lv2->flags = flags; lv2->flags = flags;
expr = scheme_optimize_clone(dup_ok, lv->value, info, delta, closure_depth + head->count); expr = scheme_optimize_clone(dup_ok, lv->value, info, delta,
closure_depth + (post_bind ? 0 : head->count));
if (!expr) return NULL; if (!expr) return NULL;
lv2->value = expr; lv2->value = expr;
@ -4747,13 +4748,14 @@ Scheme_Object *scheme_optimize_shift(Scheme_Object *expr, int delta, int after_d
Scheme_Object *body; Scheme_Object *body;
Scheme_Compiled_Let_Value *lv = NULL; Scheme_Compiled_Let_Value *lv = NULL;
int i; int i;
int post_bind = !(SCHEME_LET_FLAGS(head) & (SCHEME_LET_RECURSIVE | SCHEME_LET_STAR));
/* Build let-value change: */ /* Build let-value change: */
body = head->body; body = head->body;
for (i = head->num_clauses; i--; ) { for (i = head->num_clauses; i--; ) {
lv = (Scheme_Compiled_Let_Value *)body; lv = (Scheme_Compiled_Let_Value *)body;
expr = scheme_optimize_shift(lv->value, delta, after_depth + head->count); expr = scheme_optimize_shift(lv->value, delta, after_depth + (post_bind ? 0 : head->count));
lv->value = expr; lv->value = expr;
body = lv->body; body = lv->body;

View File

@ -1073,6 +1073,46 @@ typedef struct {
struct Resolve_Prefix *prefix; struct Resolve_Prefix *prefix;
} Scheme_Compilation_Top; } Scheme_Compilation_Top;
/* A `let', `let*', or `letrec' form is compiled to the intermediate
format (used during the optimization pass) as a Scheme_Let_Header
with a chain of Scheme_Compiled_Let_Value records as its body,
where there's one Scheme_Compiled_Let_Value for each binding
clause. A `let*' is normally expanded to nested `let's before
compilation, but the intermediate format also supposrts `let*',
which is useful mostly for converting a simple enough `letrec' form
into `let*.
The body of the `let...' form is the body of the innermost
Scheme_Compiled_Let_Value record. Obviously, all N bindings of a
`let...' form are pushed onto the virtual stack for the body, but
the situation is more complex for the binding right-hand
sides. There are three cases:
* Plain `let': no bindings are pushed, yet. (This is in contrast
to the convention for the final bytecode format, where space for
the binding is allocated before the right-hand side is
evaluated.)
* `letrec': all bindings are pushed; the first clause is pushed
first, etc.
* `let*' can be like `letrec', but also can have the bindings in
reverse order; that is, all bindings are pushed before any
right-hand side, but the last binding may be pushed first
instead of last.
*/
typedef struct Scheme_Let_Header {
Scheme_Inclhash_Object iso; /* keyex used for recursive */
mzshort count; /* total number of bindings */
mzshort num_clauses; /* number of binding clauses */
Scheme_Object *body;
} Scheme_Let_Header;
#define SCHEME_LET_FLAGS(lh) MZ_OPT_HASH_KEY(&lh->iso)
#define SCHEME_LET_RECURSIVE 0x1
#define SCHEME_LET_STAR 0x2
typedef struct Scheme_Compiled_Let_Value { typedef struct Scheme_Compiled_Let_Value {
Scheme_Inclhash_Object iso; /* keyex used for set-starting */ Scheme_Inclhash_Object iso; /* keyex used for set-starting */
mzshort count; mzshort count;
@ -1086,17 +1126,6 @@ typedef struct Scheme_Compiled_Let_Value {
#define SCHEME_CLV_NO_GROUP_LATER_USES 0x1 #define SCHEME_CLV_NO_GROUP_LATER_USES 0x1
#define SCHEME_CLV_NO_GROUP_USES 0x2 #define SCHEME_CLV_NO_GROUP_USES 0x2
typedef struct Scheme_Let_Header {
Scheme_Inclhash_Object iso; /* keyex used for recursive */
mzshort count;
mzshort num_clauses;
Scheme_Object *body;
} Scheme_Let_Header;
#define SCHEME_LET_FLAGS(lh) MZ_OPT_HASH_KEY(&lh->iso)
#define SCHEME_LET_RECURSIVE 0x1
#define SCHEME_LET_STAR 0x2
typedef struct { typedef struct {
Scheme_Object so; Scheme_Object so;
Scheme_Object *key; Scheme_Object *key;
@ -2613,6 +2642,7 @@ int scheme_env_min_use_below(Scheme_Comp_Env *frame, int pos);
#define SCHEME_FOR_INTDEF 256 #define SCHEME_FOR_INTDEF 256
#define SCHEME_CAPTURE_LIFTED 512 #define SCHEME_CAPTURE_LIFTED 512
#define SCHEME_INTDEF_SHADOW 1024 #define SCHEME_INTDEF_SHADOW 1024
#define SCHEME_POST_BIND_FRAME 2048
/* Flags used with scheme_static_distance */ /* Flags used with scheme_static_distance */
#define SCHEME_ELIM_CONST 1 #define SCHEME_ELIM_CONST 1

View File

@ -3055,12 +3055,13 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
int i, j, pos, is_rec, not_simply_let_star = 0, undiscourage, split_shift, skip_opts = 0; int i, j, pos, is_rec, not_simply_let_star = 0, undiscourage, split_shift, skip_opts = 0;
int size_before_opt, did_set_value; int size_before_opt, did_set_value;
int remove_last_one = 0, inline_fuel, rev_bind_order; int remove_last_one = 0, inline_fuel, rev_bind_order;
int post_bind = !(SCHEME_LET_FLAGS(head) & (SCHEME_LET_RECURSIVE | SCHEME_LET_STAR));
# define pos_EARLIER(a, b) (rev_bind_order ? ((a) > (b)) : ((a) < (b))) # define pos_EARLIER(a, b) (rev_bind_order ? ((a) > (b)) : ((a) < (b)))
if (context & OPT_CONTEXT_BOOLEAN) { if (context & OPT_CONTEXT_BOOLEAN) {
/* Special case: (let ([x M]) (if x x N)), where x is not in N, /* Special case: (let ([x M]) (if x x N)), where x is not in N,
to (if M #t #f), since we're in a test position. */ to (if M #t N), since we're in a test position. */
if (!(SCHEME_LET_FLAGS(head) & SCHEME_LET_RECURSIVE) && (head->count == 1) && (head->num_clauses == 1)) { if (!(SCHEME_LET_FLAGS(head) & SCHEME_LET_RECURSIVE) && (head->count == 1) && (head->num_clauses == 1)) {
clv = (Scheme_Compiled_Let_Value *)head->body; clv = (Scheme_Compiled_Let_Value *)head->body;
if (SAME_TYPE(SCHEME_TYPE(clv->body), scheme_branch_type) if (SAME_TYPE(SCHEME_TYPE(clv->body), scheme_branch_type)
@ -3077,16 +3078,28 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
b3->so.type = scheme_branch_type; b3->so.type = scheme_branch_type;
b3->test = clv->value; b3->test = clv->value;
b3->tbranch = scheme_true; b3->tbranch = scheme_true;
b3->fbranch = b->fbranch; if (post_bind) {
/* still need a `let' around N: */
b3->fbranch = (Scheme_Object *)head;
clv->value = scheme_false;
clv->flags[0] = 0; /* variable now unused */
clv->body = b->fbranch;
} else {
b3->fbranch = b->fbranch;
}
sub_info = scheme_optimize_info_add_frame(info, 1, 0, 0); if (post_bind)
sub_info = info;
else
sub_info = scheme_optimize_info_add_frame(info, 1, 0, 0);
form = scheme_optimize_expr((Scheme_Object *)b3, sub_info, context); form = scheme_optimize_expr((Scheme_Object *)b3, sub_info, context);
info->single_result = sub_info->single_result; if (!post_bind) {
info->preserves_marks = sub_info->preserves_marks; info->single_result = sub_info->single_result;
info->preserves_marks = sub_info->preserves_marks;
scheme_optimize_info_done(sub_info); scheme_optimize_info_done(sub_info);
}
return form; return form;
} }
@ -3102,8 +3115,8 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
if (SAME_TYPE(SCHEME_TYPE(clv->body), scheme_local_type) if (SAME_TYPE(SCHEME_TYPE(clv->body), scheme_local_type)
&& (((Scheme_Local *)clv->body)->position == 0)) { && (((Scheme_Local *)clv->body)->position == 0)) {
if (worth_lifting(clv->value)) { if (worth_lifting(clv->value)) {
if (for_inline) { if (post_bind) {
/* Just drop the inline-introduced let */ /* Just drop the let */
return scheme_optimize_expr(clv->value, info, context); return scheme_optimize_expr(clv->value, info, context);
} else { } else {
info = scheme_optimize_info_add_frame(info, 1, 0, 0); info = scheme_optimize_info_add_frame(info, 1, 0, 0);
@ -3119,6 +3132,29 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
is_rec = (SCHEME_LET_FLAGS(head) & SCHEME_LET_RECURSIVE); is_rec = (SCHEME_LET_FLAGS(head) & SCHEME_LET_RECURSIVE);
#if 0
if (!is_rec) {
/* (let ([x (let ([y M]) N)]) P) => (let ([y M]) (let ([x N]) P)) */
if (head->count == 1) {
clv = (Scheme_Compiled_Let_Value *)head->body; /* ([x ...]) */
if (SAME_TYPE(SCHEME_TYPE(clv->value), scheme_compiled_let_void_type)) {
Scheme_Let_Header *lh = (Scheme_Let_Header *)clv->value; /* (let ([y ...]) ...) */
if (!(SCHEME_LET_FLAGS(lh) & SCHEME_LET_RECURSIVE)
&& (lh->count == 1)) {
value = ((Scheme_Compiled_Let_Value *)lh->body)->body; /* = N */
((Scheme_Compiled_Let_Value *)lh->body)->body = (Scheme_Object *)head;
clv->value = value;
head = lh;
form = (Scheme_Obejct *)head;
orig_info = info;
info = scheme_optimize_info_add_frame(info, 1, 0, 0);
}
}
}
}
#endif
split_shift = 0; split_shift = 0;
if (is_rec) { if (is_rec) {
/* Check whether we should break a prefix out into its own /* Check whether we should break a prefix out into its own
@ -3163,10 +3199,12 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
} }
} }
body_info = scheme_optimize_info_add_frame(info, head->count, head->count, 0); body_info = scheme_optimize_info_add_frame(info, head->count, head->count,
if (for_inline) { post_bind ? SCHEME_POST_BIND_FRAME : 0);
rhs_info = scheme_optimize_info_add_frame(info, 0, head->count, 0); if (post_bind) {
body_info->inline_fuel >>= 1; rhs_info = scheme_optimize_info_add_frame(info, 0, 0, 0);
if (for_inline)
body_info->inline_fuel >>= 1;
} else if (split_shift) } else if (split_shift)
rhs_info = scheme_optimize_info_add_frame(body_info, split_shift, 0, 0); rhs_info = scheme_optimize_info_add_frame(body_info, split_shift, 0, 0);
else else
@ -3416,9 +3454,10 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
value = NULL; value = NULL;
else { else {
/* Convert value back to a pre-optimized local coordinates. /* Convert value back to a pre-optimized local coordinates.
This must be done with respect to body_info, not Unless post_bind, this must be done with respect to
rhs_info, because we attach the value to body_info: */ body_info, not rhs_info, because we attach the value to
value = scheme_optimize_reverse(body_info, vpos, 1); body_info: */
value = scheme_optimize_reverse(post_bind ? rhs_info : body_info, vpos, 1);
/* Double-check that the value is ready, because we might be /* Double-check that the value is ready, because we might be
nested in the RHS of a `letrec': */ nested in the RHS of a `letrec': */
@ -3449,7 +3488,7 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
if (cnt == 1) { if (cnt == 1) {
/* used only once; we may be able to shift the expression to the use /* used only once; we may be able to shift the expression to the use
site, instead of binding to a temporary */ site, instead of binding to a temporary */
last_once_used = scheme_make_once_used(value, pos, body_info->vclock, last_once_used); last_once_used = scheme_make_once_used(value, pos, rhs_info->vclock, last_once_used);
if (!first_once_used) first_once_used = last_once_used; if (!first_once_used) first_once_used = last_once_used;
scheme_optimize_propagate(body_info, pos, (Scheme_Object *)last_once_used, 1); scheme_optimize_propagate(body_info, pos, (Scheme_Object *)last_once_used, 1);
} }
@ -3604,7 +3643,7 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
body = pre_body->body; body = pre_body->body;
} }
if (for_inline) { if (post_bind) {
body_info->size = rhs_info->size; body_info->size = rhs_info->size;
body_info->vclock = rhs_info->vclock; body_info->vclock = rhs_info->vclock;
} }
@ -3715,6 +3754,7 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
value = body; value = body;
extract_depth = head->count; extract_depth = head->count;
rhs_info = body_info; rhs_info = body_info;
post_bind = 0;
} }
} }
} }
@ -3724,7 +3764,7 @@ scheme_optimize_lets(Scheme_Object *form, Optimize_Info *info, int for_inline, i
value = scheme_optimize_clone(1, value, rhs_info, 0, 0); value = scheme_optimize_clone(1, value, rhs_info, 0, 0);
if (value) { if (value) {
sub_info = scheme_optimize_info_add_frame(info, extract_depth, 0, 0); sub_info = scheme_optimize_info_add_frame(info, post_bind ? 0 : extract_depth, 0, 0);
sub_info->inline_fuel = 0; sub_info->inline_fuel = 0;
value = scheme_optimize_expr(value, sub_info, context); value = scheme_optimize_expr(value, sub_info, context);
info->single_result = sub_info->single_result; info->single_result = sub_info->single_result;
@ -3830,7 +3870,7 @@ static Scheme_Object *drop_zero_value_return(Scheme_Object *expr)
Scheme_Object * Scheme_Object *
scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info) scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
{ {
Resolve_Info *linfo, *val_linfo; Resolve_Info *linfo, *val_linfo = NULL;
Scheme_Let_Header *head = (Scheme_Let_Header *)form; Scheme_Let_Header *head = (Scheme_Let_Header *)form;
Scheme_Compiled_Let_Value *clv, *pre_body; Scheme_Compiled_Let_Value *clv, *pre_body;
Scheme_Let_Value *lv, *last = NULL; Scheme_Let_Value *lv, *last = NULL;
@ -3844,6 +3884,7 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
int max_let_depth = 0; int max_let_depth = 0;
int resolve_phase, num_skips; int resolve_phase, num_skips;
Scheme_Object **lifted_recs; Scheme_Object **lifted_recs;
int post_bind = !(SCHEME_LET_FLAGS(head) & (SCHEME_LET_RECURSIVE | SCHEME_LET_STAR));
/* Find body: */ /* Find body: */
body = head->body; body = head->body;
@ -3966,20 +4007,26 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
/* First `i+1' bindings now exist "at runtime", except those skipped. */ /* First `i+1' bindings now exist "at runtime", except those skipped. */
/* The mapping is complicated because we now push in the order of /* The mapping is complicated because we now push in the order of
the variables, but it may have been compiled using the inverse order. */ the variables, but it may have been compiled using the inverse order. */
frame_size = i + 1 - skip_count; frame_size = i + 1 - skip_count;
linfo = scheme_resolve_info_extend(info, frame_size, head->count, i + 1); if (lifts_frame_size != frame_size) {
for (j = i, k = 0; j >= 0; j--) { /* We need to shift coordinates for any lifted[j] that is a
if (lifts_frame_size != frame_size) { converted procedure. */
/* We need to shift coordinates for any lifted[j] that is a for (j = i, k = 0; j >= 0; j--) {
converted procedure. */
shift_lift(lifted[j], frame_size, lifts_frame_size); shift_lift(lifted[j], frame_size, lifts_frame_size);
} }
n = (rev_bind_order ? (head->count - j - 1) : j); }
if (skips[j]) if (post_bind) {
scheme_resolve_info_add_mapping(linfo, n, -1, flonums[j], lifted[j]); linfo = scheme_resolve_info_extend(info, frame_size, 0, 0);
else } else {
scheme_resolve_info_add_mapping(linfo, n, k++, flonums[j], lifted[j]); linfo = scheme_resolve_info_extend(info, frame_size, head->count, i + 1);
} for (j = i, k = 0; j >= 0; j--) {
n = (rev_bind_order ? (head->count - j - 1) : j);
if (skips[j])
scheme_resolve_info_add_mapping(linfo, n, -1, flonums[j], lifted[j]);
else
scheme_resolve_info_add_mapping(linfo, n, k++, flonums[j], lifted[j]);
}
}
lifts_frame_size = frame_size; lifts_frame_size = frame_size;
if (skips[i]) { if (skips[i]) {
@ -4153,6 +4200,11 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
linfo = scheme_resolve_info_extend(info, head->count - num_skips, head->count, head->count); linfo = scheme_resolve_info_extend(info, head->count - num_skips, head->count, head->count);
lifted_recs = NULL; lifted_recs = NULL;
} }
if (post_bind)
val_linfo = scheme_resolve_info_extend(info, head->count - num_skips, 0, 0);
else
val_linfo = linfo;
/* Build mapping of compile-time indices to run-time indices, shuffling /* Build mapping of compile-time indices to run-time indices, shuffling
letrecs to fall together in the shallowest part. Also determine letrecs to fall together in the shallowest part. Also determine
@ -4231,7 +4283,7 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
old_lift = lifted_recs[rpos]; old_lift = lifted_recs[rpos];
old_convert_count = get_convert_arg_count(old_lift); old_convert_count = get_convert_arg_count(old_lift);
lift = scheme_resolve_closure_compilation(clv->value, linfo, 1, 1, 1, lift = scheme_resolve_closure_compilation(clv->value, val_linfo, 1, 1, 1,
(resolve_phase ? NULL : old_lift)); (resolve_phase ? NULL : old_lift));
if (is_closed_reference(lift) if (is_closed_reference(lift)
@ -4275,7 +4327,7 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
Scheme_Object *lift; Scheme_Object *lift;
lift = lifted_recs[rpos]; lift = lifted_recs[rpos];
if (is_closed_reference(lift)) { if (is_closed_reference(lift)) {
(void)scheme_resolve_closure_compilation(clv->value, linfo, 1, 1, 0, lift); (void)scheme_resolve_closure_compilation(clv->value, val_linfo, 1, 1, 0, lift);
/* lift is the final result; this result might be /* lift is the final result; this result might be
referenced in the body of closures already, or in referenced in the body of closures already, or in
not-yet-closed functions. If no one uses the result not-yet-closed functions. If no one uses the result
@ -4283,7 +4335,7 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
GCed. */ GCed. */
clv->value = NULL; /* inidicates that there's nothing more to do with the expr */ clv->value = NULL; /* inidicates that there's nothing more to do with the expr */
} else { } else {
lift = scheme_resolve_closure_compilation(clv->value, linfo, 1, 1, 2, NULL); lift = scheme_resolve_closure_compilation(clv->value, val_linfo, 1, 1, 2, NULL);
/* need to resolve one more time for the body of the lifted function */ /* need to resolve one more time for the body of the lifted function */
} }
scheme_resolve_info_adjust_mapping(linfo, opos, rpos, 0, lift); scheme_resolve_info_adjust_mapping(linfo, opos, rpos, 0, lift);
@ -4298,7 +4350,6 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
} }
extra_alloc = 0; extra_alloc = 0;
val_linfo = linfo;
if (num_rec_procs) { if (num_rec_procs) {
if (!lifted_recs) { if (!lifted_recs) {
@ -4498,6 +4549,9 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
if (info->max_let_depth < linfo->max_let_depth + head->count - num_skips + extra_alloc) if (info->max_let_depth < linfo->max_let_depth + head->count - num_skips + extra_alloc)
info->max_let_depth = linfo->max_let_depth + head->count - num_skips + extra_alloc; info->max_let_depth = linfo->max_let_depth + head->count - num_skips + extra_alloc;
if (val_linfo)
if (info->max_let_depth < val_linfo->max_let_depth + head->count - num_skips + extra_alloc)
info->max_let_depth = val_linfo->max_let_depth + head->count - num_skips + extra_alloc;
return first; return first;
} }
@ -4509,13 +4563,14 @@ gen_let_syntax (Scheme_Object *form, Scheme_Comp_Env *origenv, char *formname,
{ {
Scheme_Object *bindings, *l, *binding, *name, **names, *forms, *defname; Scheme_Object *bindings, *l, *binding, *name, **names, *forms, *defname;
int num_clauses, num_bindings, i, j, k, m, pre_k; int num_clauses, num_bindings, i, j, k, m, pre_k;
Scheme_Comp_Env *frame, *env; Scheme_Comp_Env *frame, *env, *rhs_env;
Scheme_Compile_Info *recs; Scheme_Compile_Info *recs;
Scheme_Object *first = NULL; Scheme_Object *first = NULL;
Scheme_Compiled_Let_Value *last = NULL, *lv; Scheme_Compiled_Let_Value *last = NULL, *lv;
DupCheckRecord r; DupCheckRecord r;
int rec_env_already = rec[drec].env_already; int rec_env_already = rec[drec].env_already;
int rev_bind_order = recursive; int rev_bind_order = recursive;
int post_bind = !recursive && !star;
i = scheme_stx_proper_list_length(form); i = scheme_stx_proper_list_length(form);
if (i < 3) if (i < 3)
@ -4593,6 +4648,10 @@ gen_let_syntax (Scheme_Object *form, Scheme_Comp_Env *origenv, char *formname,
frame_already = frame; frame_already = frame;
} }
env = frame; env = frame;
if (post_bind)
rhs_env = scheme_no_defines(origenv);
else
rhs_env = env;
recs = MALLOC_N_RT(Scheme_Compile_Info, (num_clauses + 1)); recs = MALLOC_N_RT(Scheme_Compile_Info, (num_clauses + 1));
@ -4691,7 +4750,7 @@ gen_let_syntax (Scheme_Object *form, Scheme_Comp_Env *origenv, char *formname,
rhs = SCHEME_STX_CDR(binding); rhs = SCHEME_STX_CDR(binding);
rhs = SCHEME_STX_CAR(rhs); rhs = SCHEME_STX_CAR(rhs);
rhs = scheme_add_env_renames(rhs, env, origenv); rhs = scheme_add_env_renames(rhs, env, origenv);
ce = scheme_compile_expr(rhs, env, recs, i); ce = scheme_compile_expr(rhs, rhs_env, recs, i);
lv->value = ce; lv->value = ce;
} else { } else {
Scheme_Object *rhs; Scheme_Object *rhs;