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:
parent
2f9431552e
commit
a6ec6a7e30
|
@ -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,6 +3669,8 @@ 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
|
||||||
|
@ -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) {
|
||||||
|
|
|
@ -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,6 +4544,7 @@ 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;
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
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;
|
b3->fbranch = b->fbranch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (post_bind)
|
||||||
|
sub_info = info;
|
||||||
|
else
|
||||||
sub_info = scheme_optimize_info_add_frame(info, 1, 0, 0);
|
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);
|
||||||
|
|
||||||
|
if (!post_bind) {
|
||||||
info->single_result = sub_info->single_result;
|
info->single_result = sub_info->single_result;
|
||||||
info->preserves_marks = sub_info->preserves_marks;
|
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,9 +3199,11 @@ 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) {
|
||||||
|
rhs_info = scheme_optimize_info_add_frame(info, 0, 0, 0);
|
||||||
|
if (for_inline)
|
||||||
body_info->inline_fuel >>= 1;
|
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);
|
||||||
|
@ -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;
|
||||||
|
@ -3967,19 +4008,25 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
|
||||||
/* 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);
|
|
||||||
for (j = i, k = 0; j >= 0; j--) {
|
|
||||||
if (lifts_frame_size != frame_size) {
|
if (lifts_frame_size != frame_size) {
|
||||||
/* We need to shift coordinates for any lifted[j] that is a
|
/* We need to shift coordinates for any lifted[j] that is a
|
||||||
converted procedure. */
|
converted procedure. */
|
||||||
|
for (j = i, k = 0; j >= 0; j--) {
|
||||||
shift_lift(lifted[j], frame_size, lifts_frame_size);
|
shift_lift(lifted[j], frame_size, lifts_frame_size);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (post_bind) {
|
||||||
|
linfo = scheme_resolve_info_extend(info, frame_size, 0, 0);
|
||||||
|
} else {
|
||||||
|
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);
|
n = (rev_bind_order ? (head->count - j - 1) : j);
|
||||||
if (skips[j])
|
if (skips[j])
|
||||||
scheme_resolve_info_add_mapping(linfo, n, -1, flonums[j], lifted[j]);
|
scheme_resolve_info_add_mapping(linfo, n, -1, flonums[j], lifted[j]);
|
||||||
else
|
else
|
||||||
scheme_resolve_info_add_mapping(linfo, n, k++, flonums[j], lifted[j]);
|
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]) {
|
||||||
|
@ -4154,6 +4201,11 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info)
|
||||||
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
|
||||||
and initialize lifts for recursive procedures. Generating lift information
|
and initialize lifts for recursive procedures. Generating lift information
|
||||||
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user