Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -: 0:Source:../../../racket/src/optimize.c
- -: 0:Graph:optimize.gcno
- -: 0:Data:optimize.gcda
- -: 0:Runs:87
- -: 0:Programs:1
- -: 1:/*
- -: 2: Racket
- -: 3: Copyright (c) 2004-2017 PLT Design Inc.
- -: 4: Copyright (c) 1995-2001 Matthew Flatt
- -: 5:
- -: 6: This library is free software; you can redistribute it and/or
- -: 7: modify it under the terms of the GNU Library General Public
- -: 8: License as published by the Free Software Foundation; either
- -: 9: version 2 of the License, or (at your option) any later version.
- -: 10:
- -: 11: This library is distributed in the hope that it will be useful,
- -: 12: but WITHOUT ANY WARRANTY; without even the implied warranty of
- -: 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- -: 14: Library General Public License for more details.
- -: 15:
- -: 16: You should have received a copy of the GNU Library General Public
- -: 17: License along with this library; if not, write to the Free
- -: 18: Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- -: 19: Boston, MA 02110-1301 USA.
- -: 20:
- -: 21: libscheme
- -: 22: Copyright (c) 1994 Brent Benson
- -: 23: All rights reserved.
- -: 24:*/
- -: 25:
- -: 26:/* This file implements bytecode optimization.
- -: 27:
- -: 28: See "eval.c" for an overview of compilation passes. */
- -: 29:
- -: 30:#include "schpriv.h"
- -: 31:#include "schrunst.h"
- -: 32:#include "schmach.h"
- -: 33:
- -: 34:/* Controls for inlining algorithm: */
- -: 35:#define OPT_ESTIMATE_FUTURE_SIZES 1
- -: 36:#define OPT_DISCOURAGE_EARLY_INLINE 1
- -: 37:#define OPT_LIMIT_FUNCTION_RESIZE 0
- -: 38:#define OPT_BRANCH_ADDS_NO_SIZE 1
- -: 39:#define OPT_DELAY_GROUP_PROPAGATE 0
- -: 40:#define OPT_PRE_OPTIMIZE_FOR_CROSS_MODULE(size_override) (size_override)
- -: 41:
- -: 42:#define MAX_PROC_INLINE_SIZE 256
- -: 43:#define CROSS_MODULE_INLINE_SIZE 8
- -: 44:
- -: 45:/* Various kinds of fuel ensure that
- -: 46: the compiler doesn't go into a loop
- -: 47: or take non-linear time */
- -: 48:#define INITIAL_INLINING_FUEL 32
- -: 49:#define INITIAL_FLATTENING_FUEL 16
- -: 50:
- -: 51:/* Clasification for predicates.
- -: 52: Each one implies the smaller. */
- -: 53:#define RLV_IS_RELEVANT 1 /* The predicate is remembered by the optimizer */
- -: 54:#define RLV_EQV_TESTEABLE 2 /* (equal? x <pred>) can be replaced by (eqv? x <pred>) */
- -: 55:#define RLV_EQ_TESTEABLE 3 /* (equal? x <pred>) can be replaced by (eq? x <pred>) */
- -: 56:#define RLV_SINGLETON 4 /* Recognizes a single value */
- -: 57:
- -: 58:struct Optimize_Info
- -: 59:{
- -: 60: MZTAG_IF_REQUIRED
- -: 61: short flags;
- -: 62: struct Optimize_Info *next;
- -: 63: int original_frame, new_frame;
- -: 64: Scheme_Object *consts;
- -: 65: Comp_Prefix *cp;
- -: 66: int init_kclock;
- -: 67:
- -: 68: /* Compilation context, used for unresolving for cross-module inlining: */
- -: 69: Scheme_Env *env;
- -: 70: Scheme_Object *insp;
- -: 71:
- -: 72: /* Propagated up and down the chain: */
- -: 73: int size;
- -: 74: int vclock; /* virtual clock that ticks for a side effect, a branch,
- -: 75: observation of a side effect (such as an unbox),
- -: 76: or a dependency on an earlier side effect (such as a
- -: 77: previous guard on an unsafe operation's argument);
- -: 78: the clock is only compared between binding sites and
- -: 79: uses, so we can rewind the clock at a join after an
- -: 80: increment that models a branch (if the branch is not
- -: 81: taken or doesn't increment the clock) */
- -: 82: int aclock; /* virtual clock that ticks for allocation without side effects,
- -: 83: for constraining the reordering of operations that might
- -: 84: capture a continuation */
- -: 85: int kclock; /* virtual clock that ticks for a potential continuation capture,
- -: 86: for constraining the movement of allocation operations */
- -: 87: int sclock; /* virtual clock that ticks when space consumption is potentially observed */
- -: 88: int psize;
- -: 89: short inline_fuel, flatten_fuel;
- -: 90: char letrec_not_twice, enforce_const, use_psize, has_nonleaf;
- -: 91: Scheme_Hash_Table *top_level_consts;
- -: 92:
- -: 93: int maybe_values_argument; /* triggers an approximation for clock increments */
- -: 94:
- -: 95: /* Set by expression optimization: */
- -: 96: int single_result, preserves_marks; /* negative means "tentative", due to fixpoint in progress */
- -: 97: int escapes; /* flag to signal that the expression always escapes. When escapes is 1, it's assumed
- -: 98: that single_result and preserves_marks are also 1, and that it's not necessary to
- -: 99: use optimize_ignored before including the expression. */
- -: 100:
- -: 101: int lambda_depth; /* counts nesting depth under `lambda`s */
- -: 102: int used_toplevel; /* tracks whether any non-local variables or syntax-object literals are used */
- -: 103:
- -: 104: Scheme_Hash_Table *uses; /* used variables, accumulated for closures */
- -: 105:
- -: 106: Scheme_IR_Local *transitive_use_var; /* set when optimizing a letrec-bound procedure
- -: 107: to record variables that were added to `uses` */
- -: 108:
- -: 109: Scheme_Object *context; /* for logging */
- -: 110: Scheme_Logger *logger;
- -: 111: Scheme_Hash_Tree *types; /* maps position (from this frame) to predicate */
- -: 112: int no_types; /* disables use of type info */
- -: 113:};
- -: 114:
- -: 115:typedef struct Optimize_Info_Sequence {
- -: 116: int init_flatten_fuel, min_flatten_fuel;
- -: 117:} Optimize_Info_Sequence;
- -: 118:
- -: 119:static void merge_lambda_arg_types(Scheme_Lambda *lam1, Scheme_Lambda *lam2);
- -: 120:static void check_lambda_arg_types_registered(Scheme_Lambda *lam, int app_count);
- -: 121:static int lambda_body_size_plus_info(Scheme_Lambda *lam, int check_assign,
- -: 122: Optimize_Info *info, int *is_leaf);
- -: 123:static int lambda_has_top_level(Scheme_Lambda *lam);
- -: 124:
- -: 125:static Scheme_Object *make_sequence_2(Scheme_Object *a, Scheme_Object *b);
- -: 126:
- -: 127:static int wants_local_type_arguments(Scheme_Object *rator, int argpos);
- -: 128:
- -: 129:static void add_types_for_f_branch(Scheme_Object *t, Optimize_Info *info, int fuel);
- -: 130:
- -: 131:static void register_use(Scheme_IR_Local *var, Optimize_Info *info);
- -: 132:static Scheme_Object *optimize_info_lookup(Scheme_Object *var);
- -: 133:static Scheme_Object *optimize_info_propagate_local(Scheme_Object *var);
- -: 134:static void optimize_info_used_top(Optimize_Info *info);
- -: 135:static Scheme_Object *optimize_get_predicate(Optimize_Info *info, Scheme_Object *var, int ignore_no_types);
- -: 136:static void add_type(Optimize_Info *info, Scheme_Object *var, Scheme_Object *pred);
- -: 137:static void merge_types(Optimize_Info *src_info, Optimize_Info *info, Scheme_Hash_Tree *skip_vars);
- -: 138:
- -: 139:static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info);
- -: 140:static Scheme_Object *do_expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info,
- -: 141: int *_involves_k_cross, int fuel,
- -: 142: Scheme_Hash_Tree *ignore_vars);
- -: 143:static int produces_local_type(Scheme_Object *rator, int argc);
- -: 144:static int optimize_any_uses(Optimize_Info *info, Scheme_IR_Let_Value *at_irlv, int n);
- -: 145:static void optimize_uses_of_mutable_imply_early_alloc(Scheme_IR_Let_Value *at_irlv, int n);
- -: 146:static void propagate_used_variables(Optimize_Info *info);
- -: 147:static int env_uses_toplevel(Optimize_Info *frame);
- -: 148:static Scheme_IR_Local *clone_variable(Scheme_IR_Local *var);
- -: 149:static void increment_use_count(Scheme_IR_Local *var, int as_rator);
- -: 150:
- -: 151:static Optimize_Info *optimize_info_add_frame(Optimize_Info *info, int orig, int current, int flags);
- -: 152:static void optimize_info_done(Optimize_Info *info, Optimize_Info *parent);
- -: 153:
- -: 154:static void register_transitive_uses(Scheme_IR_Local *var, Optimize_Info *info);
- -: 155:
- -: 156:static void optimize_info_seq_init(Optimize_Info *info, Optimize_Info_Sequence *info_seq);
- -: 157:static void optimize_info_seq_step(Optimize_Info *info, Optimize_Info_Sequence *info_seq);
- -: 158:static void optimize_info_seq_done(Optimize_Info *info, Optimize_Info_Sequence *info_seq);
- -: 159:
- -: 160:static Scheme_Object *estimate_closure_size(Scheme_Object *e);
- -: 161:static Scheme_Object *no_potential_size(Scheme_Object *value);
- -: 162:
- -: 163:static Scheme_Object *optimize_lets(Scheme_Object *form, Optimize_Info *info, int context);
- -: 164:
- -: 165:static Scheme_Object *optimize_clone(int single_use, Scheme_Object *obj, Optimize_Info *info, Scheme_Hash_Tree *var_map, int as_rator);
- -: 166:
- -: 167:XFORM_NONGCING static int relevant_predicate(Scheme_Object *pred);
- -: 168:XFORM_NONGCING static int predicate_implies(Scheme_Object *pred1, Scheme_Object *pred2);
- -: 169:XFORM_NONGCING static int predicate_implies_not(Scheme_Object *pred1, Scheme_Object *pred2);
- -: 170:static int single_valued_expression(Scheme_Object *expr, int fuel);
- -: 171:static int single_valued_noncm_expression(Scheme_Object *expr, int fuel);
- -: 172:static int noncm_expression(Scheme_Object *expr, int fuel);
- -: 173:static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info,
- -: 174: int expected_vals, int maybe_omittable,
- -: 175: int fuel);
- -: 176:static Scheme_Object *equivalent_exprs(Scheme_Object *a, Scheme_Object *b,
- -: 177: Optimize_Info *a_info, Optimize_Info *b_info, int context);
- -: 178:static int movable_expression(Scheme_Object *expr, Optimize_Info *info,
- -: 179: int cross_lambda, int cross_k, int cross_s,
- -: 180: int check_space, int fuel);
- -: 181:Scheme_Object *optimize_apply_values(Scheme_Object *f, Scheme_Object *e,
- -: 182: Optimize_Info *info,
- -: 183: int e_single_result,
- -: 184: int context);
- -: 185:
- -: 186:#define SCHEME_LAMBDAP(vals_expr) (SAME_TYPE(SCHEME_TYPE(vals_expr), scheme_ir_lambda_type) \
- -: 187: || SAME_TYPE(SCHEME_TYPE(vals_expr), scheme_case_lambda_sequence_type))
- -: 188:
- -: 189:#define SCHEME_WILL_BE_LAMBDAP(v) SAME_TYPE(SCHEME_TYPE(v), scheme_will_be_lambda_type)
- -: 190:#define SCHEME_WILL_BE_LAMBDA_SIZE(v) SCHEME_PINT_VAL(v)
- -: 191:#define SCHEME_WILL_BE_LAMBDA(v) SCHEME_IPTR_VAL(v)
- -: 192:
- -: 193:static int lambda_body_size(Scheme_Object *o, int less_args);
- -: 194:
- -: 195:typedef struct Scheme_Once_Used {
- -: 196: Scheme_Object so;
- -: 197: Scheme_Object *expr;
- -: 198: Scheme_IR_Local *var;
- -: 199: int vclock; /* record clocks at binding site */
- -: 200: int aclock;
- -: 201: int kclock;
- -: 202: int sclock;
- -: 203: int spans_k; /* potentially captures a continuation */
- -: 204: int moved;
- -: 205:} Scheme_Once_Used;
- -: 206:
- -: 207:static Scheme_Once_Used *make_once_used(Scheme_Object *val, Scheme_IR_Local *var,
- -: 208: int vclock, int aclock, int kclock, int sclock, int spans_k);
- -: 209:
- -: 210:static ROSYM Scheme_Hash_Tree *empty_eq_hash_tree;
- -: 211:
- -: 212:#ifdef MZ_PRECISE_GC
- -: 213:static void register_traversers(void);
- -: 214:#endif
- -: 215:
- 87: 216:void scheme_init_optimize()
- -: 217:{
- 87: 218: REGISTER_SO(empty_eq_hash_tree);
- 87: 219: empty_eq_hash_tree = scheme_make_hash_tree(SCHEME_hashtr_eq);
- -: 220:
- -: 221:#ifdef MZ_PRECISE_GC
- -: 222: register_traversers();
- -: 223:#endif
- 87: 224:}
- -: 225:
- -: 226:/*========================================================================*/
- -: 227:/* logging */
- -: 228:/*========================================================================*/
- -: 229:
- 613115: 230:static void note_match(int actual, int expected, Optimize_Info *warn_info)
- -: 231:{
- 613115: 232: if (!warn_info || (expected == -1))
- 450085: 233: return;
- -: 234:
- 163030: 235: if (actual != expected) {
- 2: 236: scheme_log(warn_info->logger,
- -: 237: SCHEME_LOG_WARNING,
- -: 238: 0,
- -: 239: "warning%s: %d values produced when %d expected",
- -: 240: scheme_optimize_context_to_string(warn_info->context),
- -: 241: actual, expected);
- -: 242: }
- -: 243:}
- -: 244:
- 156394: 245:char *scheme_optimize_context_to_string(Scheme_Object *context)
- -: 246:/* Convert a context to a string that is suitable for use in logging */
- -: 247:{
- 156394: 248: if (context) {
- -: 249: Scheme_Object *mod, *func;
- -: 250: const char *ctx, *prefix, *mctx, *mprefix;
- -: 251: char *all;
- -: 252: int clen, plen, mclen, mplen, len;
- -: 253:
- 141192: 254: if (SCHEME_PAIRP(context)) {
- 135716: 255: func = SCHEME_CAR(context);
- 135716: 256: mod = SCHEME_CDR(context);
- 5476: 257: } else if (SAME_TYPE(SCHEME_TYPE(context), scheme_module_type)) {
- 3009: 258: func = scheme_false;
- 3009: 259: mod = context;
- -: 260: } else {
- 2467: 261: func = context;
- 2467: 262: mod = scheme_false;
- -: 263: }
- -: 264:
- 279374: 265: if (SAME_TYPE(SCHEME_TYPE(func), scheme_ir_lambda_type)) {
- -: 266: Scheme_Object *name;
- -: 267:
- 138183: 268: name = ((Scheme_Lambda *)func)->name;
- 138183: 269: if (name) {
- 271305: 270: if (SCHEME_VECTORP(name)) {
- -: 271: Scheme_Object *port;
- 134335: 272: int print_width = 1024;
- -: 273: intptr_t plen;
- -: 274:
- 134335: 275: port = scheme_make_byte_string_output_port();
- -: 276:
- 134335: 277: scheme_write_proc_context(port, print_width,
- -: 278: SCHEME_VEC_ELS(name)[0],
- -: 279: SCHEME_VEC_ELS(name)[1], SCHEME_VEC_ELS(name)[2],
- -: 280: SCHEME_VEC_ELS(name)[3], SCHEME_VEC_ELS(name)[4],
- 134335: 281: SCHEME_TRUEP(SCHEME_VEC_ELS(name)[6]));
- -: 282:
- 134334: 283: ctx = scheme_get_sized_byte_string_output(port, &plen);
- 134334: 284: prefix = " in: ";
- -: 285: } else {
- 2636: 286: ctx = scheme_get_proc_name(func, &len, 0);
- 2636: 287: prefix = " in: ";
- -: 288: }
- -: 289: } else {
- 1212: 290: ctx = "";
- 1212: 291: prefix = "";
- -: 292: }
- -: 293: } else {
- 3009: 294: ctx = "";
- 3009: 295: prefix = "";
- -: 296: }
- -: 297:
- 141191: 298: if (SAME_TYPE(SCHEME_TYPE(mod), scheme_module_type)) {
- 137724: 299: mctx = scheme_display_to_string(((Scheme_Module *)mod)->modsrc, NULL);
- 137724: 300: mprefix = " in module: ";
- -: 301: } else {
- 3467: 302: mctx = "";
- 3467: 303: mprefix = "";
- -: 304: }
- -: 305:
- 141191: 306: clen = strlen(ctx);
- 141191: 307: plen = strlen(prefix);
- 141191: 308: mclen = strlen(mctx);
- 141191: 309: mplen = strlen(mprefix);
- -: 310:
- 141191: 311: if (!clen && !mclen)
- 1138: 312: return "";
- -: 313:
- 140053: 314: all = scheme_malloc_atomic(clen + plen + mclen + mplen + 1);
- 140053: 315: memcpy(all, prefix, plen);
- 140053: 316: memcpy(all + plen, ctx, clen);
- 140053: 317: memcpy(all + plen + clen, mprefix, mplen);
- 140053: 318: memcpy(all + plen + clen + mplen, mctx, mclen);
- 140053: 319: all[clen + plen + mclen + mplen] = 0;
- 140053: 320: return all;
- -: 321: } else
- 15202: 322: return "";
- -: 323:}
- -: 324:
- 110: 325:char *scheme_optimize_info_context(Optimize_Info *info)
- -: 326:{
- 110: 327: return scheme_optimize_context_to_string(info->context);
- -: 328:}
- -: 329:
- 110: 330:Scheme_Logger *scheme_optimize_info_logger(Optimize_Info *info)
- -: 331:{
- 110: 332: return info->logger;
- -: 333:}
- -: 334:
- -: 335:/*========================================================================*/
- -: 336:/* utils */
- -: 337:/*========================================================================*/
- -: 338:
- 457768: 339:static void set_optimize_mode(Scheme_IR_Local *var)
- -: 340:{
- -: 341: MZ_ASSERT(SAME_TYPE(var->so.type, scheme_ir_local_type));
- 457768: 342: memset(&var->optimize, 0, sizeof(var->optimize));
- 457768: 343: var->mode = SCHEME_VAR_MODE_OPTIMIZE;
- 457768: 344:}
- -: 345:
- -: 346:#define SCHEME_PRIM_IS_UNSAFE_NONMUTATING (SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL | SCHEME_PRIM_IS_UNSAFE_OMITABLE)
- -: 347:
- 1072149: 348:int scheme_is_functional_nonfailing_primitive(Scheme_Object *rator, int num_args, int expected_vals)
- -: 349:/* A call to a functional, non-failing primitive (i.e., it accepts any argument)
- -: 350: can be discarded if its results are ignored.
- -: 351: Return 2 => true, and results are a constant when arguments are constants. */
- -: 352:{
- 1072149: 353: if (SCHEME_PRIMP(rator)
- 865826: 354: && (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & (SCHEME_PRIM_IS_OMITABLE_ANY | SCHEME_PRIM_IS_UNSAFE_NONMUTATING))
- 447193: 355: && (num_args >= ((Scheme_Primitive_Proc *)rator)->mina)
- 447181: 356: && (num_args <= ((Scheme_Primitive_Proc *)rator)->mu.maxa)
- 447149: 357: && ((expected_vals < 0)
- 430279: 358: || ((expected_vals == 1) && !(SCHEME_PRIM_PROC_FLAGS(rator) & SCHEME_PRIM_IS_MULTI_RESULT))
- 2835: 359: || (SAME_OBJ(scheme_values_proc, rator)
- 2835: 360: && (expected_vals == num_args)))) {
- 447093: 361: if (SAME_OBJ(scheme_values_proc, rator))
- 15922: 362: return 2;
- 431171: 363: return 1;
- -: 364: } else
- 625056: 365: return 0;
- -: 366:}
- -: 367:
- 1460720: 368:static Scheme_Object *get_struct_proc_shape(Scheme_Object *rator, Optimize_Info *info, int prop_ok)
- -: 369:/* Determines whether `rator` is known to be a struct accessor, etc. */
- -: 370:{
- -: 371: Scheme_Object *c;
- -: 372:
- 1460720: 373: if (info
- 1092069: 374: && (info->top_level_consts || info->cp->inline_variants)
- 940944: 375: && SAME_TYPE(SCHEME_TYPE(rator), scheme_ir_toplevel_type)) {
- -: 376: int pos;
- 180377: 377: pos = SCHEME_TOPLEVEL_POS(rator);
- 180377: 378: c = NULL;
- 180377: 379: if (info->top_level_consts)
- 109925: 380: c = scheme_hash_get(info->top_level_consts, scheme_make_integer(pos));
- 180377: 381: if (!c && info->cp->inline_variants)
- 143579: 382: c = scheme_hash_get(info->cp->inline_variants, scheme_make_integer(pos));
- 180377: 383: if (c && (SAME_TYPE(SCHEME_TYPE(c), scheme_struct_proc_shape_type)
- 16343: 384: || (prop_ok && SAME_TYPE(SCHEME_TYPE(c), scheme_struct_prop_proc_shape_type)))) {
- 27038: 385: return c;
- -: 386: }
- -: 387: }
- -: 388:
- 1433682: 389: return NULL;
- -: 390:}
- -: 391:
- 235500: 392:int scheme_is_struct_functional(Scheme_Object *rator, int num_args, Optimize_Info *info, int vals)
- -: 393:/* Determines whether `rator` is a functional, non-failing struct operation */
- -: 394:{
- -: 395: Scheme_Object *c;
- -: 396:
- 235500: 397: if ((vals == 1) || (vals == -1)) {
- 233081: 398: c = get_struct_proc_shape(rator, info, 1);
- 233081: 399: if (c) {
- 2350: 400: if (SAME_TYPE(SCHEME_TYPE(c), scheme_struct_proc_shape_type)) {
- 1469: 401: int mode = (SCHEME_PROC_SHAPE_MODE(c) & STRUCT_PROC_SHAPE_MASK);
- 1469: 402: int field_count = (SCHEME_PROC_SHAPE_MODE(c) >> STRUCT_PROC_SHAPE_SHIFT);
- 1469: 403: if (((num_args == 1) && (mode == STRUCT_PROC_SHAPE_PRED))
- 1137: 404: || ((num_args == field_count) && (mode == STRUCT_PROC_SHAPE_CONSTR))) {
- 802: 405: return 1;
- -: 406: }
- 214: 407: } else if (SAME_TYPE(SCHEME_TYPE(c), scheme_struct_prop_proc_shape_type)) {
- 214: 408: if ((SCHEME_PROP_PROC_SHAPE_MODE(c) == STRUCT_PROP_PROC_SHAPE_PRED)
- 191: 409: && (num_args == 1))
- 191: 410: return 1;
- -: 411: }
- -: 412: }
- -: 413: }
- -: 414:
- 234507: 415: return 0;
- -: 416:}
- -: 417:
- 6344114: 418:static Scheme_Object *extract_specialized_proc(Scheme_Object *le, Scheme_Object *default_val)
- -: 419:/* Look through `(procedure-specialize <e>)` to get `<e>` */
- -: 420:{
- 6344114: 421: if (SAME_TYPE(SCHEME_TYPE(le), scheme_application2_type)) {
- 108183: 422: Scheme_App2_Rec *app = (Scheme_App2_Rec *)le;
- 108183: 423: if (SAME_OBJ(app->rator, scheme_procedure_specialize_proc)) {
- 8: 424: if (SCHEME_PROCP(app->rand) || SCHEME_LAMBDAP(app->rand))
- 8: 425: return app->rand;
- -: 426: }
- -: 427: }
- -: 428:
- 6344106: 429: return default_val;
- -: 430:}
- -: 431:
- 1567418: 432:int scheme_omittable_expr(Scheme_Object *o, int vals, int fuel, int flags,
- -: 433: Optimize_Info *opt_info, Optimize_Info *warn_info)
- -: 434: /* Checks whether the bytecode `o` returns `vals` values with no
- -: 435: side-effects and without pushing and using continuation marks.
- -: 436: A -1 for `vals` means that any return count is ok.
- -: 437: Also used with fully resolved expression by `module' to check
- -: 438: for "functional" bodies, in which case `flags` includes
- -: 439: `OMITTABLE_RESOLVED`.
- -: 440: The `opt_info` argument is used only to access module-level
- -: 441: information, not local bindings.
- -: 442: If `warn_info` is supplied, complain when a mismatch is detected.
- -: 443: We rely on the letrec-check pass to avoid omitting early references
- -: 444: to letrec-bound variables, but `flags` can include `OMITTABLE_KEEP_VARS`
- -: 445: to keep all variable references.
- -: 446: If flags includes `OMITTABLE_KEEP_MUTABLE_VARS`, then references
- -: 447: to mutable variables are kept, which allows this function to be
- -: 448: a conservative approximation for "reorderable". */
- -: 449:{
- -: 450: Scheme_Type vtype;
- -: 451:
- -: 452: /* FIXME: can overflow the stack */
- -: 453:
- -: 454: try_again:
- -: 455:
- 1567418: 456: vtype = SCHEME_TYPE(o);
- -: 457:
- 1567418: 458: if ((vtype > _scheme_ir_values_types_)
- 1337038: 459: || ((vtype == scheme_ir_local_type)
- 105278: 460: && !(flags & OMITTABLE_KEEP_VARS)
- 98744: 461: && (!(flags & OMITTABLE_KEEP_MUTABLE_VARS)
- #####: 462: || !SCHEME_VAR(o)->mutated))
- 1238294: 463: || ((vtype == scheme_local_type)
- 491260: 464: && !(flags & OMITTABLE_KEEP_VARS)
- 491260: 465: && !(SCHEME_GET_LOCAL_FLAGS(o) == SCHEME_LOCAL_CLEAR_ON_READ))
- 1215363: 466: || ((vtype == scheme_local_unbox_type)
- 780: 467: && !(flags & (OMITTABLE_KEEP_VARS | OMITTABLE_KEEP_MUTABLE_VARS))
- 780: 468: && !(SCHEME_GET_LOCAL_FLAGS(o) == SCHEME_LOCAL_CLEAR_ON_READ))
- 1214699: 469: || (vtype == scheme_lambda_type)
- 1179779: 470: || (vtype == scheme_ir_lambda_type)
- 1168403: 471: || (vtype == scheme_inline_variant_type)
- 1168403: 472: || (vtype == scheme_case_lambda_sequence_type)
- 1167777: 473: || (vtype == scheme_quote_syntax_type)
- 1167765: 474: || (vtype == scheme_varref_form_type)
- 1167402: 475: || (vtype == scheme_ir_quote_syntax_type)) {
- 415223: 476: note_match(1, vals, warn_info);
- 415223: 477: return ((vals == 1) || (vals < 0));
- -: 478: }
- -: 479:
- 1152195: 480: if (vtype == scheme_toplevel_type) {
- 48625: 481: note_match(1, vals, warn_info);
- 48625: 482: if (!(flags & OMITTABLE_KEEP_VARS) && (flags & OMITTABLE_RESOLVED) && ((vals == 1) || (vals < 0))) {
- 48625: 483: if (SCHEME_TOPLEVEL_FLAGS(o) & SCHEME_TOPLEVEL_FLAGS_MASK)
- 46404: 484: return 1;
- -: 485: else
- 2221: 486: return 0;
- -: 487: }
- -: 488: }
- -: 489:
- 1103570: 490: if (vtype == scheme_ir_toplevel_type) {
- 7549: 491: note_match(1, vals, warn_info);
- 7549: 492: if ((vals == 1) || (vals < 0)) {
- 7549: 493: if (!(flags & OMITTABLE_KEEP_VARS)
- 4202: 494: && ((SCHEME_TOPLEVEL_FLAGS(o) & SCHEME_TOPLEVEL_FLAGS_MASK) >= SCHEME_TOPLEVEL_READY))
- 4000: 495: return 1;
- 3549: 496: else if ((SCHEME_TOPLEVEL_FLAGS(o) & SCHEME_TOPLEVEL_FLAGS_MASK) >= SCHEME_TOPLEVEL_FIXED)
- 1863: 497: return 1;
- -: 498: else
- 1686: 499: return 0;
- -: 500: }
- -: 501: }
- -: 502:
- 1096021: 503: if (vtype == scheme_branch_type) {
- -: 504: Scheme_Branch_Rec *b;
- 90867: 505: b = (Scheme_Branch_Rec *)o;
- 181734: 506: return (scheme_omittable_expr(b->test, 1, fuel - 1, flags, opt_info, warn_info)
- 37641: 507: && scheme_omittable_expr(b->tbranch, vals, fuel - 1, flags, opt_info, warn_info)
- 108437: 508: && scheme_omittable_expr(b->fbranch, vals, fuel - 1, flags, opt_info, warn_info));
- -: 509: }
- -: 510:
- 1005154: 511: if (vtype == scheme_let_one_type) {
- 20642: 512: Scheme_Let_One *lo = (Scheme_Let_One *)o;
- 41284: 513: return (scheme_omittable_expr(lo->value, 1, fuel - 1, flags, opt_info, warn_info)
- 20642: 514: && scheme_omittable_expr(lo->body, vals, fuel - 1, flags, opt_info, warn_info));
- -: 515: }
- -: 516:
- 984512: 517: if (vtype == scheme_let_void_type) {
- 474: 518: Scheme_Let_Void *lv = (Scheme_Let_Void *)o;
- -: 519: /* recognize (letrec ([x <omittable>]) ...): */
- -: 520: MZ_ASSERT(flags & OMITTABLE_RESOLVED);
- 832: 521: if (SAME_TYPE(SCHEME_TYPE(lv->body), scheme_let_value_type)) {
- 358: 522: Scheme_Let_Value *lv2 = (Scheme_Let_Value *)lv->body;
- 358: 523: if ((lv2->count == 1)
- 8: 524: && (lv2->position == 0)
- 8: 525: && scheme_omittable_expr(lv2->value, 1, fuel - 1, flags, opt_info, warn_info)) {
- #####: 526: o = lv2->body;
- -: 527: } else
- 358: 528: o = lv->body;
- -: 529: } else
- 116: 530: o = lv->body;
- 474: 531: goto try_again;
- -: 532: }
- -: 533:
- 984038: 534: if (vtype == scheme_ir_let_header_type) {
- -: 535: /* recognize another (let ([x <omittable>]) ...) pattern: */
- 11742: 536: Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)o;
- -: 537: int i;
- -: 538: MZ_ASSERT(!(flags & OMITTABLE_RESOLVED));
- 11742: 539: o = lh->body;
- 17614: 540: for (i = 0; i < lh->num_clauses; i++) {
- 12436: 541: Scheme_IR_Let_Value *lv = (Scheme_IR_Let_Value *)o;
- 12436: 542: if (!scheme_omittable_expr(lv->value, lv->count, fuel - 1, flags, opt_info, warn_info))
- 6564: 543: return 0;
- 5872: 544: o = lv->body;
- -: 545: }
- 5178: 546: goto try_again;
- -: 547: }
- -: 548:
- 972296: 549: if (vtype == scheme_letrec_type) {
- -: 550: MZ_ASSERT(flags & OMITTABLE_RESOLVED);
- 116: 551: o = ((Scheme_Letrec *)o)->body;
- 116: 552: goto try_again;
- -: 553: }
- -: 554:
- 972180: 555: if (vtype == scheme_application_type) {
- 66505: 556: Scheme_App_Rec *app = (Scheme_App_Rec *)o;
- -: 557:
- 66505: 558: if ((app->num_args >= 4) && (app->num_args <= 11)
- 16863: 559: && SAME_OBJ(scheme_make_struct_type_proc, app->args[0])) {
- 1271: 560: note_match(5, vals, warn_info);
- -: 561: }
- -: 562:
- 66505: 563: if (scheme_is_functional_nonfailing_primitive(app->args[0], app->num_args, vals)
- 62378: 564: || scheme_is_struct_functional(app->args[0], app->num_args, opt_info, vals)
- 62052: 565: || ((SCHEME_APPN_FLAGS(app) & APPN_FLAG_OMITTABLE) && !(flags & OMITTABLE_IGNORE_APPN_OMIT))) {
- -: 566: int i;
- 21109: 567: for (i = app->num_args; i--; ) {
- 13128: 568: if (!scheme_omittable_expr(app->args[i + 1], 1, fuel - 1, flags, opt_info, warn_info))
- 1159: 569: return 0;
- -: 570: }
- 3411: 571: return 1;
- 61935: 572: } else if (SCHEME_PRIMP(app->args[0])) {
- 49977: 573: if (!(SCHEME_PRIM_PROC_FLAGS(app->args[0]) & SCHEME_PRIM_IS_MULTI_RESULT)) {
- 44572: 574: note_match(1, vals, warn_info);
- 5405: 575: } else if (SAME_OBJ(scheme_values_proc, app->args[0])) {
- #####: 576: note_match(app->num_args, vals, warn_info);
- -: 577: }
- -: 578: }
- -: 579:
- 61935: 580: if (!SAME_OBJ(scheme_make_struct_type_proc, app->args[0]))
- 60664: 581: return 0;
- -: 582: }
- -: 583:
- 906946: 584: if (vtype == scheme_application2_type) {
- 205675: 585: Scheme_App2_Rec *app = (Scheme_App2_Rec *)o;
- 205675: 586: if (scheme_is_functional_nonfailing_primitive(app->rator, 1, vals)
- 120039: 587: || scheme_is_struct_functional(app->rator, 1, opt_info, vals)
- 119508: 588: || ((SCHEME_APPN_FLAGS(app) & APPN_FLAG_OMITTABLE) && !(flags & OMITTABLE_IGNORE_APPN_OMIT))) {
- 110271: 589: if (scheme_omittable_expr(app->rand, 1, fuel - 1, flags, opt_info, warn_info))
- 62855: 590: return 1;
- 119112: 591: } else if (SAME_OBJ(app->rator, scheme_make_vector_proc)
- 65: 592: && (vals == 1 || vals == -1)
- 65: 593: && (SCHEME_INTP(app->rand)
- 10: 594: && (SCHEME_INT_VAL(app->rand) >= 0))
- 2: 595: && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand))) {
- 2: 596: return 1;
- 119110: 597: } else if (SAME_OBJ(app->rator, scheme_procedure_specialize_proc)) {
- 2: 598: if ((vals == 1 || vals == -1) && extract_specialized_proc(o, NULL))
- 2: 599: return 1;
- 119108: 600: } else if (SCHEME_PRIMP(app->rator)) {
- 65647: 601: if (!(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT)
- 1542: 602: || SAME_OBJ(scheme_values_proc, app->rator)) {
- 64105: 603: note_match(1, vals, warn_info);
- -: 604: }
- -: 605: }
- -: 606:
- 142816: 607: if (!SAME_OBJ(scheme_make_struct_type_property_proc, app->rator))
- 142724: 608: return 0;
- -: 609: }
- -: 610:
- 701363: 611: if (vtype == scheme_application3_type) {
- 148418: 612: Scheme_App3_Rec *app = (Scheme_App3_Rec *)o;
- 148418: 613: if (scheme_is_functional_nonfailing_primitive(app->rator, 2, vals)
- 53083: 614: || scheme_is_struct_functional(app->rator, 2, opt_info, vals)
- 52947: 615: || ((SCHEME_APPN_FLAGS(app) & APPN_FLAG_OMITTABLE) && !(flags & OMITTABLE_IGNORE_APPN_OMIT))) {
- 118023: 616: if (scheme_omittable_expr(app->rand1, 1, fuel - 1, flags, opt_info, warn_info)
- 86031: 617: && scheme_omittable_expr(app->rand2, 1, fuel - 1, flags, opt_info, warn_info))
- 73847: 618: return 1;
- 52483: 619: } else if (SAME_OBJ(app->rator, scheme_make_vector_proc)
- 92: 620: && (vals == 1 || vals == -1)
- 92: 621: && (SCHEME_INTP(app->rand1)
- 12: 622: && (SCHEME_INT_VAL(app->rand1) >= 0)
- 12: 623: && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand1)))
- 12: 624: && scheme_omittable_expr(app->rand2, 1, fuel - 1, flags, opt_info, warn_info)) {
- 8: 625: return 1;
- 52475: 626: } else if (SCHEME_PRIMP(app->rator)) {
- 32381: 627: if (!(SCHEME_PRIM_PROC_FLAGS(app->rator) & SCHEME_PRIM_IS_MULTI_RESULT)) {
- 31722: 628: note_match(1, vals, warn_info);
- 659: 629: } else if (SAME_OBJ(scheme_values_proc, app->rator)) {
- 48: 630: note_match(2, vals, warn_info);
- -: 631: }
- -: 632: }
- -: 633:
- 74563: 634: if (!SAME_OBJ(scheme_make_struct_type_property_proc, app->rator))
- 74491: 635: return 0;
- -: 636: }
- -: 637:
- -: 638: /* check for (set! x x) */
- 553017: 639: if (vtype == scheme_set_bang_type) {
- 4298: 640: Scheme_Set_Bang *sb = (Scheme_Set_Bang *)o;
- 4298: 641: if (SAME_TYPE(scheme_local_type, SCHEME_TYPE(sb->var))
- #####: 642: && SAME_TYPE(scheme_local_type, SCHEME_TYPE(sb->val))
- #####: 643: && (SCHEME_LOCAL_POS(sb->var) == SCHEME_LOCAL_POS(sb->val)))
- #####: 644: return 1;
- 4298: 645: else if (SAME_TYPE(scheme_ir_local_type, SCHEME_TYPE(sb->var))
- 3401: 646: && SAME_OBJ(sb->var, sb->val))
- 18: 647: return 1;
- -: 648: }
- -: 649:
- -: 650: /* check for struct-type declaration: */
- 552999: 651: if (!(flags & OMITTABLE_IGNORE_MAKE_STRUCT_TYPE)) {
- -: 652: Scheme_Object *auto_e;
- -: 653: int auto_e_depth;
- 1122249: 654: auto_e = scheme_is_simple_make_struct_type(o, vals,
- 552167: 655: (((flags & OMITTABLE_RESOLVED) ? CHECK_STRUCT_TYPE_RESOLVED : 0)
- -: 656: | CHECK_STRUCT_TYPE_ALWAYS_SUCCEED
- -: 657: | CHECK_STRUCT_TYPE_DELAY_AUTO_CHECK),
- -: 658: &auto_e_depth,
- -: 659: NULL, NULL,
- -: 660: (opt_info ? opt_info->top_level_consts : NULL),
- 17915: 661: ((opt_info && opt_info->cp) ? opt_info->cp->inline_variants : NULL),
- -: 662: NULL, NULL, 0, NULL, NULL, NULL,
- -: 663: 5);
- 552167: 664: if (auto_e) {
- 406: 665: if (scheme_omittable_expr(auto_e, 1, fuel - 1, flags, opt_info, warn_info))
- 406: 666: return 1;
- -: 667: }
- -: 668: }
- -: 669:
- -: 670: /* check for struct-type property declaration: */
- 552593: 671: if (!(flags & OMITTABLE_IGNORE_MAKE_STRUCT_TYPE)) {
- 1121033: 672: if (scheme_is_simple_make_struct_type_property(o, vals,
- 551761: 673: (((flags & OMITTABLE_RESOLVED) ? CHECK_STRUCT_TYPE_RESOLVED : 0)
- -: 674: | CHECK_STRUCT_TYPE_ALWAYS_SUCCEED),
- -: 675: NULL,
- -: 676: (opt_info ? opt_info->top_level_consts : NULL),
- 17511: 677: ((opt_info && opt_info->cp) ? opt_info->cp->inline_variants : NULL),
- -: 678: NULL, NULL, 0, NULL, NULL,
- -: 679: 5))
- 72: 680: return 1;
- -: 681: }
- -: 682:
- 552521: 683: return 0;
- -: 684:}
- -: 685:
- 3778: 686:static Scheme_Object *ensure_single_value(Scheme_Object *e)
- -: 687:/* Wrap `e` so that it either produces a single value or fails */
- -: 688:{
- -: 689: Scheme_App2_Rec *app2;
- 3778: 690: if (single_valued_expression(e, 5))
- 492: 691: return e;
- -: 692:
- 3286: 693: app2 = MALLOC_ONE_TAGGED(Scheme_App2_Rec);
- 3286: 694: app2->iso.so.type = scheme_application2_type;
- 3286: 695: app2->rator = scheme_values_proc;
- 3286: 696: app2->rand = e;
- 3286: 697: SCHEME_APPN_FLAGS(app2) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- -: 698:
- 3286: 699: return (Scheme_Object *)app2;
- -: 700:}
- -: 701:
- 12292: 702:static Scheme_Object *ensure_single_value_noncm(Scheme_Object *e)
- -: 703:/* Wrap `e` so that it either produces a single value or fails.
- -: 704: Also, wrap `e` in case it may have a `with-continuation-mark`
- -: 705: in tail position. */
- -: 706:{
- -: 707: Scheme_App2_Rec *app2;
- 12292: 708: if (single_valued_noncm_expression(e, 5))
- 11737: 709: return e;
- -: 710:
- 555: 711: app2 = MALLOC_ONE_TAGGED(Scheme_App2_Rec);
- 555: 712: app2->iso.so.type = scheme_application2_type;
- 555: 713: app2->rator = scheme_values_proc;
- 555: 714: app2->rand = e;
- 555: 715: SCHEME_APPN_FLAGS(app2) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- -: 716:
- 555: 717: return (Scheme_Object *)app2;
- -: 718:}
- -: 719:
- 426: 720:static Scheme_Object *ensure_noncm(Scheme_Object *e)
- -: 721:/* Wrap `e` in case it may have a `with-continuation-mark` form in tail
- -: 722: position. This is useful when `e` escapes, and it is lifted and the
- -: 723: surrounding is discarded, in which case the shift out of a nested
- -: 724: position is observable. */
- -: 725:{
- -: 726: Scheme_Sequence *seq;
- -: 727:
- 426: 728: if (noncm_expression(e, 5))
- 384: 729: return e;
- -: 730:
- 42: 731: seq = scheme_malloc_sequence(1);
- 42: 732: seq->so.type = scheme_begin0_sequence_type;
- 42: 733: seq->count = 1;
- 42: 734: seq->array[0] = e;
- -: 735:
- 42: 736: return (Scheme_Object *)seq;
- -: 737:}
- -: 738:
- 8693: 739:static Scheme_Object *do_make_discarding_sequence(Scheme_Object *e1, Scheme_Object *e2,
- -: 740: Optimize_Info *info,
- -: 741: int ignored, int rev)
- -: 742:/* Evaluate `e1` then `e2` (or opposite order if rev), and each must
- -: 743: produce a single value. The result of `e1` is ignored and the
- -: 744: result is `e2` --- except that `e2` is ignored, too, if
- -: 745: `ignored`. */
- -: 746:{
- 8693: 747: if (ignored)
- 162: 748: e2 = optimize_ignored(e2, info, 1, 0, 5);
- -: 749:
- 8693: 750: e2 = ensure_single_value_noncm(e2);
- -: 751:
- 8693: 752: if (scheme_omittable_expr(e1, 1, 5, 0, info, NULL))
- 5129: 753: return e2;
- -: 754:
- 3564: 755: e1 = ensure_single_value(optimize_ignored(e1, info, 1, 0, 5));
- -: 756:
- 3564: 757: if (ignored && scheme_omittable_expr(e2, 1, 5, 0, info, NULL))
- 102: 758: return ensure_single_value_noncm(e1);
- -: 759:
- -: 760: /* use `begin` instead of `begin0` if we can swap the order: */
- 3462: 761: if (rev && movable_expression(e2, info, 0, 1, 1, 0, 50))
- 4: 762: rev = 0;
- -: 763:
- 3462: 764: if (!rev && SAME_TYPE(SCHEME_TYPE(e1), scheme_sequence_type)) {
- 14: 765: Scheme_Sequence *seq = (Scheme_Sequence *)e1;
- -: 766:
- 14: 767: if (SCHEME_TYPE(seq->array[seq->count - 1]) > _scheme_ir_values_types_) {
- 2: 768: seq->array[seq->count - 1] = e2;
- 2: 769: return e1;
- -: 770: }
- -: 771: }
- -: 772:
- 3460: 773: return scheme_make_sequence_compilation(scheme_make_pair((rev ? e2 : e1),
- -: 774: scheme_make_pair((rev ? e1 : e2), scheme_null)),
- -: 775: rev ? -1 : 1,
- -: 776: 0);
- -: 777:}
- -: 778:
- 8030: 779:static Scheme_Object *make_discarding_sequence(Scheme_Object *e1, Scheme_Object *e2,
- -: 780: Optimize_Info *info)
- -: 781:{
- 8030: 782: return do_make_discarding_sequence(e1, e2, info, 0, 0);
- -: 783:}
- -: 784:
- 501: 785:static Scheme_Object *make_discarding_reverse_sequence(Scheme_Object *e1, Scheme_Object *e2,
- -: 786: Optimize_Info *info)
- -: 787:{
- 501: 788: return do_make_discarding_sequence(e1, e2, info, 0, 1);
- -: 789:}
- -: 790:
- 251: 791:static Scheme_Object *make_discarding_sequence_3(Scheme_Object *e1, Scheme_Object *e2, Scheme_Object *e3,
- -: 792: Optimize_Info *info)
- -: 793:{
- 251: 794: return make_discarding_sequence(e1, make_discarding_sequence(e2, e3, info), info);
- -: 795:}
- -: 796:
- 28: 797:static Scheme_Object *make_discarding_app_sequence(Scheme_App_Rec *appr, int result_pos, Scheme_Object *result,
- -: 798: Optimize_Info *info)
- -: 799:/* Generalize do_make_discarding_sequence() to a sequence of argument
- -: 800: expressions, where `result_pos` is the position of the returned
- -: 801: argument. If `result_pos` is -1, then all argument results will be
- -: 802: ignored. If `result`, then it is used as the result after all
- -: 803: arguments are evaluated.*/
- -: 804:{
- -: 805: int i;
- 28: 806: Scheme_Object *l = scheme_null;
- -: 807:
- 28: 808: result_pos = result_pos + 1;
- 28: 809: if (result)
- #####: 810: l = scheme_make_pair(result, l);
- -: 811:
- 120: 812: for (i = appr->num_args; i; i--) {
- -: 813: Scheme_Object *e;
- 92: 814: e = appr->args[i];
- 92: 815: e = ensure_single_value(e);
- 92: 816: if (i == result_pos) {
- 4: 817: if (SCHEME_NULLP(l)) {
- 2: 818: e = ensure_single_value_noncm(e);
- 2: 819: l = scheme_make_pair(e, scheme_null);
- -: 820: } else {
- 2: 821: l = scheme_make_sequence_compilation(scheme_make_pair(e, l), -1, 0);
- 2: 822: l = scheme_make_pair(l, scheme_null);
- -: 823: }
- -: 824: } else {
- 88: 825: e = optimize_ignored(e, info, 1, 1, 5);
- 88: 826: if (e)
- 36: 827: l = scheme_make_pair(e, l);
- -: 828: }
- -: 829: }
- -: 830:
- 28: 831: if (SCHEME_NULLP(l))
- #####: 832: return scheme_void;
- -: 833:
- 28: 834: if (SCHEME_NULLP(SCHEME_CDR(l)))
- 22: 835: return SCHEME_CAR(l);
- -: 836:
- 6: 837: return scheme_make_sequence_compilation(l, 1, 0);
- -: 838:}
- -: 839:
- 99627: 840:static Scheme_Object *optimize_ignored(Scheme_Object *e, Optimize_Info *info,
- -: 841: int expected_vals, int maybe_omittable,
- -: 842: int fuel)
- -: 843:/* Simplify an expression whose result will be ignored. The
- -: 844: `expected_vals` is 1 or -1. If `maybe_omittable`, the result can be
- -: 845: NULL to indicate that it can be omitted. */
- -: 846:{
- 99627: 847: if (scheme_omittable_expr(e, expected_vals, 5, 0, info, NULL))
- 18935: 848: return maybe_omittable? NULL : scheme_false;
- -: 849:
- 80692: 850: if (fuel) {
- -: 851: /* We could do a lot more here, but for now, we just avoid purely
- -: 852: functional, always successful operations --- especially allocating ones. */
- 79722: 853: switch (SCHEME_TYPE(e)) {
- -: 854: case scheme_application2_type:
- -: 855: {
- 19223: 856: Scheme_App2_Rec *app = (Scheme_App2_Rec *)e;
- -: 857:
- 19223: 858: if (!SAME_OBJ(app->rator, scheme_values_proc)) /* `values` is probably here to ensure a single result */
- 17260: 859: if (scheme_is_functional_nonfailing_primitive(app->rator, 1, expected_vals))
- 42: 860: return do_make_discarding_sequence(app->rand, scheme_void, info, 1, 0);
- -: 861:
- -: 862: /* (make-vector <num>) => <void> */
- 19181: 863: if (SAME_OBJ(app->rator, scheme_make_vector_proc)
- 18: 864: && (SCHEME_INTP(app->rand)
- 2: 865: && (SCHEME_INT_VAL(app->rand) >= 0))
- #####: 866: && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand)))
- #####: 867: return (maybe_omittable ? NULL : scheme_void);
- -: 868: }
- 19181: 869: break;
- -: 870: case scheme_application3_type:
- -: 871: {
- 8465: 872: Scheme_App3_Rec *app = (Scheme_App3_Rec *)e;
- -: 873:
- 8465: 874: if (scheme_is_functional_nonfailing_primitive(app->rator, 2, expected_vals))
- 60: 875: return do_make_discarding_sequence(app->rand1,
- -: 876: do_make_discarding_sequence(app->rand2,
- -: 877: scheme_void,
- -: 878: info,
- -: 879: 1, 0),
- -: 880: info,
- -: 881: 1, 0);
- -: 882:
- -: 883: /* (make-vector <num> <expr>) => <expr> */
- 8405: 884: if (SAME_OBJ(app->rator, scheme_make_vector_proc)
- 14: 885: && (SCHEME_INTP(app->rand1)
- 2: 886: && (SCHEME_INT_VAL(app->rand1) >= 0))
- 2: 887: && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand1))) {
- -: 888: Scheme_Object *val;
- 2: 889: val = ensure_single_value_noncm(app->rand2);
- 2: 890: return optimize_ignored(val, info, 1, maybe_omittable, 5);
- -: 891: }
- -: 892: }
- 8403: 893: break;
- -: 894: case scheme_application_type:
- -: 895: {
- 22870: 896: Scheme_App_Rec *app = (Scheme_App_Rec *)e;
- -: 897:
- 22870: 898: if (scheme_is_functional_nonfailing_primitive(app->args[0], app->num_args, expected_vals))
- 24: 899: return make_discarding_app_sequence(app, -1, NULL, info);
- -: 900: }
- 22846: 901: break;
- -: 902: case scheme_branch_type:
- -: 903: {
- 18307: 904: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)e;
- -: 905: Scheme_Object *tb, *fb;
- -: 906:
- 18307: 907: tb = optimize_ignored(b->tbranch, info, expected_vals, 1, fuel - 1);
- 18307: 908: fb = optimize_ignored(b->fbranch, info, expected_vals, 1, fuel - 1);
- -: 909:
- 18307: 910: if (tb || fb) {
- 18299: 911: b->tbranch = tb ? tb : scheme_false;
- 18299: 912: b->fbranch = fb ? fb : scheme_false;
- 18299: 913: return (Scheme_Object*)b;
- -: 914: } else {
- -: 915: Scheme_Object *val;
- 8: 916: val = ensure_single_value_noncm(b->test);
- 8: 917: return optimize_ignored(val, info, 1, maybe_omittable, 5);
- -: 918: }
- -: 919: }
- -: 920: break;
- -: 921: case scheme_sequence_type:
- -: 922: {
- 2698: 923: Scheme_Sequence *seq = (Scheme_Sequence *)e;
- -: 924: Scheme_Object *last;
- -: 925:
- 2698: 926: last = optimize_ignored(seq->array[seq->count - 1], info, expected_vals, 1, fuel - 1);
- -: 927:
- 2698: 928: if (last) {
- 2519: 929: seq->array[seq->count - 1] = last;
- 2519: 930: return (Scheme_Object*)seq;
- 179: 931: } else if (seq->count == 2
- 137: 932: && (expected_vals == -1
- 41: 933: || single_valued_noncm_expression(seq->array[0], 5))) {
- 137: 934: return seq->array[0];
- -: 935: } else {
- 42: 936: seq->array[seq->count - 1] = scheme_false;
- 42: 937: return (Scheme_Object*)seq;
- -: 938: }
- -: 939: }
- -: 940: case scheme_begin0_sequence_type:
- -: 941: {
- 8: 942: Scheme_Sequence *seq = (Scheme_Sequence *)e;
- -: 943: Scheme_Object *first;
- -: 944:
- 8: 945: first = optimize_ignored(seq->array[0], info, expected_vals, 1, fuel - 1);
- -: 946:
- 8: 947: if (first) {
- 8: 948: seq->array[0] = first;
- 8: 949: return (Scheme_Object*)seq;
- #####: 950: } else if (seq->count == 2
- #####: 951: && (expected_vals == -1
- #####: 952: || single_valued_noncm_expression(seq->array[1], 5))) {
- #####: 953: return seq->array[1];
- -: 954: } else {
- #####: 955: seq->array[0] = scheme_false;
- #####: 956: return (Scheme_Object*)seq;
- -: 957: }
- -: 958: }
- -: 959: break;
- -: 960: case scheme_ir_let_header_type:
- -: 961: {
- 5110: 962: Scheme_IR_Let_Header *head = (Scheme_IR_Let_Header *)e;
- -: 963: Scheme_IR_Let_Value *lv;
- -: 964: Scheme_Object *body;
- -: 965: int i;
- -: 966:
- 5110: 967: body = head->body;
- 5110: 968: if (0 == head->num_clauses)
- #####: 969: lv = (Scheme_IR_Let_Value *)body;
- 15799: 970: for (i = head->num_clauses; i--; ) {
- 5579: 971: lv = (Scheme_IR_Let_Value *)body;
- 5579: 972: body = lv->body;
- -: 973: }
- 5110: 974: body = optimize_ignored(body, info, expected_vals, 0, fuel - 1);
- 5110: 975: lv->body = body;
- 5110: 976: return (Scheme_Object*)head;
- -: 977: }
- -: 978: break;
- -: 979: }
- -: 980: }
- -: 981:
- 54441: 982: return e;
- -: 983:}
- -: 984:
- 95: 985:static Scheme_Object *make_sequence_2(Scheme_Object *a, Scheme_Object *b)
- -: 986:{
- 95: 987: return scheme_make_sequence_compilation(scheme_make_pair(a, scheme_make_pair(b, scheme_null)), 1, 0);
- -: 988:}
- -: 989:
- 305: 990:static Scheme_Object *make_discarding_first_sequence(Scheme_Object *e1, Scheme_Object *e2,
- -: 991: Optimize_Info *info)
- -: 992:/* Like make_discarding_sequence(), but second expression is not constrained to
- -: 993: a single result. */
- -: 994:{
- 305: 995: e1 = optimize_ignored(e1, info, 1, 1, 5);
- 305: 996: if (!e1)
- 211: 997: return e2;
- 94: 998: e1 = ensure_single_value(e1);
- 94: 999: return make_sequence_2(e1, e2);
- -: 1000:}
- -: 1001:
- 615: 1002:static Scheme_Object *make_application_2(Scheme_Object *a, Scheme_Object *b, Optimize_Info *info)
- -: 1003:{
- 615: 1004: return scheme_make_application(scheme_make_pair(a, scheme_make_pair(b, scheme_null)), info);
- -: 1005:}
- -: 1006:
- 2388: 1007:static Scheme_Object *make_application_3(Scheme_Object *a, Scheme_Object *b, Scheme_Object *c,
- -: 1008: Optimize_Info *info)
- -: 1009:{
- 2388: 1010: return scheme_make_application(scheme_make_pair(a, scheme_make_pair(b, scheme_make_pair(c, scheme_null))),
- -: 1011: info);
- -: 1012:}
- -: 1013:
- 79421: 1014:static Scheme_Object *replace_tail_inside(Scheme_Object *alt, Scheme_Object *inside, Scheme_Object *orig)
- -: 1015:/* Installs a new expression in the result position of various forms, such as `begin`;
- -: 1016: extract_tail_inside() needs to be consistent with this function */
- -: 1017:{
- 79421: 1018: if (inside) {
- 6251: 1019: switch (SCHEME_TYPE(inside)) {
- -: 1020: case scheme_sequence_type:
- 3217: 1021: if (((Scheme_Sequence *)inside)->count)
- 3217: 1022: ((Scheme_Sequence *)inside)->array[((Scheme_Sequence *)inside)->count-1] = alt;
- -: 1023: else
- #####: 1024: scheme_signal_error("internal error: strange inside replacement");
- 3217: 1025: break;
- -: 1026: case scheme_ir_let_header_type:
- #####: 1027: ((Scheme_IR_Let_Header *)inside)->body = alt;
- #####: 1028: break;
- -: 1029: case scheme_ir_let_value_type:
- 3034: 1030: ((Scheme_IR_Let_Value *)inside)->body = alt;
- 3034: 1031: break;
- -: 1032: default:
- #####: 1033: scheme_signal_error("internal error: strange inside replacement");
- -: 1034: }
- 6251: 1035: return orig;
- -: 1036: }
- 73170: 1037: return alt;
- -: 1038:}
- -: 1039:
- 5233088: 1040:static void extract_tail_inside(Scheme_Object **_t2, Scheme_Object **_inside)
- -: 1041:/* Looks through various forms, like `begin` to extract a result expression;
- -: 1042: replace_tail_inside() needs to be consistent with this function */
- -: 1043:{
- -: 1044: while (1) {
- 5245153: 1045: if (SAME_TYPE(SCHEME_TYPE(*_t2), scheme_ir_let_header_type)) {
- 12065: 1046: Scheme_IR_Let_Header *head = (Scheme_IR_Let_Header *)*_t2;
- -: 1047: int i;
- 12065: 1048: *_inside = *_t2;
- 12065: 1049: *_t2 = head->body;
- 36556: 1050: for (i = head->num_clauses; i--; ) {
- 12426: 1051: *_inside = *_t2;
- 12426: 1052: *_t2 = ((Scheme_IR_Let_Value *)*_t2)->body;
- -: 1053: }
- 5221023: 1054: } else if (SAME_TYPE(SCHEME_TYPE(*_t2), scheme_sequence_type)) {
- 3449: 1055: Scheme_Sequence *seq = (Scheme_Sequence *)*_t2;
- 3449: 1056: if (seq->count) {
- 3449: 1057: *_inside = *_t2;
- 3449: 1058: *_t2 = seq->array[seq->count-1];
- -: 1059: } else
- #####: 1060: break;
- -: 1061: } else
- -: 1062: break;
- 15514: 1063: }
- 5217574: 1064:}
- -: 1065:
- 328084: 1066:Scheme_Object *scheme_optimize_extract_tail_inside(Scheme_Object *t2)
- -: 1067:{
- -: 1068: Scheme_Object *inside;
- 328084: 1069: extract_tail_inside(&t2, &inside);
- 328084: 1070: return t2;
- -: 1071:}
- -: 1072:
- -: 1073:/*========================================================================*/
- -: 1074:/* detecting `make-struct-type` calls and struct shapes */
- -: 1075:/*========================================================================*/
- -: 1076:
- 43064: 1077:static int is_inspector_call(Scheme_Object *a)
- -: 1078:/* Does `a` produce an inspector? */
- -: 1079:{
- 43064: 1080: if (SAME_TYPE(SCHEME_TYPE(a), scheme_application_type)) {
- 43040: 1081: Scheme_App_Rec *app = (Scheme_App_Rec *)a;
- 43040: 1082: if (!app->num_args
- 43040: 1083: && (SAME_OBJ(app->args[0], scheme_current_inspector_proc)
- #####: 1084: || SAME_OBJ(app->args[0], scheme_make_inspector_proc)))
- 43040: 1085: return 1;
- -: 1086: }
- 24: 1087: return 0;
- -: 1088:}
- -: 1089:
- 13846: 1090:static int is_proc_spec_proc(Scheme_Object *p, int init_field_count)
- -: 1091:/* Does `p` produce a good `prop:procedure` value? */
- -: 1092:{
- -: 1093: Scheme_Type vtype;
- -: 1094:
- 13846: 1095: if (SCHEME_INTP(p)
- 6938: 1096: && (SCHEME_INT_VAL(p) >= 0)
- 6938: 1097: && (SCHEME_INT_VAL(p) < init_field_count))
- 6938: 1098: return 1;
- -: 1099:
- 6908: 1100: if (SCHEME_PROCP(p)) {
- 1855: 1101: p = scheme_get_or_check_arity(p, -1);
- 1855: 1102: if (SCHEME_INTP(p)) {
- 1855: 1103: return (SCHEME_INT_VAL(p) >= 1);
- #####: 1104: } else if (SCHEME_STRUCTP(p)
- #####: 1105: && scheme_is_struct_instance(scheme_arity_at_least, p)) {
- #####: 1106: p = ((Scheme_Structure *)p)->slots[0];
- #####: 1107: if (SCHEME_INTP(p))
- #####: 1108: return (SCHEME_INT_VAL(p) >= 1);
- -: 1109: }
- #####: 1110: return 0;
- -: 1111: }
- -: 1112:
- 5053: 1113: vtype = SCHEME_TYPE(p);
- -: 1114:
- 5053: 1115: if ((vtype == scheme_lambda_type) || (vtype == scheme_ir_lambda_type)) {
- 776: 1116: if (((Scheme_Lambda *)p)->num_params >= 1)
- 776: 1117: return 1;
- -: 1118: }
- -: 1119:
- 4277: 1120: return 0;
- -: 1121:}
- -: 1122:
- 158990: 1123:static int is_local_ref(Scheme_Object *e, int p, int r, Scheme_IR_Local **vars)
- -: 1124:/* Does `e` refer to...
- -: 1125: In resolved mode: variables at offet `p` though `p+r`?
- -: 1126: In optimizer IR mode: variables in `vars`? */
- -: 1127:{
- 158990: 1128: if (!vars && SAME_TYPE(SCHEME_TYPE(e), scheme_local_type)) {
- 110137: 1129: if ((SCHEME_LOCAL_POS(e) >= p)
- 110137: 1130: && (SCHEME_LOCAL_POS(e) < (p + r)))
- 110137: 1131: return 1;
- 48853: 1132: } else if (vars && SAME_TYPE(SCHEME_TYPE(e), scheme_ir_local_type)) {
- -: 1133: int i;
- 2085: 1134: for (i = p; i < p + r; i++) {
- 2085: 1135: if (SAME_OBJ(e, (Scheme_Object *)vars[i]))
- 2085: 1136: return 1;
- -: 1137: }
- -: 1138: }
- -: 1139:
- 46768: 1140: return 0;
- -: 1141:}
- -: 1142:
- 35165: 1143:static int is_int_list(Scheme_Object *o, int up_to)
- -: 1144:/* Is `o` a list of distinct integers that are less than `up_to`? */
- -: 1145:{
- 35165: 1146: if (SCHEME_PAIRP(o)) {
- -: 1147: char *s, quick[8];
- -: 1148: Scheme_Object *e;
- 30704: 1149: if (up_to <= 8)
- 29941: 1150: s = quick;
- -: 1151: else
- 763: 1152: s = (char *)scheme_malloc_atomic(up_to);
- 30704: 1153: memset(s, 0, up_to);
- 145107: 1154: while (SCHEME_PAIRP(o)) {
- 83699: 1155: e = SCHEME_CAR(o);
- 83699: 1156: o = SCHEME_CDR(o);
- 83699: 1157: if (!SCHEME_INTP(e)
- 83699: 1158: || (SCHEME_INT_VAL(e) < 0)
- 83699: 1159: || (SCHEME_INT_VAL(e) > up_to)
- 83699: 1160: || s[SCHEME_INT_VAL(e)])
- #####: 1161: return 0;
- 83699: 1162: s[SCHEME_INT_VAL(e)] = 1;
- -: 1163: }
- -: 1164: }
- -: 1165:
- 35165: 1166: return SCHEME_NULLP(o);
- -: 1167:}
- -: 1168:
- 46768: 1169:static int ok_proc_creator_args(Scheme_Object *rator, Scheme_Object *rand1, Scheme_Object *rand2, Scheme_Object *rand3,
- -: 1170: int delta2, int field_count, Scheme_IR_Local **vars)
- -: 1171:/* Does `rator` plus `rand1` and `rand2` create a struct accessor or mutator? */
- -: 1172:{
- 46768: 1173: if ((SAME_OBJ(rator, scheme_make_struct_field_accessor_proc)
- 45937: 1174: && is_local_ref(rand1, delta2+3, 1, vars))
- 831: 1175: || (SAME_OBJ(rator, scheme_make_struct_field_mutator_proc)
- 831: 1176: && is_local_ref(rand1, delta2+4, 1, vars))) {
- 46768: 1177: if (SCHEME_INTP(rand2)
- 46768: 1178: && (SCHEME_INT_VAL(rand2) >= 0)
- 46768: 1179: && (SCHEME_INT_VAL(rand2) < field_count)
- 46768: 1180: && (!rand3 || SCHEME_SYMBOLP(rand3))) {
- 46768: 1181: return 1;
- -: 1182: }
- -: 1183: }
- -: 1184:
- #####: 1185: return 0;
- -: 1186:}
- -: 1187:
- 22022: 1188:static int is_values_with_accessors_and_mutators(Scheme_Object *e, int vals, int resolved,
- -: 1189: Simple_Stuct_Type_Info *_stinfo,
- -: 1190: Scheme_IR_Local **vars)
- -: 1191:/* Does `e` produce values for a structure type, mutators, and accessors in the
- -: 1192: usual order? */
- -: 1193:{
- 22022: 1194: if (SAME_TYPE(SCHEME_TYPE(e), scheme_application_type)) {
- 21818: 1195: Scheme_App_Rec *app = (Scheme_App_Rec *)e;
- 21818: 1196: int delta = (resolved ? app->num_args : 0);
- 21818: 1197: if (SAME_OBJ(app->args[0], scheme_values_proc)
- 21818: 1198: && (app->num_args == vals)
- 21818: 1199: && (app->num_args >= 3)
- 21818: 1200: && is_local_ref(app->args[1], delta, 1, vars)
- 21818: 1201: && is_local_ref(app->args[2], delta+1, 1, vars)
- 21818: 1202: && is_local_ref(app->args[3], delta+2, 1, vars)) {
- 21818: 1203: int i, num_gets = 0, num_sets = 0, normal_ops = 1;
- 68586: 1204: for (i = app->num_args; i > 3; i--) {
- 46768: 1205: if (is_local_ref(app->args[i], delta, 5, vars)) {
- #####: 1206: normal_ops = 0;
- 46768: 1207: } else if (SAME_TYPE(SCHEME_TYPE(app->args[i]), scheme_application_type)
- 93520: 1208: && _stinfo->normal_ops && !_stinfo->indexed_ops) {
- 46760: 1209: Scheme_App_Rec *app3 = (Scheme_App_Rec *)app->args[i];
- 46760: 1210: int delta2 = delta + (resolved ? app3->num_args : 0);
- 46760: 1211: if (app3->num_args == 3) {
- 46760: 1212: if (!ok_proc_creator_args(app3->args[0], app3->args[1], app3->args[2], app3->args[3],
- -: 1213: delta2, _stinfo->field_count, vars))
- #####: 1214: break;
- 46760: 1215: if (SAME_OBJ(app3->args[0], scheme_make_struct_field_mutator_proc)) {
- 831: 1216: if (num_gets) {
- -: 1217: /* Since we're alking backwards, it's not normal to hit a mutator
- -: 1218: after (i.e., before in argument order) a selector */
- #####: 1219: normal_ops = 0;
- -: 1220: }
- 831: 1221: num_sets++;
- -: 1222: } else {
- 45929: 1223: if (SCHEME_INT_VAL(app3->args[2]) != (i - 4)) {
- -: 1224: /* selectors are not in the usual order */
- #####: 1225: normal_ops = 0;
- -: 1226: }
- 45929: 1227: num_gets++;
- -: 1228: }
- -: 1229: } else
- #####: 1230: break;
- 8: 1231: } else if (SAME_TYPE(SCHEME_TYPE(app->args[i]), scheme_application3_type)
- 8: 1232: && _stinfo->normal_ops && !_stinfo->indexed_ops) {
- 8: 1233: Scheme_App3_Rec *app3 = (Scheme_App3_Rec *)app->args[i];
- 8: 1234: int delta2 = delta + (resolved ? 2 : 0);
- 8: 1235: if (!ok_proc_creator_args(app3->rator, app3->rand1, app3->rand2, NULL,
- -: 1236: delta2, _stinfo->field_count, vars))
- #####: 1237: break;
- 8: 1238: if (SAME_OBJ(app3->rator, scheme_make_struct_field_mutator_proc)) {
- #####: 1239: if (num_gets) normal_ops = 0;
- #####: 1240: num_sets++;
- -: 1241: } else {
- 8: 1242: if (SCHEME_INT_VAL(app3->rand2) != (i - 4)) normal_ops = 0;
- 8: 1243: num_gets++;
- -: 1244: }
- -: 1245: } else
- -: 1246: break;
- -: 1247: }
- 21818: 1248: if (i <= 3) {
- 21818: 1249: _stinfo->normal_ops = normal_ops;
- 21818: 1250: _stinfo->indexed_ops = 1;
- 21818: 1251: _stinfo->num_gets = num_gets;
- 21818: 1252: _stinfo->num_sets = num_sets;
- 21818: 1253: return 1;
- -: 1254: }
- -: 1255: }
- -: 1256: }
- -: 1257:
- 204: 1258: return 0;
- -: 1259:}
- -: 1260:
- 59315: 1261:static Scheme_Object *skip_clears(Scheme_Object *body)
- -: 1262:/* If `body` is a `begin` form that exists only to clear variables
- -: 1263: as installed by the SFS pass, then extract the result form. */
- -: 1264:{
- 59315: 1265: if (SAME_TYPE(SCHEME_TYPE(body), scheme_sequence_type)) {
- 18981: 1266: Scheme_Sequence *seq = (Scheme_Sequence *)body;
- -: 1267: int i;
- 57335: 1268: for (i = seq->count - 1; i--; ) {
- 19373: 1269: if (!SAME_TYPE(SCHEME_TYPE(seq->array[i]), scheme_local_type))
- -: 1270: break;
- -: 1271: }
- 18981: 1272: if (i < 0)
- 18981: 1273: return seq->array[seq->count-1];
- -: 1274: }
- 40334: 1275: return body;
- -: 1276:}
- -: 1277:
- -: 1278:typedef int (*Ok_Value_Callback)(void *data, Scheme_Object *v, int mode);
- -: 1279:#define OK_CONSTANT_SHAPE 1
- -: 1280:#define OK_CONSTANT_ENCODED_SHAPE 2
- -: 1281:#define OK_CONSTANT_VALIDATE_SHAPE 3
- -: 1282:#define OK_CONSTANT_VARIANT 4
- -: 1283:#define OK_CONSTANT_VALUE 5
- -: 1284:
- 40021: 1285:static int is_ok_value(Ok_Value_Callback ok_value, void *data,
- -: 1286: Scheme_Object *arg,
- -: 1287: Scheme_Hash_Table *top_level_consts,
- -: 1288: Scheme_Hash_Table *inline_variants,
- -: 1289: Scheme_Hash_Table *top_level_table,
- -: 1290: Scheme_Object **runstack, int rs_delta,
- -: 1291: Scheme_Object **symbols, Scheme_Hash_Table *symbol_table)
- -: 1292:/* Does `arg` produce a value that satisfies `ok_value`? */
- -: 1293:{
- -: 1294: int pos;
- -: 1295: Scheme_Object *v;
- -: 1296:
- 40021: 1297: if (SAME_TYPE(SCHEME_TYPE(arg), scheme_ir_toplevel_type)) {
- 632: 1298: pos = SCHEME_TOPLEVEL_POS(arg);
- 673: 1299: if (top_level_consts || inline_variants) {
- -: 1300: /* This is optimize mode */
- 627: 1301: v = NULL;
- 627: 1302: if (top_level_consts)
- 591: 1303: v = scheme_hash_get(top_level_consts, scheme_make_integer(pos));
- 627: 1304: if (!v && inline_variants)
- 187: 1305: v = scheme_hash_get(inline_variants, scheme_make_integer(pos));
- 627: 1306: if (v)
- 591: 1307: return ok_value(data, v, OK_CONSTANT_SHAPE);
- -: 1308: }
- 39389: 1309: } else if (SAME_TYPE(SCHEME_TYPE(arg), scheme_toplevel_type)) {
- 39127: 1310: pos = SCHEME_TOPLEVEL_POS(arg);
- 39127: 1311: if (runstack) {
- -: 1312: /* This is eval mode; conceptually, this code belongs in
- -: 1313: define_execute_with_dynamic_state() */
- -: 1314: Scheme_Bucket *b;
- -: 1315: Scheme_Prefix *toplevels;
- 35584: 1316: toplevels = (Scheme_Prefix *)runstack[SCHEME_TOPLEVEL_DEPTH(arg) - rs_delta];
- 35584: 1317: b = (Scheme_Bucket *)toplevels->a[pos];
- 35584: 1318: if (b->val && (((Scheme_Bucket_With_Flags *)b)->flags & GLOB_IS_CONSISTENT))
- 30220: 1319: return ok_value(data, b->val, OK_CONSTANT_VALUE);
- -: 1320: }
- 8907: 1321: if (symbols) {
- -: 1322: /* This is module-export mode; conceptually, this code belongs in
- -: 1323: setup_accessible_table() */
- -: 1324: Scheme_Object *name;
- 1743: 1325: name = symbols[pos];
- 1743: 1326: if (SCHEME_SYMBOLP(name)) {
- 1610: 1327: v = scheme_hash_get(symbol_table, name);
- 1610: 1328: if (v)
- 1610: 1329: return ok_value(data, v, OK_CONSTANT_VARIANT);
- 133: 1330: } else if (SAME_TYPE(SCHEME_TYPE(name), scheme_module_variable_type)) {
- 133: 1331: if (((Module_Variable *)name)->shape)
- 125: 1332: return ok_value(data, ((Module_Variable *)name)->shape, OK_CONSTANT_ENCODED_SHAPE);
- -: 1333: }
- -: 1334: }
- 7172: 1335: if (top_level_table) {
- -: 1336: /* This is validate mode; conceptually, this code belongs in
- -: 1337: define_values_validate() */
- 1466: 1338: v = scheme_hash_get(top_level_table, scheme_make_integer(pos));
- 1466: 1339: if (v) {
- 1406: 1340: return ok_value(data, v, OK_CONSTANT_VALIDATE_SHAPE);
- -: 1341: }
- -: 1342: }
- -: 1343: }
- -: 1344:
- 6069: 1345: return 0;
- -: 1346:}
- -: 1347:
- 33844: 1348:static int ok_constant_super_value(void *data, Scheme_Object *v, int mode)
- -: 1349:/* Is `v` a structure type (which can serve as a supertype)? */
- -: 1350:{
- 33844: 1351: Scheme_Object **_parent_identity = (Scheme_Object **)data;
- -: 1352:
- 33844: 1353: if (mode == OK_CONSTANT_SHAPE) {
- 483: 1354: if (SAME_TYPE(SCHEME_TYPE(v), scheme_struct_proc_shape_type)) {
- 483: 1355: int mode = (SCHEME_PROC_SHAPE_MODE(v) & STRUCT_PROC_SHAPE_MASK);
- 483: 1356: int field_count = (SCHEME_PROC_SHAPE_MODE(v) >> STRUCT_PROC_SHAPE_SHIFT);
- 483: 1357: if (mode == STRUCT_PROC_SHAPE_STRUCT) {
- 483: 1358: if (_parent_identity)
- 296: 1359: *_parent_identity = SCHEME_PROC_SHAPE_IDENTITY(v);
- 483: 1360: return field_count + 1;
- -: 1361: }
- -: 1362: }
- 33361: 1363: } else if (mode == OK_CONSTANT_ENCODED_SHAPE) {
- -: 1364: intptr_t k;
- 125: 1365: if (scheme_decode_struct_shape(v, &k)) {
- 109: 1366: if ((k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_STRUCT)
- 109: 1367: return (k >> STRUCT_PROC_SHAPE_SHIFT) + 1;
- -: 1368: }
- 33236: 1369: } else if (mode == OK_CONSTANT_VALIDATE_SHAPE) {
- 1406: 1370: int k = SCHEME_INT_VAL(v);
- 1406: 1371: if ((k >= 0)
- 1406: 1372: && (k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_STRUCT)
- 1406: 1373: return (k >> STRUCT_PROC_SHAPE_SHIFT) + 1;
- 31830: 1374: } else if (mode == OK_CONSTANT_VARIANT) {
- 1610: 1375: if (SCHEME_VECTORP(v) && (SCHEME_VEC_SIZE(v) == 3)) {
- 1551: 1376: if (_parent_identity)
- 1551: 1377: *_parent_identity = SCHEME_VEC_ELS(v)[2];
- 1551: 1378: v = SCHEME_VEC_ELS(v)[1];
- 1551: 1379: if (v && SCHEME_INTP(v)) {
- 1551: 1380: int mode = (SCHEME_INT_VAL(v) & STRUCT_PROC_SHAPE_MASK);
- 1551: 1381: int field_count = (SCHEME_INT_VAL(v) >> STRUCT_PROC_SHAPE_SHIFT);
- 1551: 1382: if (mode == STRUCT_PROC_SHAPE_STRUCT)
- 1551: 1383: return field_count + 1;
- -: 1384: }
- -: 1385: }
- 30220: 1386: } else if (mode == OK_CONSTANT_VALUE) {
- 30220: 1387: if (SCHEME_STRUCT_TYPEP(v)) {
- 30220: 1388: Scheme_Struct_Type *st = (Scheme_Struct_Type *)v;
- 30220: 1389: if (st->num_slots == st->num_islots)
- 30220: 1390: return st->num_slots + 1;
- -: 1391: }
- -: 1392: }
- -: 1393:
- 75: 1394: return 0;
- -: 1395:}
- -: 1396:
- 39810: 1397:static int is_constant_super(Scheme_Object *arg,
- -: 1398: Scheme_Hash_Table *top_level_consts,
- -: 1399: Scheme_Hash_Table *inline_variants,
- -: 1400: Scheme_Hash_Table *top_level_table,
- -: 1401: Scheme_Object **runstack, int rs_delta,
- -: 1402: Scheme_Object **symbols, Scheme_Hash_Table *symbol_table,
- -: 1403: Scheme_Object **_parent_identity)
- -: 1404:/* Does `arg` produce another structure type (which can serve as a supertype)? */
- -: 1405:{
- 39810: 1406: return is_ok_value(ok_constant_super_value, _parent_identity,
- -: 1407: arg,
- -: 1408: top_level_consts,
- -: 1409: inline_variants, top_level_table,
- -: 1410: runstack, rs_delta,
- -: 1411: symbols, symbol_table);
- -: 1412:}
- -: 1413:
- 108: 1414:static int ok_constant_property_with_guard(void *data, Scheme_Object *v, int mode)
- -: 1415:{
- 108: 1416: intptr_t k = 0;
- -: 1417:
- 108: 1418: if (mode == OK_CONSTANT_SHAPE) {
- 108: 1419: if (SAME_TYPE(SCHEME_TYPE(v), scheme_struct_prop_proc_shape_type)) {
- 108: 1420: k = SCHEME_PROC_SHAPE_MODE(v);
- -: 1421: }
- #####: 1422: } else if (mode == OK_CONSTANT_ENCODED_SHAPE) {
- #####: 1423: if (!scheme_decode_struct_prop_shape(v, &k))
- #####: 1424: k = 0;
- #####: 1425: } else if (mode == OK_CONSTANT_VALIDATE_SHAPE) {
- #####: 1426: int k = SCHEME_INT_VAL(v);
- #####: 1427: if (k < 0)
- #####: 1428: k = -(k+1);
- -: 1429: else
- #####: 1430: k = 0;
- #####: 1431: } else if (mode == OK_CONSTANT_VARIANT) {
- #####: 1432: if (SCHEME_VECTORP(v) && (SCHEME_VEC_SIZE(v) == 4)) {
- #####: 1433: v = SCHEME_VEC_ELS(v)[1];
- #####: 1434: if (v && SCHEME_INTP(v))
- #####: 1435: k = SCHEME_INT_VAL(v);
- -: 1436: }
- #####: 1437: } else if (mode == OK_CONSTANT_VALUE) {
- #####: 1438: if (SAME_TYPE(SCHEME_TYPE(v), scheme_struct_property_type)) {
- #####: 1439: if (!((Scheme_Struct_Property *)v)->guard)
- #####: 1440: return 1;
- -: 1441: }
- -: 1442: }
- -: 1443:
- 108: 1444: return (k == STRUCT_PROP_PROC_SHAPE_PROP);
- -: 1445:}
- -: 1446:
- 211: 1447:static int is_struct_type_property_without_guard(Scheme_Object *arg,
- -: 1448: Scheme_Hash_Table *top_level_consts,
- -: 1449: Scheme_Hash_Table *inline_variants,
- -: 1450: Scheme_Hash_Table *top_level_table,
- -: 1451: Scheme_Object **runstack, int rs_delta,
- -: 1452: Scheme_Object **symbols, Scheme_Hash_Table *symbol_table)
- -: 1453:/* Does `arg` produce a structure type property that has no guard (so that any value is ok)? */
- -: 1454:{
- 211: 1455: return is_ok_value(ok_constant_property_with_guard, NULL,
- -: 1456: arg,
- -: 1457: top_level_consts,
- -: 1458: inline_variants, top_level_table,
- -: 1459: runstack, rs_delta,
- -: 1460: symbols, symbol_table);
- -: 1461:}
- -: 1462:
- 206: 1463:static int is_simple_property_list(Scheme_Object *a, int resolved,
- -: 1464: Scheme_Hash_Table *top_level_consts,
- -: 1465: Scheme_Hash_Table *inline_variants,
- -: 1466: Scheme_Hash_Table *top_level_table,
- -: 1467: Scheme_Object **runstack, int rs_delta,
- -: 1468: Scheme_Object **symbols, Scheme_Hash_Table *symbol_table)
- -: 1469:/* Does `a` produce a property list that always lets `make-struct-type` succeed? */
- -: 1470:{
- -: 1471: Scheme_Object *arg;
- -: 1472: int i, count;
- -: 1473:
- 206: 1474: if (SAME_TYPE(SCHEME_TYPE(a), scheme_application_type)) {
- #####: 1475: if (!SAME_OBJ(((Scheme_App_Rec *)a)->args[0], scheme_list_proc))
- #####: 1476: return 0;
- #####: 1477: count = ((Scheme_App_Rec *)a)->num_args;
- 206: 1478: } else if (SAME_TYPE(SCHEME_TYPE(a), scheme_application2_type)) {
- 144: 1479: if (!SAME_OBJ(((Scheme_App2_Rec *)a)->rator, scheme_list_proc))
- #####: 1480: return 0;
- 144: 1481: count = 1;
- 62: 1482: } else if (SAME_TYPE(SCHEME_TYPE(a), scheme_application3_type)) {
- 62: 1483: if (!SAME_OBJ(((Scheme_App3_Rec *)a)->rator, scheme_list_proc))
- #####: 1484: return 0;
- 62: 1485: count = 2;
- -: 1486: } else
- #####: 1487: return 0;
- -: 1488:
- 289: 1489: for (i = 0; i < count; i++) {
- 211: 1490: if (SAME_TYPE(SCHEME_TYPE(a), scheme_application_type))
- #####: 1491: arg = ((Scheme_App_Rec *)a)->args[i+1];
- 211: 1492: else if (SAME_TYPE(SCHEME_TYPE(a), scheme_application2_type))
- 144: 1493: arg = ((Scheme_App2_Rec *)a)->rand;
- -: 1494: else {
- 67: 1495: if (i == 0)
- 62: 1496: arg = ((Scheme_App3_Rec *)a)->rand1;
- -: 1497: else
- 5: 1498: arg = ((Scheme_App3_Rec *)a)->rand2;
- -: 1499: }
- -: 1500:
- 294: 1501: if (SAME_TYPE(SCHEME_TYPE(arg), scheme_application3_type)) {
- 211: 1502: Scheme_App3_Rec *a3 = (Scheme_App3_Rec *)arg;
- -: 1503:
- 211: 1504: if (!SAME_OBJ(a3->rator, scheme_cons_proc))
- #####: 1505: return 0;
- 211: 1506: if (is_struct_type_property_without_guard(a3->rand1,
- -: 1507: top_level_consts,
- -: 1508: inline_variants, top_level_table,
- -: 1509: runstack, rs_delta,
- -: 1510: symbols, symbol_table)) {
- 83: 1511: if (!scheme_omittable_expr(a3->rand2, 1, 3, (resolved ? OMITTABLE_RESOLVED : 0), NULL, NULL))
- #####: 1512: return 0;
- -: 1513: } else
- 128: 1514: return 0;
- -: 1515: } else
- #####: 1516: return 0;
- -: 1517: }
- -: 1518:
- 78: 1519: return 1;
- -: 1520:}
- -: 1521:
- 818252: 1522:Scheme_Object *scheme_is_simple_make_struct_type(Scheme_Object *e, int vals, int flags,
- -: 1523: GC_CAN_IGNORE int *_auto_e_depth,
- -: 1524: Simple_Stuct_Type_Info *_stinfo,
- -: 1525: Scheme_Object **_parent_identity,
- -: 1526: Scheme_Hash_Table *top_level_consts,
- -: 1527: Scheme_Hash_Table *inline_variants,
- -: 1528: Scheme_Hash_Table *top_level_table,
- -: 1529: Scheme_Object **runstack, int rs_delta,
- -: 1530: Scheme_Object **symbols, Scheme_Hash_Table *symbol_table,
- -: 1531: Scheme_Object **_name,
- -: 1532: int fuel)
- -: 1533:/* Checks whether it's a `make-struct-type' call --- that, if `flags` includes
- -: 1534: `CHECK_STRUCT_TYPE_ALWAYS_SUCCEED`, certainly succeeds (i.e., no exception) ---
- -: 1535: pending a check of the auto-value argument if `flags` includes `CHECK_STRUCT_TYPE_DELAY_AUTO_CHECK`.
- -: 1536: The expression itself must have no side-effects except for errors (but the possibility
- -: 1537: of errors means that the expression is not necessarily omittable).
- -: 1538: The resulting *constructor* must always succeed (i.e., no guards).
- -: 1539: The result is the auto-value argument or scheme_true if it's simple, NULL if not.
- -: 1540: The first result of `e` will be a struct type, the second a constructor, and the third a predicate;
- -: 1541: the rest are selectors and mutators. */
- -: 1542:{
- 818252: 1543: int resolved = (flags & CHECK_STRUCT_TYPE_RESOLVED);
- -: 1544:
- 818252: 1545: if (!fuel) return NULL;
- -: 1546:
- 818252: 1547: if (SAME_TYPE(SCHEME_TYPE(e), scheme_application_type)) {
- 104603: 1548: if ((vals == 5) || (vals < 0)) {
- 89586: 1549: Scheme_App_Rec *app = (Scheme_App_Rec *)e;
- -: 1550:
- 89586: 1551: if ((app->num_args >= 4) && (app->num_args <= 11)
- 89586: 1552: && SAME_OBJ(scheme_make_struct_type_proc, app->args[0])) {
- -: 1553: int super_count_plus_one;
- -: 1554:
- 89586: 1555: if (_parent_identity)
- 4845: 1556: *_parent_identity = scheme_null;
- 89586: 1557: if (!SCHEME_FALSEP(app->args[2]))
- 39810: 1558: super_count_plus_one = is_constant_super(app->args[2],
- -: 1559: top_level_consts, inline_variants, top_level_table, runstack,
- 39810: 1560: rs_delta + app->num_args,
- -: 1561: symbols, symbol_table, _parent_identity);
- -: 1562: else
- 49776: 1563: super_count_plus_one = 0;
- -: 1564:
- 89586: 1565: if (SCHEME_SYMBOLP(app->args[1])
- 89586: 1566: && (SCHEME_FALSEP(app->args[2]) /* super */
- 39810: 1567: || super_count_plus_one)
- 83545: 1568: && SCHEME_INTP(app->args[3])
- 83545: 1569: && (SCHEME_INT_VAL(app->args[3]) >= 0)
- 83545: 1570: && SCHEME_INTP(app->args[4])
- 83545: 1571: && (SCHEME_INT_VAL(app->args[4]) >= 0)
- 83545: 1572: && ((app->num_args < 5)
- -: 1573: /* auto-field value: */
- 81710: 1574: || (flags & CHECK_STRUCT_TYPE_DELAY_AUTO_CHECK)
- 81185: 1575: || scheme_omittable_expr(app->args[5], 1, 3, (resolved ? OMITTABLE_RESOLVED : 0), NULL, NULL))
- 83545: 1576: && ((app->num_args < 6)
- -: 1577: /* no properties... */
- 79192: 1578: || SCHEME_NULLP(app->args[6])
- -: 1579: /* ... or properties that might make the `make-struct-type`
- -: 1580: call itself fail, but otherwise don't affect the constructor
- -: 1581: or selectors in a way that matters (although supplying the
- -: 1582: `prop:chaperone-unsafe-undefined` property can affect the
- -: 1583: constructor in an optimizer-irrelevant way) */
- 50158: 1584: || (!(flags & CHECK_STRUCT_TYPE_ALWAYS_SUCCEED)
- 49952: 1585: && scheme_omittable_expr(app->args[6], 1, 4, (resolved ? OMITTABLE_RESOLVED : 0), NULL, NULL))
- 10815: 1586: || ((flags & CHECK_STRUCT_TYPE_ALWAYS_SUCCEED)
- 206: 1587: && is_simple_property_list(app->args[6], resolved,
- -: 1588: top_level_consts, inline_variants,
- -: 1589: top_level_table,
- -: 1590: runstack, rs_delta,
- -: 1591: symbols, symbol_table)))
- 72808: 1592: && ((app->num_args < 7)
- -: 1593: /* inspector: */
- 49035: 1594: || SCHEME_FALSEP(app->args[7])
- 46099: 1595: || (SCHEME_SYMBOLP(app->args[7])
- 3035: 1596: && !strcmp("prefab", SCHEME_SYM_VAL(app->args[7]))
- 3035: 1597: && !SCHEME_SYM_WEIRDP(app->args[7]))
- 43064: 1598: || is_inspector_call(app->args[7]))
- 72784: 1599: && ((app->num_args < 8)
- -: 1600: /* procedure property: */
- 49011: 1601: || SCHEME_FALSEP(app->args[8])
- 13846: 1602: || is_proc_spec_proc(app->args[8], SCHEME_INT_VAL(app->args[3])))
- 68507: 1603: && ((app->num_args < 9)
- -: 1604: /* immutables: */
- 35165: 1605: || is_int_list(app->args[9],
- 35165: 1606: SCHEME_INT_VAL(app->args[3])))
- 68507: 1607: && ((app->num_args < 10)
- -: 1608: /* guard: */
- 29143: 1609: || SCHEME_FALSEP(app->args[10]))
- 61707: 1610: && ((app->num_args < 11)
- -: 1611: /* constructor name: */
- 22343: 1612: || SCHEME_FALSEP(app->args[11])
- 22343: 1613: || SCHEME_SYMBOLP(app->args[11]))) {
- 61707: 1614: if (_auto_e_depth)
- 406: 1615: *_auto_e_depth = (resolved ? app->num_args : 0);
- 61707: 1616: if (_name)
- 3555: 1617: *_name = app->args[1];
- 61707: 1618: if (_stinfo) {
- 25388: 1619: int super_count = (super_count_plus_one
- -: 1620: ? (super_count_plus_one - 1)
- 25388: 1621: : 0);
- 25388: 1622: _stinfo->init_field_count = SCHEME_INT_VAL(app->args[3]) + super_count;
- 50776: 1623: _stinfo->field_count = (SCHEME_INT_VAL(app->args[3])
- 25388: 1624: + SCHEME_INT_VAL(app->args[4])
- -: 1625: + super_count);
- 25388: 1626: _stinfo->uses_super = (super_count_plus_one ? 1 : 0);
- 25388: 1627: _stinfo->super_field_count = (super_count_plus_one ? (super_count_plus_one - 1) : 0);
- 25388: 1628: _stinfo->normal_ops = 1;
- 25388: 1629: _stinfo->indexed_ops = 0;
- 25388: 1630: _stinfo->num_gets = 1;
- 25388: 1631: _stinfo->num_sets = 1;
- -: 1632: }
- 61707: 1633: return ((app->num_args < 5) ? scheme_true : app->args[5]);
- -: 1634: }
- -: 1635: }
- -: 1636: }
- -: 1637: }
- -: 1638:
- 756545: 1639: if (SAME_TYPE(SCHEME_TYPE(e), scheme_ir_let_header_type)) {
- -: 1640: /* check for (let-values ([(: mk ? ref- set-!) (make-struct-type ...)]) (values ...))
- -: 1641: as generated by the expansion of `struct' */
- 633: 1642: Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)e;
- 633: 1643: if ((lh->count == 5) && (lh->num_clauses == 1)) {
- 597: 1644: if (SAME_TYPE(SCHEME_TYPE(lh->body), scheme_ir_let_value_type)) {
- 597: 1645: Scheme_IR_Let_Value *lv = (Scheme_IR_Let_Value *)lh->body;
- 597: 1646: if (SAME_TYPE(SCHEME_TYPE(lv->value), scheme_application_type)) {
- -: 1647: Scheme_Object *auto_e;
- -: 1648: Simple_Stuct_Type_Info stinfo;
- 597: 1649: if (!_stinfo) _stinfo = &stinfo;
- 597: 1650: auto_e = scheme_is_simple_make_struct_type(lv->value, 5, flags,
- -: 1651: _auto_e_depth, _stinfo, _parent_identity,
- -: 1652: top_level_consts, inline_variants, top_level_table,
- -: 1653: runstack, rs_delta,
- -: 1654: symbols, symbol_table,
- -: 1655: _name,
- -: 1656: fuel-1);
- 597: 1657: if (auto_e) {
- -: 1658: /* We have (let-values ([... (make-struct-type)]) ....), so make sure body
- -: 1659: just uses `make-struct-field-{accessor,mutator}'. */
- 409: 1660: if (is_values_with_accessors_and_mutators(lv->body, vals, resolved, _stinfo, lv->vars)) {
- 405: 1661: return auto_e;
- -: 1662: }
- -: 1663: }
- -: 1664: }
- -: 1665: }
- -: 1666: }
- -: 1667: }
- -: 1668:
- 756140: 1669: if (SAME_TYPE(SCHEME_TYPE(e), scheme_let_void_type)) {
- -: 1670: /* same thing, but in resolved form */
- 38148: 1671: Scheme_Let_Void *lvd = (Scheme_Let_Void *)e;
- 38148: 1672: if (lvd->count == 5) {
- 37702: 1673: if (SAME_TYPE(SCHEME_TYPE(lvd->body), scheme_let_value_type)) {
- 37702: 1674: Scheme_Let_Value *lv = (Scheme_Let_Value *)lvd->body;
- 37702: 1675: if ((lv->position == 0) && (lv->count == 5)) {
- -: 1676: Scheme_Object *e2;
- 37702: 1677: e2 = skip_clears(lv->value);
- 37702: 1678: if (SAME_TYPE(SCHEME_TYPE(e2), scheme_application_type)) {
- -: 1679: Scheme_Object *auto_e;
- -: 1680: Simple_Stuct_Type_Info stinfo;
- 37702: 1681: if (!_stinfo) _stinfo = &stinfo;
- 75404: 1682: auto_e = scheme_is_simple_make_struct_type(e2, 5, flags,
- -: 1683: _auto_e_depth, _stinfo, _parent_identity,
- -: 1684: top_level_consts, inline_variants, top_level_table,
- 37702: 1685: runstack, rs_delta + lvd->count,
- -: 1686: symbols, symbol_table,
- -: 1687: _name,
- -: 1688: fuel-1);
- 37702: 1689: if (auto_e) {
- -: 1690: /* We have (let-values ([... (make-struct-type)]) ....), so make sure body
- -: 1691: just uses `make-struct-field-{accessor,mutator}'. */
- 21613: 1692: e2 = skip_clears(lv->body);
- 21613: 1693: if (is_values_with_accessors_and_mutators(e2, vals, resolved, _stinfo, NULL)) {
- 21413: 1694: if (_auto_e_depth) *_auto_e_depth += lvd->count;
- 21413: 1695: return auto_e;
- -: 1696: }
- -: 1697: }
- -: 1698: }
- -: 1699: }
- -: 1700: }
- -: 1701: }
- -: 1702: }
- -: 1703:
- 734727: 1704: return NULL;
- -: 1705:}
- -: 1706:
- 721309: 1707:int scheme_is_simple_make_struct_type_property(Scheme_Object *e, int vals, int flags,
- -: 1708: int *_has_guard,
- -: 1709: Scheme_Hash_Table *top_level_consts,
- -: 1710: Scheme_Hash_Table *inline_variants,
- -: 1711: Scheme_Hash_Table *top_level_table,
- -: 1712: Scheme_Object **runstack, int rs_delta,
- -: 1713: Scheme_Object **symbols, Scheme_Hash_Table *symbol_table,
- -: 1714: int fuel)
- -: 1715:/* Reports whether `app` is a call to `make-struct-type-property` to
- -: 1716: produce a propert with no guard. */
- -: 1717:{
- 721309: 1718: int resolved = (flags & CHECK_STRUCT_TYPE_RESOLVED);
- -: 1719:
- 721309: 1720: if ((vals != 3) && (vals >= 0)) return 0;
- -: 1721:
- 571087: 1722: if (SAME_TYPE(SCHEME_TYPE(e), scheme_application2_type)) {
- 9603: 1723: Scheme_App2_Rec *app = (Scheme_App2_Rec *)e;
- 9603: 1724: if (SAME_OBJ(app->rator, scheme_make_struct_type_property_proc)) {
- 9092: 1725: if (SCHEME_SYMBOLP(app->rand)) {
- 9092: 1726: if (_has_guard) *_has_guard = 0;
- 9092: 1727: return 1;
- -: 1728: }
- -: 1729: }
- -: 1730: }
- -: 1731:
- 561995: 1732: if (SAME_TYPE(SCHEME_TYPE(e), scheme_application3_type)) {
- 7387: 1733: Scheme_App3_Rec *app = (Scheme_App3_Rec *)e;
- 7387: 1734: if (SAME_OBJ(app->rator, scheme_make_struct_type_property_proc)) {
- 7387: 1735: if (SCHEME_SYMBOLP(app->rand1)
- 7387: 1736: && (!(flags & CHECK_STRUCT_TYPE_ALWAYS_SUCCEED)
- 34: 1737: || SCHEME_LAMBDAP(app->rand2))
- 7378: 1738: && (scheme_omittable_expr(app->rator, 1, 4, (resolved ? OMITTABLE_RESOLVED : 0), NULL, NULL))) {
- 7378: 1739: if (_has_guard) *_has_guard = 1;
- 7378: 1740: return 1;
- -: 1741: }
- -: 1742: }
- -: 1743: }
- -: 1744:
- 554617: 1745: return 0;
- -: 1746:}
- -: 1747:
- -: 1748:/*========================================================================*/
- -: 1749:/* more utils */
- -: 1750:/*========================================================================*/
- -: 1751:
- 31556: 1752:intptr_t scheme_get_struct_proc_shape(int k, Simple_Stuct_Type_Info *stinfo)
- -: 1753:{
- 31556: 1754: switch (k) {
- -: 1755: case 0:
- 6168: 1756: if (stinfo->field_count == stinfo->init_field_count)
- 6162: 1757: return STRUCT_PROC_SHAPE_STRUCT | (stinfo->field_count << STRUCT_PROC_SHAPE_SHIFT);
- -: 1758: else
- 6: 1759: return STRUCT_PROC_SHAPE_OTHER;
- -: 1760: break;
- -: 1761: case 1:
- 6172: 1762: return STRUCT_PROC_SHAPE_CONSTR | (stinfo->init_field_count << STRUCT_PROC_SHAPE_SHIFT);
- -: 1763: break;
- -: 1764: case 2:
- 6172: 1765: return STRUCT_PROC_SHAPE_PRED;
- -: 1766: break;
- -: 1767: default:
- 13044: 1768: if (stinfo && stinfo->normal_ops && stinfo->indexed_ops) {
- 6684: 1769: if (k - 3 < stinfo->num_gets) {
- -: 1770: /* record index of field */
- 6524: 1771: return (STRUCT_PROC_SHAPE_GETTER
- 6524: 1772: | ((stinfo->super_field_count + (k - 3)) << STRUCT_PROC_SHAPE_SHIFT));
- -: 1773: } else
- 160: 1774: return (STRUCT_PROC_SHAPE_SETTER | (stinfo->field_count << STRUCT_PROC_SHAPE_SHIFT));
- -: 1775: }
- -: 1776: }
- -: 1777:
- 6360: 1778: return STRUCT_PROC_SHAPE_OTHER;
- -: 1779:}
- -: 1780:
- 14140: 1781:Scheme_Object *scheme_make_struct_proc_shape(intptr_t k, Scheme_Object *identity)
- -: 1782:{
- -: 1783: Scheme_Object *ps;
- -: 1784:
- 14140: 1785: ps = scheme_malloc_small_tagged(sizeof(Scheme_Simple_Object));
- 14140: 1786: ps->type = scheme_struct_proc_shape_type;
- 14140: 1787: SCHEME_PROC_SHAPE_MODE(ps) = k;
- 14140: 1788: SCHEME_PROC_SHAPE_IDENTITY(ps) = identity;
- -: 1789:
- 14140: 1790: return ps;
- -: 1791:}
- -: 1792:
- 4800: 1793:intptr_t scheme_get_struct_property_proc_shape(int k, int has_guard)
- -: 1794:{
- 4800: 1795: switch (k) {
- -: 1796: case 0:
- 1600: 1797: if (has_guard)
- 836: 1798: return STRUCT_PROP_PROC_SHAPE_GUARDED_PROP;
- -: 1799: else
- 764: 1800: return STRUCT_PROP_PROC_SHAPE_PROP;
- -: 1801: case 1:
- 1600: 1802: return STRUCT_PROP_PROC_SHAPE_PRED;
- -: 1803: case 2:
- -: 1804: default:
- 1600: 1805: return STRUCT_PROP_PROC_SHAPE_GETTER;
- -: 1806: }
- -: 1807:}
- -: 1808:
- 528: 1809:Scheme_Object *scheme_make_struct_property_proc_shape(intptr_t k)
- -: 1810:{
- -: 1811: Scheme_Object *ps;
- -: 1812:
- 528: 1813: ps = scheme_alloc_small_object();
- 528: 1814: ps->type = scheme_struct_prop_proc_shape_type;
- 528: 1815: SCHEME_PROP_PROC_SHAPE_MODE(ps) = k;
- -: 1816:
- 528: 1817: return ps;
- -: 1818:}
- -: 1819:
- 3249: 1820:XFORM_NONGCING static int is_struct_identity_subtype(Scheme_Object *sub, Scheme_Object *sup)
- -: 1821:{
- -: 1822: /* A structure identity is a list of symbols, but the symbols are
- -: 1823: just for debugging. Instead, the address of each pair forming the
- -: 1824: list represents an identiity. */
- 7603: 1825: while (SCHEME_PAIRP(sub)) {
- 3617: 1826: if (SAME_OBJ(sub, sup))
- 2512: 1827: return 1;
- 1105: 1828: sub = SCHEME_CDR(sub);
- -: 1829: }
- 737: 1830: return 0;
- -: 1831:}
- -: 1832:
- 11183: 1833:static int single_valued_noncm_function(Scheme_Object *rator, int num_args,
- -: 1834: int s_v, int non_cm)
- -: 1835:{
- 11183: 1836: if (SCHEME_PRIMP(rator)) {
- -: 1837: int opt;
- 4847: 1838: opt = ((Scheme_Prim_Proc_Header *)rator)->flags & SCHEME_PRIM_OPT_MASK;
- 4847: 1839: if (opt >= SCHEME_PRIM_OPT_NONCM)
- 3480: 1840: return 1;
- -: 1841:
- 1367: 1842: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_ALWAYS_ESCAPES)
- #####: 1843: return 1;
- -: 1844:
- -: 1845: /* special cases for values */
- 1367: 1846: if (SAME_OBJ(rator, scheme_values_proc)) {
- 129: 1847: if (s_v && (num_args != 1))
- 10: 1848: return 0;
- 119: 1849: return 1;
- -: 1850: }
- -: 1851: }
- -: 1852:
- 7574: 1853: return 0;
- -: 1854:}
- -: 1855:
- 21186: 1856:static int do_single_valued_noncm_expression(Scheme_Object *expr, int fuel, int s_v, int non_cm)
- -: 1857:/* Not necessarily omittable or copyable expression.
- -: 1858: If `s_v`, the expression must not be single-valued.
- -: 1859: If `non_cm`, the expression must be not sensitive to tail position. In particular,
- -: 1860: it has no with-continuation-mark in tail position, unless the body is omittable.
- -: 1861: The conservative answer is 0. */
- -: 1862:{
- 21186: 1863: if (!s_v && !non_cm)
- #####: 1864: return 1;
- -: 1865:
- 43053: 1866: while (fuel) {
- 21773: 1867: switch (SCHEME_TYPE(expr)) {
- -: 1868: case scheme_ir_local_type:
- -: 1869: case scheme_local_type:
- -: 1870: case scheme_local_unbox_type:
- -: 1871: case scheme_ir_toplevel_type:
- 518: 1872: return 1;
- -: 1873: break;
- -: 1874: case scheme_application_type:
- -: 1875: {
- 547: 1876: Scheme_App_Rec *app = (Scheme_App_Rec *)expr;
- 547: 1877: return single_valued_noncm_function(app->args[0], app->num_args, s_v, non_cm);
- -: 1878: }
- -: 1879: break;
- -: 1880: case scheme_application2_type:
- -: 1881: {
- 7695: 1882: Scheme_App2_Rec *app = (Scheme_App2_Rec *)expr;
- 7695: 1883: return single_valued_noncm_function(app->rator, 1, s_v, non_cm);
- -: 1884: }
- -: 1885: break;
- -: 1886: case scheme_application3_type:
- -: 1887: {
- 2941: 1888: Scheme_App3_Rec *app = (Scheme_App3_Rec *)expr;
- 2941: 1889: return single_valued_noncm_function(app->rator, 2, s_v, non_cm);
- -: 1890: }
- -: 1891: break;
- -: 1892: case scheme_branch_type:
- -: 1893: {
- 461: 1894: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)expr;
- 922: 1895: return (do_single_valued_noncm_expression(b->tbranch, fuel - 1, s_v, non_cm)
- 461: 1896: && do_single_valued_noncm_expression(b->fbranch, fuel - 1, s_v, non_cm));
- -: 1897: }
- -: 1898: break;
- -: 1899: case scheme_ir_let_header_type:
- -: 1900: {
- 269: 1901: Scheme_IR_Let_Header *hl = (Scheme_IR_Let_Header *)expr;
- 269: 1902: expr = hl->body;
- -: 1903: }
- 269: 1904: break;
- -: 1905: case scheme_ir_let_value_type:
- -: 1906: {
- 274: 1907: Scheme_IR_Let_Value *lv = (Scheme_IR_Let_Value *)expr;
- 274: 1908: expr = lv->body;
- -: 1909: }
- 274: 1910: break;
- -: 1911: case scheme_sequence_type:
- -: 1912: {
- 134: 1913: Scheme_Sequence *seq = (Scheme_Sequence *)expr;
- 134: 1914: expr = seq->array[seq->count-1];
- -: 1915: }
- 134: 1916: break;
- -: 1917: case scheme_begin0_sequence_type:
- -: 1918: {
- #####: 1919: Scheme_Sequence *seq = (Scheme_Sequence *)expr;
- #####: 1920: expr = seq->array[0];
- -: 1921: }
- #####: 1922: break;
- -: 1923: case scheme_with_cont_mark_type:
- -: 1924: {
- 99: 1925: Scheme_With_Continuation_Mark * wcm = (Scheme_With_Continuation_Mark *)expr;
- 99: 1926: if (non_cm) {
- -: 1927: /* To avoid being sensitive to tail position, the body must not inspect
- -: 1928: the continuation at all. */
- 95: 1929: return scheme_omittable_expr(wcm->body, s_v ? 1 : -1, 5, 0, NULL, NULL);
- -: 1930: } else {
- 4: 1931: expr = wcm->body;
- -: 1932: }
- -: 1933: }
- 4: 1934: break;
- -: 1935: case scheme_ir_lambda_type:
- -: 1936: case scheme_case_lambda_sequence_type:
- -: 1937: case scheme_set_bang_type:
- 499: 1938: return 1;
- -: 1939: break;
- -: 1940: default:
- 8336: 1941: if (SCHEME_TYPE(expr) > _scheme_ir_values_types_)
- 8336: 1942: return 1;
- #####: 1943: break;
- -: 1944: }
- 681: 1945: fuel--;
- -: 1946: }
- -: 1947:
- 94: 1948: return 0;
- -: 1949:}
- -: 1950:
- 16305: 1951:static int single_valued_noncm_expression(Scheme_Object *expr, int fuel)
- -: 1952:{
- 16305: 1953: return do_single_valued_noncm_expression(expr, fuel, 1, 1);
- -: 1954:}
- -: 1955:
- 3778: 1956:static int single_valued_expression(Scheme_Object *expr, int fuel)
- -: 1957:{
- 3778: 1958: return do_single_valued_noncm_expression(expr, fuel, 1, 0);
- -: 1959:}
- -: 1960:
- 426: 1961:static int noncm_expression(Scheme_Object *expr, int fuel)
- -: 1962:{
- 426: 1963: return do_single_valued_noncm_expression(expr, fuel, 0, 1);
- -: 1964:}
- -: 1965:
- 49097: 1966:static int is_movable_prim(Scheme_Object *rator, int n, int cross_lambda, int cross_k, Optimize_Info *info)
- -: 1967:/* Can we move a call to `rator` relative to other function calls?
- -: 1968: A -1 return means that the arguments must be movable without
- -: 1969: changing space complexity (which is the case for `cons`, for example). */
- -: 1970:{
- 49097: 1971: if (rator && SCHEME_PRIMP(rator)) {
- 41472: 1972: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_IS_UNSAFE_FUNCTIONAL) {
- -: 1973: /* Although it's semantically ok to return -1 even when cross_lambda,
- -: 1974: doing so risks duplicating a computation if the relevant `lambda'
- -: 1975: is later inlined. */
- 16136: 1976: if (cross_lambda) return 0;
- 15691: 1977: if (cross_k
- 9546: 1978: && !(SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_IS_UNSAFE_NONALLOCATE)
- #####: 1979: && (produces_local_type(rator, n) != SCHEME_LOCAL_TYPE_FIXNUM)) {
- #####: 1980: return 0;
- -: 1981: }
- 15691: 1982: return -1;
- -: 1983: }
- -: 1984: }
- -: 1985:
- 32961: 1986: if (SAME_OBJ(scheme_void_proc, rator))
- #####: 1987: return -1;
- -: 1988:
- 32961: 1989: if (!cross_lambda
- 29547: 1990: && !cross_k /* because all calls below allocate */
- -: 1991: /* Note that none of these have space-safety issues, since they
- -: 1992: return values that contain all arguments: */
- 12277: 1993: && (SAME_OBJ(scheme_list_proc, rator)
- 12227: 1994: || (SAME_OBJ(scheme_cons_proc, rator) && (n == 2))
- 12151: 1995: || (SAME_OBJ(scheme_mcons_proc, rator) && (n == 2))
- 12147: 1996: || (SAME_OBJ(scheme_unsafe_cons_list_proc, rator) && (n == 2))
- 12147: 1997: || SAME_OBJ(scheme_list_star_proc, rator)
- 12143: 1998: || SAME_OBJ(scheme_vector_proc, rator)
- 12137: 1999: || SAME_OBJ(scheme_vector_immutable_proc, rator)
- 12137: 2000: || (SAME_OBJ(scheme_box_proc, rator) && (n == 1))
- 12131: 2001: || (SAME_OBJ(scheme_box_immutable_proc, rator) && (n == 1))))
- 148: 2002: return 1;
- -: 2003:
- 32813: 2004: return 0;
- -: 2005:}
- -: 2006:
- 95063: 2007:static int movable_expression(Scheme_Object *expr, Optimize_Info *info,
- -: 2008: int cross_lambda, int cross_k, int cross_s,
- -: 2009: int check_space, int fuel)
- -: 2010:/* A movable expression can't necessarily be constant-folded,
- -: 2011: but can be delayed because it has no side-effects (or is unsafe),
- -: 2012: produces a single value,
- -: 2013: and is not sensitive to being in tail position */
- -: 2014:{
- -: 2015: int can_move;
- -: 2016:
- 95063: 2017: if (fuel < 0) return 0;
- -: 2018:
- 95063: 2019: switch (SCHEME_TYPE(expr)) {
- -: 2020: case scheme_toplevel_type:
- #####: 2021: return ((SCHEME_TOPLEVEL_FLAGS(expr) & SCHEME_TOPLEVEL_FLAGS_MASK) >= SCHEME_TOPLEVEL_FIXED);
- -: 2022: case scheme_ir_quote_syntax_type:
- 14315: 2023: return 1;
- -: 2024: case scheme_ir_local_type:
- -: 2025: {
- -: 2026: /* Ok if not mutable */
- 21297: 2027: if (!SCHEME_VAR(expr)->mutated) {
- 21277: 2028: if (check_space) {
- 10409: 2029: if (SCHEME_VAR(expr)->val_type)
- #####: 2030: return 1;
- -: 2031: /* the value of the identifier might be something that would
- -: 2032: retain significant memory, so we can't delay evaluation */
- 10409: 2033: return 0;
- -: 2034: }
- 10868: 2035: return 1;
- -: 2036: }
- -: 2037: }
- 20: 2038: break;
- -: 2039: case scheme_application_type:
- 2461: 2040: if (!cross_lambda
- 1623: 2041: && !cross_k
- 890: 2042: && (SCHEME_APPN_FLAGS((Scheme_App_Rec *)expr) & APPN_FLAG_OMITTABLE))
- 1: 2043: can_move = -1;
- -: 2044: else
- 2460: 2045: can_move = is_movable_prim(((Scheme_App_Rec *)expr)->args[0], ((Scheme_App_Rec *)expr)->num_args,
- -: 2046: cross_lambda, cross_k, info);
- 2461: 2047: if (can_move) {
- -: 2048: int i;
- 137: 2049: for (i = ((Scheme_App_Rec *)expr)->num_args; i--; ) {
- 84: 2050: if (!movable_expression(((Scheme_App_Rec *)expr)->args[i+1], info,
- -: 2051: cross_lambda, cross_k, cross_s,
- #####: 2052: check_space || (cross_s && (can_move < 0)), fuel - 1))
- 15: 2053: return 0;
- -: 2054: }
- 19: 2055: return 1;
- -: 2056: }
- 2427: 2057: break;
- -: 2058: case scheme_application2_type:
- 29369: 2059: if (!cross_lambda
- 27130: 2060: && !cross_k
- 10691: 2061: && (SCHEME_APPN_FLAGS((Scheme_App2_Rec *)expr) & APPN_FLAG_OMITTABLE))
- 58: 2062: can_move = -1;
- -: 2063: else
- 29311: 2064: can_move = is_movable_prim(((Scheme_App2_Rec *)expr)->rator, 1, cross_lambda, cross_k, info);
- 29369: 2065: if (can_move) {
- 20733: 2066: if (movable_expression(((Scheme_App2_Rec *)expr)->rand, info,
- -: 2067: cross_lambda, cross_k, cross_s,
- 8557: 2068: check_space || (cross_s && (can_move < 0)), fuel - 1))
- 3611: 2069: return 1;
- -: 2070: }
- 25758: 2071: break;
- -: 2072: case scheme_application3_type:
- 17348: 2073: if (!cross_lambda
- 16566: 2074: && !cross_k
- 6922: 2075: && (SCHEME_APPN_FLAGS((Scheme_App3_Rec *)expr) & APPN_FLAG_OMITTABLE))
- 22: 2076: can_move = -1;
- -: 2077: else
- 17326: 2078: can_move = is_movable_prim(((Scheme_App3_Rec *)expr)->rator, 2, cross_lambda, cross_k, info);
- 17348: 2079: if (can_move) {
- 4817: 2080: if (movable_expression(((Scheme_App3_Rec *)expr)->rand1, info,
- -: 2081: cross_lambda, cross_k, cross_s,
- 1103: 2082: check_space || (cross_s && (can_move < 0)), fuel - 1)
- 2601: 2083: && movable_expression(((Scheme_App3_Rec *)expr)->rand2, info,
- -: 2084: cross_lambda, cross_k, cross_s,
- #####: 2085: check_space || (cross_s && (can_move < 0)), fuel - 1))
- 2583: 2086: return 1;
- -: 2087: }
- 14765: 2088: break;
- -: 2089: case scheme_branch_type:
- -: 2090: {
- 5670: 2091: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)expr;
- 5670: 2092: if (movable_expression(b->test, info, cross_lambda, cross_k, cross_s, check_space, fuel-1)
- -: 2093: /* Check space for branches if cross_s, because evaluating `if` eliminates one of them */
- 4220: 2094: && movable_expression(b->tbranch, info, cross_lambda, cross_k, cross_s, check_space || cross_s, fuel-1)
- 350: 2095: && movable_expression(b->fbranch, info, cross_lambda, cross_k, cross_s, check_space || cross_s, fuel-1))
- 105: 2096: return 1;
- -: 2097: }
- 5565: 2098: break;
- -: 2099: case scheme_ir_lambda_type:
- -: 2100: case scheme_case_lambda_sequence_type:
- -: 2101: /* Can't move across lambda or continuation if not closed, since
- -: 2102: that changes allocation of a closure. */
- 180: 2103: return !cross_lambda && !cross_k;
- -: 2104: default:
- 4423: 2105: if (SCHEME_TYPE(expr) > _scheme_ir_values_types_)
- 3923: 2106: return 1;
- -: 2107: }
- -: 2108:
- 49035: 2109: return 0;
- -: 2110:}
- -: 2111:
- 8088: 2112:int scheme_is_ir_lambda(Scheme_Object *o, int can_be_closed, int can_be_liftable)
- -: 2113:{
- 8088: 2114: if (SAME_TYPE(SCHEME_TYPE(o), scheme_ir_lambda_type)) {
- 7552: 2115: if (!can_be_closed || !can_be_liftable) {
- -: 2116: Scheme_Lambda *lam;
- #####: 2117: lam = (Scheme_Lambda *)o;
- -: 2118: /* Because == 0 is like a constant */
- #####: 2119: if (!can_be_closed && !lam->closure_size)
- #####: 2120: return 0;
- -: 2121: /* Because procs that reference only globals are lifted: */
- #####: 2122: if (!can_be_liftable && (lam->closure_size == 1) && lambda_has_top_level(lam))
- #####: 2123: return 0;
- -: 2124: }
- 7552: 2125: return 1;
- -: 2126: } else
- 536: 2127: return 0;
- -: 2128:}
- -: 2129:
- 8: 2130:XFORM_NONGCING static int small_inline_number(Scheme_Object *o)
- -: 2131:{
- 8: 2132: if (SCHEME_BIGNUMP(o))
- #####: 2133: return SCHEME_BIGLEN(o) < 32;
- 8: 2134: else if (SCHEME_COMPLEXP(o))
- #####: 2135: return (small_inline_number(scheme_complex_real_part(o))
- #####: 2136: && small_inline_number(scheme_complex_imaginary_part(o)));
- 8: 2137: else if (SCHEME_RATIONALP(o))
- #####: 2138: return (small_inline_number(scheme_rational_numerator(o))
- #####: 2139: && small_inline_number(scheme_rational_denominator(o)));
- -: 2140: else
- 8: 2141: return 1;
- -: 2142:}
- -: 2143:
- -: 2144:#define STR_INLINE_LIMIT 256
- -: 2145:
- 785285: 2146:int scheme_ir_duplicate_ok(Scheme_Object *fb, int cross_module)
- -: 2147:/* Is the constant a value that we can "copy" in the code? */
- -: 2148:{
- 785285: 2149: return (SCHEME_VOIDP(fb)
- 777372: 2150: || SAME_OBJ(fb, scheme_true)
- 763024: 2151: || SCHEME_FALSEP(fb)
- 715465: 2152: || (SCHEME_SYMBOLP(fb)
- 13437: 2153: && (!cross_module || (!SCHEME_SYM_WEIRDP(fb)
- 409: 2154: && (SCHEME_SYM_LEN(fb) < STR_INLINE_LIMIT))))
- 702028: 2155: || (SCHEME_KEYWORDP(fb)
- 656: 2156: && (!cross_module || (SCHEME_KEYWORD_LEN(fb) < STR_INLINE_LIMIT)))
- 701372: 2157: || SCHEME_EOFP(fb)
- 701286: 2158: || SCHEME_INTP(fb)
- 665033: 2159: || SCHEME_NULLP(fb)
- 649303: 2160: || (!cross_module && SAME_TYPE(SCHEME_TYPE(fb), scheme_ir_toplevel_type))
- 649294: 2161: || (!cross_module && SAME_TYPE(SCHEME_TYPE(fb), scheme_ir_local_type))
- 586417: 2162: || SCHEME_PRIMP(fb)
- -: 2163: /* Values that are hashed by the printer and/or interned on
- -: 2164: read to avoid duplication: */
- 314702: 2165: || SCHEME_CHARP(fb)
- 314425: 2166: || (SCHEME_CHAR_STRINGP(fb)
- 19731: 2167: && (!cross_module || (SCHEME_CHAR_STRLEN_VAL(fb) < STR_INLINE_LIMIT)))
- 294694: 2168: || (SCHEME_BYTE_STRINGP(fb)
- 533: 2169: && (!cross_module || (SCHEME_BYTE_STRLEN_VAL(fb) < STR_INLINE_LIMIT)))
- 294161: 2170: || SAME_TYPE(SCHEME_TYPE(fb), scheme_regexp_type)
- 293537: 2171: || (SCHEME_NUMBERP(fb)
- 1449: 2172: && (!cross_module || small_inline_number(fb)))
- 1077373: 2173: || SAME_TYPE(SCHEME_TYPE(fb), scheme_ctype_type));
- -: 2174:}
- -: 2175:
- -: 2176:/*========================================================================*/
- -: 2177:/* applications, branches, sequences */
- -: 2178:/*========================================================================*/
- -: 2179:
- -: 2180:static Scheme_Object *finish_optimize_application(Scheme_App_Rec *app, Optimize_Info *info, int context);
- -: 2181:static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimize_Info *info, int context);
- -: 2182:static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimize_Info *info, int context);
- -: 2183:
- 108155: 2184:static Scheme_Object *try_optimize_fold(Scheme_Object *f, Scheme_Object *args, Scheme_Object *o, Optimize_Info *info)
- -: 2185:/* If `args` is NULL, extract arguments from `o` */
- -: 2186:{
- 108155: 2187: if (scheme_is_foldable_prim(f)) {
- -: 2188:
- 4423: 2189: if (!args) {
- 4381: 2190: switch (SCHEME_TYPE(o)) {
- -: 2191: case scheme_application_type:
- -: 2192: {
- 10: 2193: Scheme_App_Rec *app = (Scheme_App_Rec *)o;
- -: 2194: int i;
- -: 2195:
- 10: 2196: args = scheme_null;
- 38: 2197: for (i = app->num_args; i--; ) {
- 18: 2198: args = scheme_make_pair(app->args[i + 1], args);
- -: 2199: }
- -: 2200: }
- 10: 2201: break;
- -: 2202: case scheme_application2_type:
- -: 2203: {
- 2540: 2204: Scheme_App2_Rec *app = (Scheme_App2_Rec *)o;
- 2540: 2205: args = scheme_make_pair(app->rand, scheme_null);
- -: 2206: }
- 2540: 2207: break;
- -: 2208: case scheme_application3_type:
- -: 2209: default:
- -: 2210: {
- 1831: 2211: Scheme_App3_Rec *app = (Scheme_App3_Rec *)o;
- 1831: 2212: args = scheme_make_pair(app->rand1,
- -: 2213: scheme_make_pair(app->rand2,
- -: 2214: scheme_null));
- -: 2215: }
- 1831: 2216: break;
- -: 2217: }
- -: 2218: }
- -: 2219:
- 4423: 2220: return scheme_try_apply(f, args, info);
- -: 2221: }
- -: 2222:
- 103732: 2223: return NULL;
- -: 2224:}
- -: 2225:
- 720556: 2226:static int estimate_expr_size(Scheme_Object *expr, int sz, int fuel)
- -: 2227:{
- -: 2228: Scheme_Type t;
- -: 2229:
- 720556: 2230: if (sz > 128)
- 8999: 2231: return sz;
- 711557: 2232: if (fuel < 0)
- 38: 2233: return sz + 128;
- -: 2234:
- 711519: 2235: t = SCHEME_TYPE(expr);
- -: 2236:
- 711519: 2237: switch(t) {
- -: 2238: case scheme_ir_local_type:
- -: 2239: {
- 219968: 2240: sz += 1;
- 219968: 2241: break;
- -: 2242: }
- -: 2243: case scheme_case_lambda_sequence_type:
- -: 2244: {
- 267: 2245: int max_sz = sz + 1, a_sz;
- 267: 2246: Scheme_Case_Lambda *cl = (Scheme_Case_Lambda *)expr;
- -: 2247: int i;
- 1170: 2248: for (i = cl->count; i--; ) {
- 636: 2249: a_sz = estimate_expr_size(cl->array[i], sz, fuel);
- 636: 2250: if (a_sz > max_sz) max_sz = a_sz;
- -: 2251: }
- 267: 2252: sz = max_sz;
- -: 2253: }
- 267: 2254: break;
- -: 2255: case scheme_application2_type:
- -: 2256: {
- 100306: 2257: Scheme_App2_Rec *app = (Scheme_App2_Rec *)expr;
- -: 2258:
- 100306: 2259: sz = estimate_expr_size(app->rator, sz, fuel - 1);
- 100306: 2260: sz = estimate_expr_size(app->rand, sz, fuel - 1);
- 100306: 2261: sz++;
- -: 2262:
- 100306: 2263: break;
- -: 2264: }
- -: 2265: case scheme_application_type:
- -: 2266: {
- 23538: 2267: Scheme_App_Rec *app = (Scheme_App_Rec *)expr;
- -: 2268: int i;
- -: 2269:
- 142538: 2270: for (i = app->num_args + 1; i--; ) {
- 95462: 2271: sz = estimate_expr_size(app->args[i], sz, fuel - 1);
- -: 2272: }
- 23538: 2273: sz++;
- -: 2274:
- 23538: 2275: break;
- -: 2276: }
- -: 2277: case scheme_application3_type:
- -: 2278: {
- 47394: 2279: Scheme_App3_Rec *app = (Scheme_App3_Rec *)expr;
- -: 2280:
- 47394: 2281: sz = estimate_expr_size(app->rator, sz, fuel - 1);
- 47394: 2282: sz = estimate_expr_size(app->rand1, sz, fuel - 1);
- 47394: 2283: sz = estimate_expr_size(app->rand2, sz, fuel - 1);
- 47394: 2284: sz++;
- -: 2285:
- 47394: 2286: break;
- -: 2287: }
- -: 2288: case scheme_ir_let_header_type:
- -: 2289: {
- 36783: 2290: Scheme_IR_Let_Header *head = (Scheme_IR_Let_Header *)expr;
- -: 2291: Scheme_Object *body;
- -: 2292: Scheme_IR_Let_Value *lv;
- -: 2293: int i;
- -: 2294:
- 36783: 2295: body = head->body;
- 118015: 2296: for (i = head->num_clauses; i--; ) {
- 44449: 2297: lv = (Scheme_IR_Let_Value *)body;
- 44449: 2298: sz = estimate_expr_size(lv->value, sz, fuel - 1);
- 44449: 2299: body = lv->body;
- 44449: 2300: sz++;
- -: 2301: }
- 36783: 2302: sz = estimate_expr_size(body, sz, fuel - 1);
- 36783: 2303: break;
- -: 2304: }
- -: 2305: case scheme_sequence_type:
- -: 2306: case scheme_begin0_sequence_type:
- -: 2307: {
- 7253: 2308: Scheme_Sequence *seq = (Scheme_Sequence *)expr;
- -: 2309: int i;
- -: 2310:
- 32349: 2311: for (i = seq->count; i--; ) {
- 17843: 2312: sz = estimate_expr_size(seq->array[i], sz, fuel - 1);
- -: 2313: }
- -: 2314:
- 7253: 2315: break;
- -: 2316: }
- -: 2317: case scheme_branch_type:
- -: 2318: {
- 48026: 2319: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)expr;
- -: 2320:
- 48026: 2321: sz = estimate_expr_size(b->test, sz, fuel - 1);
- 48026: 2322: sz = estimate_expr_size(b->tbranch, sz, fuel - 1);
- 48026: 2323: sz = estimate_expr_size(b->fbranch, sz, fuel - 1);
- 48026: 2324: break;
- -: 2325: }
- -: 2326: case scheme_ir_lambda_type:
- -: 2327: {
- 23684: 2328: sz = estimate_expr_size(((Scheme_Lambda *)expr)->body, sz, fuel - 1);
- 23684: 2329: sz++;
- 23684: 2330: break;
- -: 2331: }
- -: 2332: case scheme_ir_toplevel_type:
- -: 2333: case scheme_ir_quote_syntax_type:
- -: 2334: /* FIXME: other syntax types not covered */
- -: 2335: default:
- 204300: 2336: sz += 1;
- 204300: 2337: break;
- -: 2338: }
- -: 2339:
- 711519: 2340: return sz;
- -: 2341:}
- -: 2342:
- 14827: 2343:static Scheme_Object *estimate_closure_size(Scheme_Object *e)
- -: 2344:{
- -: 2345: Scheme_Object *wbl;
- -: 2346: int sz;
- 14827: 2347: sz = estimate_expr_size(e, 0, 32);
- -: 2348:
- 14827: 2349: wbl = scheme_alloc_object();
- 14827: 2350: wbl->type = scheme_will_be_lambda_type;
- 14827: 2351: SCHEME_WILL_BE_LAMBDA_SIZE(wbl) = sz;
- 14827: 2352: SCHEME_WILL_BE_LAMBDA(wbl) = e;
- -: 2353:
- 14827: 2354: return wbl;
- -: 2355:}
- -: 2356:
- 184990: 2357:static Scheme_Object *no_potential_size(Scheme_Object *v)
- -: 2358:{
- 184990: 2359: if (v && SCHEME_WILL_BE_LAMBDAP(v))
- 9229: 2360: return NULL;
- -: 2361: else
- 175761: 2362: return v;
- -: 2363:}
- -: 2364:
- 54464: 2365:static Scheme_Object *apply_inlined(Scheme_Lambda *lam, Optimize_Info *info,
- -: 2366: int argc, Scheme_App_Rec *app, Scheme_App2_Rec *app2, Scheme_App3_Rec *app3,
- -: 2367: int context, Scheme_Object *orig, Scheme_Object *le_prev,
- -: 2368: int single_use)
- -: 2369:/* Optimize the body of `lam` given the known arguments in `app`, `app2`, or `app3` */
- -: 2370:{
- -: 2371: Scheme_IR_Let_Header *lh;
- 54464: 2372: Scheme_IR_Let_Value *lv, *prev = NULL;
- -: 2373: Scheme_Object *val;
- -: 2374: int i, expected;
- -: 2375: Optimize_Info *sub_info;
- -: 2376: Scheme_IR_Local **vars;
- 54464: 2377: Scheme_Object *p = lam->body;
- -: 2378:
- 54464: 2379: expected = lam->num_params;
- -: 2380:
- 54464: 2381: if (!expected) {
- -: 2382: /* No arguments, so no need for a `let` wrapper: */
- 2916: 2383: sub_info = optimize_info_add_frame(info, 0, 0, 0);
- 2916: 2384: if (!single_use || lam->ir_info->is_dup)
- 2289: 2385: sub_info->inline_fuel >>= 1;
- 2916: 2386: p = scheme_optimize_expr(p, sub_info, context);
- 2916: 2387: info->single_result = sub_info->single_result;
- 2916: 2388: info->preserves_marks = sub_info->preserves_marks;
- 2916: 2389: optimize_info_done(sub_info, NULL);
- 2916: 2390: merge_types(sub_info, info, NULL);
- -: 2391:
- 2916: 2392: return replace_tail_inside(p, le_prev, orig);
- -: 2393: }
- -: 2394:
- 51548: 2395: lh = MALLOC_ONE_TAGGED(Scheme_IR_Let_Header);
- 51548: 2396: lh->iso.so.type = scheme_ir_let_header_type;
- 51548: 2397: lh->count = expected;
- 51548: 2398: lh->num_clauses = expected;
- -: 2399:
- 161036: 2400: for (i = 0; i < expected; i++) {
- 109488: 2401: lv = MALLOC_ONE_TAGGED(Scheme_IR_Let_Value);
- 109488: 2402: lv->iso.so.type = scheme_ir_let_value_type;
- 109488: 2403: lv->count = 1;
- -: 2404:
- 109488: 2405: vars = MALLOC_N(Scheme_IR_Local*, 1);
- 109488: 2406: vars[0] = lam->ir_info->vars[i];
- 109488: 2407: lv->vars = vars;
- -: 2408:
- 109488: 2409: if ((i == expected - 1)
- 52428: 2410: && (SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_HAS_REST)) {
- -: 2411: int j;
- 880: 2412: Scheme_Object *l = scheme_null;
- -: 2413:
- 3827: 2414: for (j = argc; j-- > i; ) {
- 2067: 2415: if (app)
- 1813: 2416: val = app->args[j + 1];
- 254: 2417: else if (app3)
- 243: 2418: val = (j ? app3->rand2 : app3->rand1);
- 11: 2419: else if (app2)
- 11: 2420: val = app2->rand;
- -: 2421: else
- #####: 2422: val = scheme_false;
- -: 2423:
- 2067: 2424: l = scheme_make_pair(val, l);
- -: 2425: }
- 880: 2426: l = scheme_make_pair(scheme_list_proc, l);
- 880: 2427: val = scheme_make_application(l, info);
- 108608: 2428: } else if (app)
- 40763: 2429: val = app->args[i + 1];
- 67845: 2430: else if (app3)
- 52345: 2431: val = (i ? app3->rand2 : app3->rand1);
- -: 2432: else
- 15500: 2433: val = app2->rand;
- -: 2434:
- 109488: 2435: lv->value = val;
- -: 2436:
- 109488: 2437: if (prev)
- 57940: 2438: prev->body = (Scheme_Object *)lv;
- -: 2439: else
- 51548: 2440: lh->body = (Scheme_Object *)lv;
- 109488: 2441: prev = lv;
- -: 2442: }
- -: 2443:
- 51548: 2444: if (prev)
- 51548: 2445: prev->body = p;
- -: 2446: else
- #####: 2447: lh->body = p;
- -: 2448:
- 51548: 2449: sub_info = optimize_info_add_frame(info, 0, 0, 0);
- 51548: 2450: if (!single_use || lam->ir_info->is_dup)
- 51008: 2451: sub_info->inline_fuel >>= 1;
- -: 2452:
- 51548: 2453: p = optimize_lets((Scheme_Object *)lh, sub_info, context);
- -: 2454:
- 51548: 2455: info->single_result = sub_info->single_result;
- 51548: 2456: info->preserves_marks = sub_info->preserves_marks;
- 51548: 2457: optimize_info_done(sub_info, NULL);
- 51548: 2458: merge_types(sub_info, info, NULL);
- -: 2459:
- 51548: 2460: return replace_tail_inside(p, le_prev, orig);
- -: 2461:}
- -: 2462:
- 1393930: 2463:int scheme_check_leaf_rator(Scheme_Object *le)
- -: 2464:{
- 1393930: 2465: if (le && SCHEME_PRIMP(le)) {
- -: 2466: int opt;
- 1279362: 2467: opt = ((Scheme_Prim_Proc_Header *)le)->flags & SCHEME_PRIM_OPT_MASK;
- 1279362: 2468: if (opt >= SCHEME_PRIM_OPT_IMMEDIATE)
- 1004986: 2469: return 1;
- -: 2470: }
- 388944: 2471: return 0;
- -: 2472:}
- -: 2473:
- 922069: 2474:int scheme_get_rator_flags(Scheme_Object *le)
- -: 2475:{
- 922069: 2476: if (!le) {
- 228339: 2477: return 0;
- 768473: 2478: } else if (SCHEME_PRIMP(le)) {
- -: 2479: int opt;
- 623362: 2480: opt = ((Scheme_Prim_Proc_Header *)le)->flags & SCHEME_PRIM_OPT_MASK;
- 623362: 2481: if (opt >= SCHEME_PRIM_OPT_NONCM) {
- 548619: 2482: return (LAMBDA_PRESERVES_MARKS | LAMBDA_SINGLE_RESULT);
- -: 2483: }
- 70368: 2484: } else if (SAME_TYPE(SCHEME_TYPE(le), scheme_ir_lambda_type)) {
- 70110: 2485: Scheme_Lambda *lam = (Scheme_Lambda *)le;
- 70110: 2486: return SCHEME_LAMBDA_FLAGS(lam);
- -: 2487: }
- 75001: 2488: return 0;
- -: 2489:}
- -: 2490:
- 1286874: 2491:int check_single_use(Scheme_Object *var)
- -: 2492:{
- 1286874: 2493: Scheme_IR_Local *v = SCHEME_VAR(var);
- -: 2494:
- 2573748: 2495: return ((v->use_count == 1)
- -: 2496: /* If we're outside the binding, then the binding
- -: 2497: itself will remain as a used: */
- 124390: 2498: && !v->optimize_outside_binding
- -: 2499: /* To help avoid infinite unrolling,
- -: 2500: don't count a self use as "single" use. */
- 1411115: 2501: && !v->optimize_unready);
- -: 2502:}
- -: 2503:
- #####: 2504:int check_potential_size(Scheme_Object *var)
- -: 2505:{
- -: 2506: Scheme_Object* n;
- -: 2507:
- #####: 2508: n = SCHEME_VAR(var)->optimize.known_val;
- #####: 2509: if (n && SCHEME_WILL_BE_LAMBDAP(n)) {
- #####: 2510: return SCHEME_WILL_BE_LAMBDA_SIZE(n);
- -: 2511: }
- -: 2512:
- #####: 2513: return 0;
- -: 2514:}
- -: 2515:
- 4119694: 2516:Scheme_Object *do_lookup_constant_proc(Optimize_Info *info, Scheme_Object *le,
- -: 2517: int argc, int for_inline, int *_single_use)
- -: 2518:/* Return a known procedure, if any.
- -: 2519: When argc == -1 it may return a case-lambda. Else, it will check the arity
- -: 2520: and split a case-lambda to extact the relevant lambda. If the arity is
- -: 2521: wrong the result is scheme_true.
- -: 2522: If for_inline, it may return a potential size. Else, itwill go inside
- -: 2523: potecial sizes, noinline procedures, lets, begins and other construction,
- -: 2524: so the result can't be inlined and must be used only to get the properties
- -: 2525: of the actual procedure.*/
- -: 2526:
- -: 2527:{
- 4119694: 2528: Scheme_Object *prev = NULL;
- -: 2529:
- 4119694: 2530: *_single_use = 0;
- -: 2531:
- -: 2532: /* Move inside `let' bindings to get the inner procedure */
- 4119694: 2533: if (!for_inline)
- 2209268: 2534: extract_tail_inside(&le, &prev);
- -: 2535:
- 4119694: 2536: le = extract_specialized_proc(le, le);
- -: 2537:
- 4119694: 2538: if (SCHEME_LAMBDAP(le)) {
- -: 2539: /* Found a `((lambda' */
- 1001: 2540: *_single_use = 1;
- -: 2541: }
- -: 2542:
- 4119694: 2543: if (SAME_TYPE(SCHEME_TYPE(le), scheme_ir_local_type)) {
- -: 2544: int tmp;
- 1286874: 2545: tmp = check_single_use(le);
- 1286874: 2546: *_single_use = tmp;
- 1286874: 2547: if ((SCHEME_VAR(le)->mode != SCHEME_VAR_MODE_OPTIMIZE)) {
- -: 2548: /* We got a local that is bound in a let that is not yet optimized. */
- #####: 2549: return NULL;
- -: 2550: }
- 1286874: 2551: le = SCHEME_VAR(le)->optimize.known_val;
- 1286874: 2552: if (!le)
- 1094134: 2553: return NULL;
- -: 2554: }
- -: 2555:
- 6148398: 2556: while (SAME_TYPE(SCHEME_TYPE(le), scheme_ir_toplevel_type)) {
- -: 2557: int pos;
- 793727: 2558: pos = SCHEME_TOPLEVEL_POS(le);
- 793727: 2559: *_single_use = 0;
- 793727: 2560: if (info->cp->inline_variants) {
- -: 2561: Scheme_Object *iv;
- 497141: 2562: iv = scheme_hash_get(info->cp->inline_variants, scheme_make_integer(pos));
- 497141: 2563: if (iv && SCHEME_TRUEP(iv)) {
- 61006: 2564: Scheme_Hash_Table *iv_ht = NULL;
- 61006: 2565: if (SCHEME_HASHTP(iv)) {
- 9782: 2566: iv_ht = (Scheme_Hash_Table *)iv;
- 9782: 2567: iv = scheme_hash_get(iv_ht, scheme_make_integer(argc));
- 9782: 2568: if (!iv)
- 290: 2569: iv = scheme_hash_get(iv_ht, scheme_false);
- -: 2570: }
- 61006: 2571: if (SAME_TYPE(SCHEME_TYPE(iv), scheme_vector_type)) { /* inline variant + shift info */
- 18646: 2572: int has_cases = 0;
- 18646: 2573: Scheme_Object *orig_iv = iv;
- -: 2574: MZ_ASSERT(SAME_TYPE(scheme_inline_variant_type, SCHEME_TYPE(SCHEME_VEC_ELS(iv)[0])));
- -: 2575: /* unresolving may add new top-levels to `info->cp`: */
- 37292: 2576: iv = scheme_unresolve(SCHEME_VEC_ELS(iv)[0], argc, &has_cases,
- 18646: 2577: info->cp, info->env, info->insp, SCHEME_INT_VAL(SCHEME_VEC_ELS(iv)[3]),
- -: 2578: SCHEME_VEC_ELS(iv)[1], SCHEME_VEC_ELS(iv)[2]);
- 18646: 2579: if (has_cases) {
- 1346: 2580: if (!iv_ht) {
- 1056: 2581: iv_ht = scheme_make_hash_table(SCHEME_hash_ptr);
- 1056: 2582: scheme_hash_set(iv_ht, scheme_false, orig_iv);
- 1056: 2583: scheme_hash_set(info->cp->inline_variants, scheme_make_integer(pos), (Scheme_Object *)iv_ht);
- -: 2584: }
- 1346: 2585: scheme_hash_set(iv_ht, scheme_make_integer(argc), iv ? iv : scheme_false);
- -: 2586: } else
- 17300: 2587: scheme_hash_set(info->cp->inline_variants, scheme_make_integer(pos), iv ? iv : scheme_false);
- -: 2588: }
- 61006: 2589: if (iv && SCHEME_TRUEP(iv)) {
- 58815: 2590: le = iv;
- 58815: 2591: break;
- -: 2592: }
- -: 2593: }
- -: 2594: }
- 734912: 2595: if (SAME_TYPE(SCHEME_TYPE(le), scheme_ir_toplevel_type) && info->top_level_consts) {
- 279784: 2596: le = scheme_hash_get(info->top_level_consts, scheme_make_integer(pos));
- 279784: 2597: if (!le)
- 182506: 2598: return NULL;
- -: 2599: } else
- -: 2600: break;
- -: 2601: }
- -: 2602:
- 2843054: 2603: if (SCHEME_WILL_BE_LAMBDAP(le)) {
- 92753: 2604: if (for_inline)
- 38468: 2605: return le;
- -: 2606: else
- 54285: 2607: le = SCHEME_WILL_BE_LAMBDA(le);
- -: 2608: }
- -: 2609:
- 2804586: 2610: if (!for_inline && SAME_TYPE(scheme_noninline_proc_type, SCHEME_TYPE(le))) {
- 3811: 2611: le = SCHEME_BOX_VAL(le);
- -: 2612: }
- -: 2613:
- -: 2614:
- 2804586: 2615: if (SAME_TYPE(SCHEME_TYPE(le), scheme_case_lambda_sequence_type)) {
- 2425: 2616: Scheme_Case_Lambda *cl = (Scheme_Case_Lambda *)le;
- -: 2617: Scheme_Object *cp;
- -: 2618: int i, count;
- -: 2619:
- 2425: 2620: if (argc == -1)
- 854: 2621: return le;
- -: 2622:
- 1571: 2623: count = cl->count;
- 2890: 2624: for (i = 0; i < count; i++) {
- 2874: 2625: cp = cl->array[i];
- 4193: 2626: if (SAME_TYPE(SCHEME_TYPE(cp), scheme_ir_lambda_type)) {
- 2874: 2627: Scheme_Lambda *lam = (Scheme_Lambda *)cp;
- 2874: 2628: if ((lam->num_params == argc)
- 1375: 2629: || ((SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_HAS_REST)
- 56: 2630: && (argc + 1 >= lam->num_params))) {
- 1555: 2631: return cp;
- -: 2632: }
- -: 2633: } else {
- #####: 2634: scheme_signal_error("internal error: strange case-lambda");
- -: 2635: }
- -: 2636: }
- 16: 2637: if (i >= count) {
- 16: 2638: return scheme_true;
- -: 2639: }
- -: 2640: }
- -: 2641:
- 2802161: 2642: if (SAME_TYPE(SCHEME_TYPE(le), scheme_ir_lambda_type)) {
- 269016: 2643: Scheme_Lambda *lam = (Scheme_Lambda *)le;
- -: 2644:
- 269016: 2645: if (argc == -1)
- 46187: 2646: return le;
- -: 2647:
- 222829: 2648: if ((lam->num_params == argc)
- 2467: 2649: || ((SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_HAS_REST)
- 2003: 2650: && (argc + 1 >= lam->num_params))) {
- 222361: 2651: return le;
- -: 2652: } else {
- 468: 2653: return scheme_true;
- -: 2654: }
- -: 2655: }
- -: 2656:
- 2533145: 2657: if (SCHEME_PROCP(le)) {
- -: 2658: Scheme_Object *a[1];
- -: 2659:
- 1882083: 2660: if (argc == -1)
- 183: 2661: return le;
- -: 2662:
- 1881900: 2663: a[0] = le;
- 1881900: 2664: if (scheme_check_proc_arity(NULL, argc, 0, 1, a))
- 1881698: 2665: return le;
- -: 2666: else
- 202: 2667: return scheme_true;
- -: 2668: }
- -: 2669:
- 651062: 2670: return NULL;
- -: 2671:}
- -: 2672:
- 2209268: 2673:Scheme_Object *lookup_constant_proc(Optimize_Info *info, Scheme_Object *le, int argc)
- -: 2674:{
- 2209268: 2675: int single_use = 0;
- 2209268: 2676: return do_lookup_constant_proc(info, le, argc, 0, &single_use);
- -: 2677:}
- -: 2678:
- -: 2679:#if 0
- -: 2680:# define LOG_INLINE(x) x
- -: 2681:#else
- -: 2682:# define LOG_INLINE(x) /*empty*/
- -: 2683:#endif
- -: 2684:
- 1910580: 2685:Scheme_Object *optimize_for_inline(Optimize_Info *info, Scheme_Object *le, int argc,
- -: 2686: Scheme_App_Rec *app, Scheme_App2_Rec *app2, Scheme_App3_Rec *app3,
- -: 2687: int context, int optimized_rator)
- -: 2688:/* One of app, app2 and app3 should be non-NULL.
- -: 2689: If app, we're inlining a general application. If app2, we're inlining an
- -: 2690: application with a single argument and if app3, we're inlining an
- -: 2691: application with two arguments. */
- -: 2692:{
- 1910580: 2693: int single_use = 0, psize = 0;
- 1910580: 2694: Scheme_Object *prev = NULL, *orig_le = le, *le2;
- 1910580: 2695: int already_opt = optimized_rator;
- -: 2696:
- 1910580: 2697: if ((info->inline_fuel < 0) && info->has_nonleaf)
- 124: 2698: return NULL;
- -: 2699:
- -: 2700: /* Move inside `let' bindings, so we can convert ((let (....) proc) arg ...)
- -: 2701: to (let (....) (proc arg ...)) */
- 1910456: 2702: if (already_opt)
- 928103: 2703: extract_tail_inside(&le, &prev);
- -: 2704:
- 1910456: 2705: le = extract_specialized_proc(le, le);
- -: 2706:
- 1910456: 2707: if (!already_opt
- 982353: 2708: && SCHEME_LAMBDAP(le)) {
- -: 2709: /* We have an immediate `lambda' that wasn't optimized, yet.
- -: 2710: Go optimize it, first. */
- 30: 2711: return NULL;
- -: 2712: }
- -: 2713:
- 1910426: 2714: le2 = le;
- 1910426: 2715: le = do_lookup_constant_proc(info, le, argc, 1, &single_use);
- -: 2716:
- 1910426: 2717: if (!le) {
- 460811: 2718: info->has_nonleaf = 1;
- 460811: 2719: return NULL;
- -: 2720: }
- -: 2721:
- 1449615: 2722: if (SCHEME_WILL_BE_LAMBDAP(le)) {
- 38468: 2723: psize = SCHEME_WILL_BE_LAMBDA_SIZE(le);
- -: 2724: LOG_INLINE(fprintf(stderr, "Potential inline %d %d\n", psize, info->inline_fuel * (argc + 2)));
- -: 2725: /* If we inline, the enclosing function will get larger, so we increase
- -: 2726: its potential size. */
- 38468: 2727: if (psize <= (info->inline_fuel * (argc + 2)))
- 2764: 2728: info->psize += psize;
- 38468: 2729: info->has_nonleaf = 1;
- 38468: 2730: return NULL;
- -: 2731: }
- -: 2732:
- 1411147: 2733: if (SAME_OBJ(le, scheme_true)) {
- -: 2734: /* wrong arity */
- -: 2735: int len;
- -: 2736: const char *pname, *context;
- 328: 2737: info->escapes = 1;
- 328: 2738: le2 = lookup_constant_proc(info, le2, -1);
- 328: 2739: pname = scheme_get_proc_name(le2, &len, 0);
- 328: 2740: context = scheme_optimize_context_to_string(info->context);
- 328: 2741: scheme_log(info->logger,
- -: 2742: SCHEME_LOG_WARNING,
- -: 2743: 0,
- -: 2744: "warning%s: optimizer detects procedure incorrectly applied to %d arguments%s%s",
- -: 2745: context,
- -: 2746: argc,
- -: 2747: pname ? ": " : "",
- -: 2748: pname ? pname : "");
- 328: 2749: return NULL;
- -: 2750: }
- -: 2751:
- 1410819: 2752: if (SAME_TYPE(SCHEME_TYPE(le), scheme_ir_lambda_type) && (info->inline_fuel >= 0)) {
- 152461: 2753: Scheme_Lambda *lam = (Scheme_Lambda *)le;
- 152461: 2754: int sz, threshold, is_leaf = 0;
- -: 2755:
- 152461: 2756: sz = lambda_body_size_plus_info(lam, 1, info, &is_leaf);
- 152461: 2757: if (is_leaf) {
- -: 2758: /* encourage inlining of leaves: */
- 5346: 2759: sz >>= 2;
- -: 2760: }
- 152461: 2761: threshold = info->inline_fuel * (2 + argc);
- -: 2762:
- -: 2763: /* Do we have enough fuel? */
- 156443: 2764: if ((sz >= 0) && (single_use || (sz <= threshold))) {
- -: 2765: Optimize_Info *sub_info;
- 58447: 2766: sub_info = info;
- -: 2767:
- -: 2768: /* If optimize_clone succeeds, inlining succeeds. */
- 58447: 2769: le = optimize_clone(single_use, (Scheme_Object *)lam, sub_info, empty_eq_hash_tree, 0);
- -: 2770:
- 58447: 2771: if (le) {
- -: 2772: LOG_INLINE(fprintf(stderr, "Inline %d[%d]<=%d@%d %d %s\n", sz, is_leaf, threshold, info->inline_fuel,
- -: 2773: single_use, scheme_write_to_string(lam->name ? lam->name : scheme_false, NULL)));
- 108929: 2774: scheme_log(info->logger,
- -: 2775: SCHEME_LOG_DEBUG,
- -: 2776: 0,
- -: 2777: "inlining %s size: %d threshold: %d#<separator>%s",
- 54464: 2778: scheme_write_to_string(lam->name ? lam->name : scheme_false, NULL),
- -: 2779: sz,
- -: 2780: threshold,
- -: 2781: scheme_optimize_context_to_string(info->context));
- 54464: 2782: le = apply_inlined((Scheme_Lambda *)le, sub_info, argc, app, app2, app3, context,
- -: 2783: orig_le, prev, single_use);
- 54464: 2784: return le;
- -: 2785: } else {
- -: 2786: LOG_INLINE(fprintf(stderr, "No inline %s\n", scheme_write_to_string(lam->name ? lam->name : scheme_false, NULL)));
- 7964: 2787: scheme_log(info->logger,
- -: 2788: SCHEME_LOG_DEBUG,
- -: 2789: 0,
- -: 2790: "no-inlining %s size: %d threshold: %d#<separator>%s",
- 3982: 2791: scheme_write_to_string(lam->name ? lam->name : scheme_false, NULL),
- -: 2792: sz,
- -: 2793: threshold,
- -: 2794: scheme_optimize_context_to_string(info->context));
- -: 2795: }
- -: 2796: } else {
- -: 2797: LOG_INLINE(fprintf(stderr, "No fuel %s %d[%d]>%d@%d %d\n", scheme_write_to_string(lam->name ? lam->name : scheme_false, NULL),
- -: 2798: sz, is_leaf, threshold,
- -: 2799: info->inline_fuel, info->use_psize));
- 188028: 2800: scheme_log(info->logger,
- -: 2801: SCHEME_LOG_DEBUG,
- -: 2802: 0,
- -: 2803: "out-of-fuel %s size: %d threshold: %d#<separator>%s",
- 94014: 2804: scheme_write_to_string(lam->name ? lam->name : scheme_false, NULL),
- -: 2805: sz,
- -: 2806: threshold,
- -: 2807: scheme_optimize_context_to_string(info->context));
- -: 2808: }
- -: 2809: }
- -: 2810:
- 1356354: 2811: if (!scheme_check_leaf_rator(le))
- 356434: 2812: info->has_nonleaf = 1;
- -: 2813:
- 1356354: 2814: return NULL;
- -: 2815:}
- -: 2816:
- 76: 2817:static int is_local_type_expression(Scheme_Object *expr, Optimize_Info *info)
- -: 2818:/* Get an unboxing type (e.g., flonum) for `expr` */
- -: 2819:{
- 76: 2820: return scheme_predicate_to_local_type(expr_implies_predicate(expr, info));
- -: 2821:}
- -: 2822:
- 925376: 2823:static void register_local_argument_types(Scheme_App_Rec *app, Scheme_App2_Rec *app2, Scheme_App3_Rec *app3,
- -: 2824: Optimize_Info *info)
- -: 2825:/* If `rator` is a variable bound to a `lambda`, record the types of actual arguments
- -: 2826: provided in a function call. If all calls are consistent with unboxing, then the
- -: 2827: procedure will accept unboxed arguments at run time. */
- -: 2828:{
- -: 2829: Scheme_Object *rator, *rand, *le;
- -: 2830: int n, i, nth_app;
- -: 2831:
- 925376: 2832: if (app) {
- 143323: 2833: rator = app->args[0];
- 143323: 2834: n = app->num_args;
- 143323: 2835: nth_app = SCHEME_APPN_FLAGS(app) & APPN_POSITION_MASK;
- 782053: 2836: } else if (app2) {
- 514755: 2837: rator = app2->rator;
- 514755: 2838: n = 1;
- 514755: 2839: nth_app = SCHEME_APPN_FLAGS(app2) & APPN_POSITION_MASK;
- -: 2840: } else {
- 267298: 2841: rator = app3->rator;
- 267298: 2842: n = 2;
- 267298: 2843: nth_app = SCHEME_APPN_FLAGS(app3) & APPN_POSITION_MASK;
- -: 2844: }
- -: 2845:
- 925376: 2846: if (SAME_TYPE(SCHEME_TYPE(rator), scheme_ir_local_type)) {
- 112117: 2847: le = optimize_info_lookup(rator);
- 112117: 2848: if (le && SCHEME_WILL_BE_LAMBDAP(le))
- 15415: 2849: le = SCHEME_WILL_BE_LAMBDA(le);
- -: 2850:
- 112117: 2851: if (le && SAME_TYPE(SCHEME_TYPE(le), scheme_ir_lambda_type)) {
- 60840: 2852: Scheme_Lambda *lam = (Scheme_Lambda *)le;
- 60840: 2853: if ((lam->num_params == n)
- 60392: 2854: && !(SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_HAS_REST)) {
- -: 2855: Scheme_Object *pred;
- -: 2856:
- 60092: 2857: if (!lam->ir_info->arg_types) {
- -: 2858: Scheme_Object **arg_types;
- -: 2859: short *contributors;
- 6246: 2860: arg_types = MALLOC_N(Scheme_Object*, n);
- 6246: 2861: lam->ir_info->arg_types = arg_types;
- 6246: 2862: contributors = MALLOC_N_ATOMIC(short, n);
- 6246: 2863: memset(contributors, 0, sizeof(short) * n);
- 6246: 2864: lam->ir_info->arg_type_contributors = contributors;
- -: 2865: }
- -: 2866:
- 170955: 2867: for (i = 0; i < n; i++) {
- 110863: 2868: if (app)
- 50660: 2869: rand = app->args[i+1];
- 60203: 2870: else if (app2)
- 28373: 2871: rand = app2->rand;
- -: 2872: else {
- 31830: 2873: if (!i)
- 15915: 2874: rand = app3->rand1;
- -: 2875: else
- 15915: 2876: rand = app3->rand2;
- -: 2877: }
- -: 2878:
- 110863: 2879: if (lam->ir_info->arg_types[i]
- 81642: 2880: || !lam->ir_info->arg_type_contributors[i]) {
- 60287: 2881: int widen_to_top = 0;
- -: 2882:
- 60287: 2883: pred = expr_implies_predicate(rand, info);
- -: 2884:
- 60287: 2885: if (pred) {
- 27708: 2886: if (!lam->ir_info->arg_type_contributors[i]) {
- 5739: 2887: lam->ir_info->arg_types[i] = pred;
- 5739: 2888: if (nth_app)
- 4316: 2889: lam->ir_info->arg_type_contributors[i] |= (1 << (nth_app-1));
- 21969: 2890: } else if (predicate_implies(pred, lam->ir_info->arg_types[i])) {
- -: 2891: /* ok */
- 19997: 2892: if (nth_app)
- 10424: 2893: lam->ir_info->arg_type_contributors[i] |= (1 << (nth_app-1));
- 1972: 2894: } else if (predicate_implies(lam->ir_info->arg_types[i], pred)) {
- -: 2895: /* widen */
- 208: 2896: lam->ir_info->arg_types[i] = pred;
- 208: 2897: if (nth_app)
- 183: 2898: lam->ir_info->arg_type_contributors[i] |= (1 << (nth_app-1));
- -: 2899: } else
- 1764: 2900: widen_to_top = 1;
- -: 2901: } else
- 32579: 2902: widen_to_top = 1;
- -: 2903:
- 60287: 2904: if (widen_to_top) {
- 34343: 2905: if (nth_app) {
- -: 2906: /* Since we cant provide a nice type right now, just
- -: 2907: don't check in, in case a future iteration provides
- -: 2908: better information. If we never check in with a type,
- -: 2909: it will count as widening in the end. */
- -: 2910: } else {
- -: 2911: /* since we don't have an identity, the lambda won't
- -: 2912: be able to tell whether all apps have checked in,
- -: 2913: so we have to registers a "top" as an anonymous
- -: 2914: contributor. */
- 7186: 2915: lam->ir_info->arg_type_contributors[i] |= (1 << (SCHEME_USE_COUNT_INF-1));
- 7186: 2916: lam->ir_info->arg_types[i] = NULL;
- -: 2917: }
- -: 2918: }
- -: 2919: }
- -: 2920: }
- -: 2921: }
- -: 2922: }
- -: 2923: }
- 925376: 2924:}
- -: 2925:
- 17318: 2926:static void reset_rator(Scheme_Object *app, Scheme_Object *a)
- -: 2927:{
- 17318: 2928: switch (SCHEME_TYPE(app)) {
- -: 2929: case scheme_application_type:
- 563: 2930: ((Scheme_App_Rec *)app)->args[0] = a;
- 563: 2931: break;
- -: 2932: case scheme_application2_type:
- 14849: 2933: ((Scheme_App2_Rec *)app)->rator = a;
- 14849: 2934: break;
- -: 2935: case scheme_application3_type:
- 1906: 2936: ((Scheme_App3_Rec *)app)->rator = a;
- 1906: 2937: break;
- -: 2938: }
- 17318: 2939:}
- -: 2940:
- 18117: 2941:static void set_application_omittable(Scheme_Object *app, Scheme_Object *a)
- -: 2942:{
- 18117: 2943: switch (SCHEME_TYPE(app)) {
- -: 2944: case scheme_application_type:
- 483: 2945: SCHEME_APPN_FLAGS((Scheme_App_Rec *)app) |= APPN_FLAG_OMITTABLE;
- 483: 2946: break;
- -: 2947: case scheme_application2_type:
- 9455: 2948: SCHEME_APPN_FLAGS((Scheme_App2_Rec *)app) |= APPN_FLAG_OMITTABLE;
- 9455: 2949: break;
- -: 2950: case scheme_application3_type:
- 8179: 2951: SCHEME_APPN_FLAGS((Scheme_App3_Rec *)app) |= APPN_FLAG_OMITTABLE;
- 8179: 2952: break;
- -: 2953: }
- 18117: 2954:}
- -: 2955:
- 985376: 2956:static Scheme_Object *check_app_let_rator(Scheme_Object *app, Scheme_Object *rator, Optimize_Info *info,
- -: 2957: int argc, int context)
- -: 2958:/* Convert ((let (....) E) arg ...) to (let (....) (E arg ...)) and
- -: 2959: ((begin .... E) arg ...) to (begin .... (E arg ...)), in case
- -: 2960: the `let' or `begin' is immediately apparent. We check for this
- -: 2961: pattern again in optimize_for_inline() after optimizing a rator. */
- -: 2962:{
- 985376: 2963: Scheme_Object *orig_rator = rator, *inside = NULL;
- -: 2964:
- 985376: 2965: extract_tail_inside(&rator, &inside);
- -: 2966:
- 985376: 2967: if (!inside)
- 982403: 2968: return NULL;
- -: 2969:
- -: 2970: /* Moving a variable into application position: */
- 2973: 2971: if (SAME_TYPE(SCHEME_TYPE(rator), scheme_ir_local_type)) {
- 2947: 2972: Scheme_IR_Local *var = SCHEME_VAR(rator);
- 2947: 2973: if (var->non_app_count < SCHEME_USE_COUNT_INF)
- 2947: 2974: --var->non_app_count;
- -: 2975: }
- -: 2976:
- 2973: 2977: reset_rator(app, rator);
- 2973: 2978: orig_rator = replace_tail_inside(app, inside, orig_rator);
- -: 2979:
- 2973: 2980: return scheme_optimize_expr(orig_rator, info, context);
- -: 2981:}
- -: 2982:
- 931185: 2983:static int is_nonmutating_nondependant_primitive(Scheme_Object *rator, int n)
- -: 2984:/* Does not include SCHEME_PRIM_IS_UNSAFE_OMITABLE, because those can
- -: 2985: depend on earlier tests (explicit or implicit) for whether the
- -: 2986: unsafe operation is defined */
- -: 2987:{
- 931185: 2988: if (SCHEME_PRIMP(rator)
- 631653: 2989: && ((SCHEME_PRIM_PROC_OPT_FLAGS(rator) & (SCHEME_PRIM_IS_OMITABLE | SCHEME_PRIM_IS_OMITABLE_ALLOCATION))
- 209051: 2990: && !(SCHEME_PRIM_PROC_OPT_FLAGS(rator) & (SCHEME_PRIM_IS_UNSAFE_OMITABLE)))
- 196009: 2991: && (n >= ((Scheme_Primitive_Proc *)rator)->mina)
- 195997: 2992: && (n <= ((Scheme_Primitive_Proc *)rator)->mu.maxa))
- 195961: 2993: return 1;
- -: 2994:
- 735224: 2995: return 0;
- -: 2996:}
- -: 2997:
- 195961: 2998:static int is_primitive_allocating(Scheme_Object *rator, int n)
- -: 2999:{
- 195961: 3000: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & (SCHEME_PRIM_IS_OMITABLE_ALLOCATION))
- 76213: 3001: return 1;
- -: 3002:
- 119748: 3003: return 0;
- -: 3004:}
- -: 3005:
- 931185: 3006:static int is_noncapturing_primitive(Scheme_Object *rator, int n)
- -: 3007:{
- 931185: 3008: if (SCHEME_PRIMP(rator)) {
- -: 3009: int opt, t;
- 631653: 3010: opt = ((Scheme_Prim_Proc_Header *)rator)->flags & SCHEME_PRIM_OPT_MASK;
- 631653: 3011: if (opt >= SCHEME_PRIM_OPT_IMMEDIATE)
- 502190: 3012: return 1;
- 129463: 3013: if (opt >= SCHEME_PRIM_OPT_NONCM) {
- 53972: 3014: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_ALWAYS_ESCAPES) {
- -: 3015: /* even if a continuation is captured, it won't get back */
- 18853: 3016: return 1;
- -: 3017: }
- -: 3018: }
- 110610: 3019: t = (((Scheme_Primitive_Proc *)rator)->pp.flags & SCHEME_PRIM_OTHER_TYPE_MASK);
- 110610: 3020: if (!n && (t == SCHEME_PRIM_TYPE_PARAMETER))
- 3476: 3021: return 1;
- 107134: 3022: if (SAME_OBJ(rator, scheme_values_proc))
- 18180: 3023: return 1;
- -: 3024: }
- -: 3025:
- 388486: 3026: return 0;
- -: 3027:}
- -: 3028:
- 931185: 3029:static int is_nonsaving_primitive(Scheme_Object *rator, int n)
- -: 3030:{
- 931185: 3031: if (SCHEME_PRIMP(rator)) {
- -: 3032: int opt;
- 631653: 3033: opt = ((Scheme_Prim_Proc_Header *)rator)->flags & SCHEME_PRIM_OPT_MASK;
- 631653: 3034: if (opt >= SCHEME_PRIM_OPT_IMMEDIATE)
- 502190: 3035: return 1;
- 129463: 3036: if (SAME_OBJ(rator, scheme_values_proc))
- 18180: 3037: return 1;
- -: 3038: }
- -: 3039:
- 410815: 3040: return 0;
- -: 3041:}
- -: 3042:
- 914562: 3043:static int is_always_escaping_primitive(Scheme_Object *rator)
- -: 3044:{
- 914562: 3045: if (SCHEME_PRIMP(rator)
- 618217: 3046: && (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_ALWAYS_ESCAPES)) {
- 18853: 3047: return 1;
- -: 3048: }
- 895709: 3049: return 0;
- -: 3050:}
- -: 3051:
- -: 3052:#define IS_NAMED_PRIM(p, nm) (!strcmp(((Scheme_Primitive_Proc *)p)->name, nm))
- -: 3053:
- 1544743: 3054:static int wants_local_type_arguments(Scheme_Object *rator, int argpos)
- -: 3055:{
- 1544743: 3056: if (SCHEME_PRIMP(rator)) {
- -: 3057: int flags;
- 1006097: 3058: flags = SCHEME_PRIM_PROC_OPT_FLAGS(rator);
- -: 3059:
- 1006097: 3060: if (argpos == 0) {
- 608530: 3061: if (flags & SCHEME_PRIM_WANTS_FLONUM_FIRST)
- 410: 3062: return SCHEME_LOCAL_TYPE_FLONUM;
- 608120: 3063: if (flags & SCHEME_PRIM_WANTS_EXTFLONUM_FIRST)
- 114: 3064: return SCHEME_LOCAL_TYPE_EXTFLONUM;
- 397567: 3065: } else if (argpos == 1) {
- 261323: 3066: if (flags & SCHEME_PRIM_WANTS_FLONUM_SECOND)
- 406: 3067: return SCHEME_LOCAL_TYPE_FLONUM;
- 260917: 3068: if (flags & SCHEME_PRIM_WANTS_EXTFLONUM_SECOND)
- 110: 3069: return SCHEME_LOCAL_TYPE_EXTFLONUM;
- 136244: 3070: } else if (argpos == 2) {
- 66017: 3071: if (flags & SCHEME_PRIM_WANTS_FLONUM_THIRD)
- 270: 3072: return SCHEME_LOCAL_TYPE_FLONUM;
- 65747: 3073: if (flags & SCHEME_PRIM_WANTS_EXTFLONUM_THIRD)
- 76: 3074: return SCHEME_LOCAL_TYPE_EXTFLONUM;
- -: 3075: }
- -: 3076: }
- -: 3077:
- 1543357: 3078: return 0;
- -: 3079:}
- -: 3080:
- 413410: 3081:static int produces_local_type(Scheme_Object *rator, int argc)
- -: 3082:{
- 413410: 3083: if (SCHEME_PRIMP(rator)
- 413410: 3084: && (argc >= ((Scheme_Primitive_Proc *)rator)->mina)
- 413406: 3085: && (argc <= ((Scheme_Primitive_Proc *)rator)->mu.maxa)) {
- -: 3086: int flags;
- 413406: 3087: flags = SCHEME_PRIM_PROC_OPT_FLAGS(rator);
- 413406: 3088: return SCHEME_PRIM_OPT_TYPE(flags);
- -: 3089: }
- -: 3090:
- 4: 3091: return 0;
- -: 3092:}
- -: 3093:
- 1644801: 3094:static Scheme_Object *local_type_to_predicate(int t)
- -: 3095:{
- 1644801: 3096: switch (t) {
- -: 3097: case SCHEME_LOCAL_TYPE_FLONUM:
- 982: 3098: return scheme_flonum_p_proc;
- -: 3099: case SCHEME_LOCAL_TYPE_FIXNUM:
- 64130: 3100: return scheme_fixnum_p_proc;
- -: 3101: case SCHEME_LOCAL_TYPE_EXTFLONUM:
- 262: 3102: return scheme_extflonum_p_proc;
- -: 3103: }
- 1579427: 3104: return NULL;
- -: 3105:}
- -: 3106:
- 510438: 3107:int scheme_predicate_to_local_type(Scheme_Object *pred)
- -: 3108:{
- 510438: 3109: if (!pred)
- 414194: 3110: return 0;
- 96244: 3111: if (SAME_OBJ(scheme_flonum_p_proc, pred))
- 435: 3112: return SCHEME_LOCAL_TYPE_FLONUM;
- 95809: 3113: if (SAME_OBJ(scheme_fixnum_p_proc, pred))
- 33259: 3114: return SCHEME_LOCAL_TYPE_FIXNUM;
- 62550: 3115: if (SAME_OBJ(scheme_extflonum_p_proc, pred))
- 130: 3116: return SCHEME_LOCAL_TYPE_EXTFLONUM;
- 62420: 3117: return 0;
- -: 3118:}
- -: 3119:
- 506545: 3120:int scheme_expr_produces_local_type(Scheme_Object *expr, int *_involves_k_cross)
- -: 3121:{
- 506545: 3122: if (_involves_k_cross) *_involves_k_cross = 0;
- 506545: 3123: return scheme_predicate_to_local_type(do_expr_implies_predicate(expr, NULL, _involves_k_cross,
- -: 3124: 10, empty_eq_hash_tree));
- -: 3125:}
- -: 3126:
- 923488: 3127:static Scheme_Object *rator_implies_predicate(Scheme_Object *rator, Optimize_Info *info, int argc)
- -: 3128:{
- 923488: 3129: if (SCHEME_PRIMP(rator)) {
- 692981: 3130: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_PRODUCES_REAL)
- 678: 3131: return scheme_real_p_proc;
- 692303: 3132: else if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_PRODUCES_NUMBER)
- 27701: 3133: return scheme_number_p_proc;
- 664602: 3134: else if (SAME_OBJ(rator, scheme_cons_proc))
- 14742: 3135: return scheme_pair_p_proc;
- 649860: 3136: else if (SAME_OBJ(rator, scheme_unsafe_cons_list_proc))
- 2: 3137: return scheme_list_pair_p_proc;
- 649858: 3138: else if (SAME_OBJ(rator, scheme_mcons_proc))
- 69: 3139: return scheme_mpair_p_proc;
- 649789: 3140: else if (SAME_OBJ(rator, scheme_list_proc)) {
- 6920: 3141: if (argc >= 1)
- 6920: 3142: return scheme_list_pair_p_proc;
- -: 3143: else
- #####: 3144: return scheme_null_p_proc;
- 642869: 3145: } else if (SAME_OBJ(rator, scheme_list_star_proc)) {
- 10443: 3146: if (argc > 2)
- 6146: 3147: return scheme_pair_p_proc;
- 632426: 3148: } else if (IS_NAMED_PRIM(rator, "vector->list")
- 630447: 3149: || IS_NAMED_PRIM(rator, "map")) {
- 3029: 3150: return scheme_list_p_proc;
- 629397: 3151: } else if (IS_NAMED_PRIM(rator, "string-ref")) {
- 59: 3152: return scheme_char_p_proc;
- 629338: 3153: } else if (IS_NAMED_PRIM(rator, "string-append")
- 628795: 3154: || IS_NAMED_PRIM(rator, "string->immutable-string")
- 628776: 3155: || IS_NAMED_PRIM(rator, "symbol->string")
- 628253: 3156: || IS_NAMED_PRIM(rator, "keyword->string")) {
- 1124: 3157: return scheme_string_p_proc;
- 628214: 3158: } else if (IS_NAMED_PRIM(rator, "bytes-append")
- 627971: 3159: || IS_NAMED_PRIM(rator, "bytes->immutable-bytes")) {
- 245: 3160: return scheme_byte_string_p_proc;
- 627969: 3161: } else if (SAME_OBJ(rator, scheme_vector_proc)
- 627854: 3162: || SAME_OBJ(rator, scheme_vector_immutable_proc)
- 627824: 3163: || SAME_OBJ(rator, scheme_make_vector_proc)
- 627410: 3164: || SAME_OBJ(rator, scheme_list_to_vector_proc)
- 627316: 3165: || SAME_OBJ(rator, scheme_struct_to_vector_proc)
- 626902: 3166: || IS_NAMED_PRIM(rator, "vector->immutable-vector"))
- 1069: 3167: return scheme_vector_p_proc;
- 626900: 3168: else if (SAME_OBJ(rator, scheme_box_proc)
- 626727: 3169: || SAME_OBJ(rator, scheme_box_immutable_proc))
- 203: 3170: return scheme_box_p_proc;
- 626697: 3171: else if (SAME_OBJ(rator, scheme_void_proc))
- 3: 3172: return scheme_void_p_proc;
- 626694: 3173: else if (SAME_OBJ(rator, scheme_procedure_specialize_proc))
- 6: 3174: return scheme_procedure_p_proc;
- 626688: 3175: else if (IS_NAMED_PRIM(rator, "vector-set!")
- 626686: 3176: || IS_NAMED_PRIM(rator, "string-set!")
- 626684: 3177: || IS_NAMED_PRIM(rator, "bytes-set!")
- 626682: 3178: || IS_NAMED_PRIM(rator, "set-box!"))
- 8: 3179: return scheme_void_p_proc;
- 626680: 3180: else if (IS_NAMED_PRIM(rator, "vector-set!")
- 626680: 3181: || IS_NAMED_PRIM(rator, "string-set!")
- 626680: 3182: || IS_NAMED_PRIM(rator, "bytes-set!"))
- #####: 3183: return scheme_void_p_proc;
- 626680: 3184: else if (IS_NAMED_PRIM(rator, "string->symbol")
- 625793: 3185: || IS_NAMED_PRIM(rator, "gensym"))
- 1235: 3186: return scheme_symbol_p_proc;
- 625445: 3187: else if (IS_NAMED_PRIM(rator, "string->keyword"))
- 2: 3188: return scheme_keyword_p_proc;
- 625443: 3189: else if (IS_NAMED_PRIM(rator, "pair?")
- 581411: 3190: || IS_NAMED_PRIM(rator, "mpair?")
- 581017: 3191: || IS_NAMED_PRIM(rator, "list?")
- 569298: 3192: || IS_NAMED_PRIM(rator, "list-pair?")
- 569260: 3193: || IS_NAMED_PRIM(rator, "vector?")
- 566214: 3194: || IS_NAMED_PRIM(rator, "box?")
- 565541: 3195: || IS_NAMED_PRIM(rator, "number?")
- 563949: 3196: || IS_NAMED_PRIM(rator, "real?")
- 562744: 3197: || IS_NAMED_PRIM(rator, "complex?")
- 562738: 3198: || IS_NAMED_PRIM(rator, "rational?")
- 562732: 3199: || IS_NAMED_PRIM(rator, "integer?")
- 561687: 3200: || IS_NAMED_PRIM(rator, "exact-integer?")
- 561265: 3201: || IS_NAMED_PRIM(rator, "exact-nonnegative-integer?")
- 559849: 3202: || IS_NAMED_PRIM(rator, "exact-positive-integer?")
- 559301: 3203: || IS_NAMED_PRIM(rator, "inexact-real?")
- 559295: 3204: || IS_NAMED_PRIM(rator, "fixnum?")
- 558385: 3205: || IS_NAMED_PRIM(rator, "flonum?")
- 558379: 3206: || IS_NAMED_PRIM(rator, "single-flonum?")
- 558373: 3207: || IS_NAMED_PRIM(rator, "null?")
- 494955: 3208: || IS_NAMED_PRIM(rator, "void?")
- 494703: 3209: || IS_NAMED_PRIM(rator, "symbol?")
- 491394: 3210: || IS_NAMED_PRIM(rator, "keyword?")
- 489923: 3211: || IS_NAMED_PRIM(rator, "string?")
- 486148: 3212: || IS_NAMED_PRIM(rator, "bytes?")
- 483854: 3213: || IS_NAMED_PRIM(rator, "path?")
- 482048: 3214: || IS_NAMED_PRIM(rator, "char?")
- 481742: 3215: || IS_NAMED_PRIM(rator, "interned-char?")
- 481728: 3216: || IS_NAMED_PRIM(rator, "boolean?")
- 481373: 3217: || IS_NAMED_PRIM(rator, "chaperone?")
- 481339: 3218: || IS_NAMED_PRIM(rator, "impersonator?")
- 481309: 3219: || IS_NAMED_PRIM(rator, "procedure?")
- 477259: 3220: || IS_NAMED_PRIM(rator, "eof-object?")
- 475366: 3221: || IS_NAMED_PRIM(rator, "immutable?")
- 474588: 3222: || IS_NAMED_PRIM(rator, "not")
- 467231: 3223: || IS_NAMED_PRIM(rator, "true-object?")
- 466747: 3224: || IS_NAMED_PRIM(rator, "zero?")
- 461468: 3225: || IS_NAMED_PRIM(rator, "procedure-arity-includes?")
- 457469: 3226: || IS_NAMED_PRIM(rator, "variable-reference-constant?")
- 457339: 3227: || IS_NAMED_PRIM(rator, "eq?")
- 426491: 3228: || IS_NAMED_PRIM(rator, "eqv?")
- 425834: 3229: || IS_NAMED_PRIM(rator, "equal?")
- 421472: 3230: || IS_NAMED_PRIM(rator, "string=?")
- 420838: 3231: || IS_NAMED_PRIM(rator, "bytes=?")
- 420732: 3232: || IS_NAMED_PRIM(rator, "char=?")
- 420506: 3233: || IS_NAMED_PRIM(rator, "free-identifier=?")
- 410261: 3234: || IS_NAMED_PRIM(rator, "bound-identifier=?")
- 409117: 3235: || IS_NAMED_PRIM(rator, "procedure-closure-contents-eq?")) {
- 216330: 3236: return scheme_boolean_p_proc;
- -: 3237: }
- -: 3238:
- -: 3239: {
- -: 3240: Scheme_Object *p;
- 413410: 3241: p = local_type_to_predicate(produces_local_type(rator, argc));
- 413410: 3242: if (p)
- 42726: 3243: return p;
- -: 3244: }
- -: 3245: }
- -: 3246:
- -: 3247: {
- -: 3248: Scheme_Object *shape;
- 601191: 3249: shape = get_struct_proc_shape(rator, info, 1);
- 601191: 3250: if (shape) {
- 10894: 3251: if (SAME_TYPE(SCHEME_TYPE(shape), scheme_struct_proc_shape_type)) {
- 14053: 3252: if (((SCHEME_PROC_SHAPE_MODE(shape) & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_PRED)) {
- 5271: 3253: return scheme_boolean_p_proc;
- -: 3254: }
- 1232: 3255: } else if (SAME_TYPE(SCHEME_TYPE(shape), scheme_struct_prop_proc_shape_type)) {
- 1232: 3256: if (SCHEME_PROP_PROC_SHAPE_MODE(shape) == STRUCT_PROP_PROC_SHAPE_PRED) {
- 900: 3257: return scheme_boolean_p_proc;
- -: 3258: }
- -: 3259: }
- -: 3260: }
- -: 3261: }
- -: 3262:
- 595020: 3263: return NULL;
- -: 3264:}
- -: 3265:
- 3978421: 3266:static Scheme_Object *do_expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info,
- -: 3267: int *_involves_k_cross, int fuel,
- -: 3268: Scheme_Hash_Tree *ignore_vars)
- -: 3269:/* can be called by the JIT with info = NULL;
- -: 3270: in that case, beware that the validator must be
- -: 3271: able to reconstruct the result in a shallow way, so don't
- -: 3272: make the result of a function call depend on its arguments */
- -: 3273:{
- 3978421: 3274: if (fuel <= 0)
- 6244: 3275: return NULL;
- -: 3276:
- 3972177: 3277: switch (SCHEME_TYPE(expr)) {
- -: 3278: case scheme_ir_local_type:
- -: 3279: {
- 1735303: 3280: if (scheme_hash_tree_get(ignore_vars, expr))
- 9097: 3281: return NULL;
- -: 3282:
- 1726206: 3283: if (!SCHEME_VAR(expr)->mutated) {
- -: 3284: Scheme_Object *p;
- -: 3285:
- 1723830: 3286: if (info) {
- 1644594: 3287: p = optimize_get_predicate(info, expr, 0);
- 1644594: 3288: if (p)
- 492439: 3289: return p;
- -: 3290: }
- -: 3291:
- 1231391: 3292: p = local_type_to_predicate(SCHEME_VAR(expr)->val_type);
- 1231391: 3293: if (p) {
- 22648: 3294: if (_involves_k_cross
- 19: 3295: && SCHEME_VAR(expr)->escapes_after_k_tick)
- 19: 3296: *_involves_k_cross = 1;
- 22648: 3297: return p;
- -: 3298: }
- -: 3299:
- 1208743: 3300: if ((SCHEME_VAR(expr)->mode == SCHEME_VAR_MODE_OPTIMIZE)
- 1179147: 3301: && SCHEME_VAR(expr)->optimize.known_val)
- 187275: 3302: return do_expr_implies_predicate(SCHEME_VAR(expr)->optimize.known_val, info, _involves_k_cross,
- -: 3303: fuel-1, ignore_vars);
- -: 3304: }
- -: 3305: }
- 1023844: 3306: break;
- -: 3307: case scheme_application2_type:
- -: 3308: {
- 502527: 3309: Scheme_App2_Rec *app = (Scheme_App2_Rec *)expr;
- -: 3310:
- 502527: 3311: if (SCHEME_PRIMP(app->rator)
- 362668: 3312: && SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_CLOSED_ON_REALS) {
- -: 3313: Scheme_Object *p;
- 17549: 3314: p = do_expr_implies_predicate(app->rand, info, NULL, fuel-1, ignore_vars);
- 17549: 3315: if (p && predicate_implies(p, scheme_real_p_proc))
- 2095: 3316: return scheme_real_p_proc;
- -: 3317: }
- -: 3318:
- 500432: 3319: if (SAME_OBJ(app->rator, scheme_cdr_proc)
- 466176: 3320: || SAME_OBJ(app->rator, scheme_unsafe_cdr_proc)) {
- -: 3321: Scheme_Object *p;
- 111992: 3322: p = do_expr_implies_predicate(app->rand, info, NULL, fuel-1, ignore_vars);
- 111992: 3323: if (SAME_OBJ(p, scheme_list_pair_p_proc))
- 4478: 3324: return scheme_list_p_proc;
- -: 3325: }
- -: 3326:
- 495954: 3327: return rator_implies_predicate(app->rator, info, 1);
- -: 3328: }
- -: 3329: break;
- -: 3330: case scheme_application3_type:
- -: 3331: {
- 202442: 3332: Scheme_App3_Rec *app = (Scheme_App3_Rec *)expr;
- 202442: 3333: if (SCHEME_PRIMP(app->rator)
- 176176: 3334: && (SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_IS_BINARY_INLINED)
- 106454: 3335: && IS_NAMED_PRIM(app->rator, "bitwise-and")) {
- -: 3336: /* Assume that a fixnum argument to bitwise-and will never get lost,
- -: 3337: and so the validator will be able to confirm that a `bitwise-and`
- -: 3338: combination produces a fixnum if either argument is a literal,
- -: 3339: nonnegative fixnum. */
- 307: 3340: if ((SCHEME_INTP(app->rand1)
- 10: 3341: && (SCHEME_INT_VAL(app->rand1) >= 0)
- 10: 3342: && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand1)))
- 307: 3343: || (SCHEME_INTP(app->rand2)
- 204: 3344: && (SCHEME_INT_VAL(app->rand2) >= 0)
- 202: 3345: && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand2)))) {
- 22: 3346: return scheme_fixnum_p_proc;
- -: 3347: }
- -: 3348: }
- -: 3349:
- 202420: 3350: if (SCHEME_PRIMP(app->rator)
- 176154: 3351: && SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_CLOSED_ON_REALS) {
- -: 3352: Scheme_Object *p;
- 13971: 3353: p = do_expr_implies_predicate(app->rand1, info, NULL, fuel-1, ignore_vars);
- 13971: 3354: if (p && predicate_implies(p, scheme_real_p_proc)) {
- 3224: 3355: p = do_expr_implies_predicate(app->rand2, info, NULL, fuel-1, ignore_vars);
- 3224: 3356: if (p && predicate_implies(p, scheme_real_p_proc)) {
- 1966: 3357: return scheme_real_p_proc;
- -: 3358: }
- -: 3359: }
- -: 3360: }
- -: 3361:
- 200454: 3362: if (SAME_OBJ(app->rator, scheme_cons_proc)) {
- -: 3363: Scheme_Object *p;
- 16285: 3364: p = do_expr_implies_predicate(app->rand2, info, NULL, fuel-1, ignore_vars);
- 16285: 3365: if (SAME_OBJ(p, scheme_list_pair_p_proc)
- 15686: 3366: || SAME_OBJ(p, scheme_list_p_proc)
- 15649: 3367: || SAME_OBJ(p, scheme_null_p_proc))
- 1565: 3368: return scheme_list_pair_p_proc;
- -: 3369: }
- -: 3370:
- 198889: 3371: if (SCHEME_PRIMP(app->rator)
- 172623: 3372: && IS_NAMED_PRIM(app->rator, "append")) {
- -: 3373: Scheme_Object *p;
- 1342: 3374: p = do_expr_implies_predicate(app->rand2, info, NULL, fuel-1, ignore_vars);
- 1342: 3375: if (SAME_OBJ(p, scheme_list_pair_p_proc))
- 211: 3376: return scheme_list_pair_p_proc;
- 1131: 3377: if (SAME_OBJ(p, scheme_list_p_proc)
- 1111: 3378: || SAME_OBJ(p, scheme_null_p_proc))
- 32: 3379: return scheme_list_p_proc;
- -: 3380: }
- -: 3381:
- 198646: 3382: return rator_implies_predicate(app->rator, info, 2);
- -: 3383: }
- -: 3384: break;
- -: 3385: case scheme_application_type:
- -: 3386: {
- 44646: 3387: Scheme_App_Rec *app = (Scheme_App_Rec *)expr;
- -: 3388:
- 44646: 3389: if (SCHEME_PRIMP(app->args[0])
- 27877: 3390: && SCHEME_PRIM_PROC_OPT_FLAGS(app->args[0]) & SCHEME_PRIM_CLOSED_ON_REALS) {
- -: 3391: Scheme_Object *p;
- -: 3392: int i;
- 266: 3393: for (i = 0; i < app->num_args; i++) {
- 260: 3394: p = do_expr_implies_predicate(app->args[i+1], info, NULL, fuel-1, ignore_vars);
- 260: 3395: if (!p || !predicate_implies(p, scheme_real_p_proc))
- -: 3396: break;
- -: 3397: }
- 248: 3398: if (i >= app->num_args)
- 6: 3399: return scheme_real_p_proc;
- -: 3400: }
- -: 3401:
- 44640: 3402: if (SCHEME_PRIMP(app->args[0])
- 27871: 3403: && IS_NAMED_PRIM(app->args[0], "append")) {
- -: 3404: Scheme_Object *p;
- 174: 3405: p = do_expr_implies_predicate(app->args[app->num_args], info, NULL, fuel-1, ignore_vars);
- 174: 3406: if (SAME_OBJ(p, scheme_list_pair_p_proc))
- #####: 3407: return scheme_list_pair_p_proc;
- 174: 3408: if (SAME_OBJ(p, scheme_list_p_proc)
- 158: 3409: || SAME_OBJ(p, scheme_null_p_proc))
- 16: 3410: return scheme_list_p_proc;
- -: 3411: }
- -: 3412:
- 44624: 3413: return rator_implies_predicate(app->args[0], info, app->num_args);
- -: 3414: }
- -: 3415: break;
- -: 3416: case scheme_ir_lambda_type:
- 96840: 3417: return scheme_procedure_p_proc;
- -: 3418: break;
- -: 3419: case scheme_case_lambda_sequence_type:
- 532: 3420: return scheme_procedure_p_proc;
- -: 3421: break;
- -: 3422: case scheme_ir_quote_syntax_type:
- 30913: 3423: return scheme_syntax_p_proc;
- -: 3424: break;
- -: 3425: case scheme_branch_type:
- -: 3426: {
- -: 3427: Scheme_Object *l, *r;
- 137989: 3428: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)expr;
- 137989: 3429: l = do_expr_implies_predicate(b->tbranch, info, _involves_k_cross, fuel-1, ignore_vars);
- 137989: 3430: if (l) {
- 44328: 3431: r = do_expr_implies_predicate(b->fbranch, info, _involves_k_cross, fuel-1, ignore_vars);
- 44328: 3432: if (predicate_implies(l, r))
- 8419: 3433: return r;
- 35909: 3434: else if (predicate_implies(r, l))
- 14970: 3435: return l;
- -: 3436: else
- 20939: 3437: return NULL;
- -: 3438: }
- -: 3439: }
- 93661: 3440: break;
- -: 3441: case scheme_sequence_type:
- -: 3442: {
- 11336: 3443: Scheme_Sequence *seq = (Scheme_Sequence *)expr;
- -: 3444:
- 11336: 3445: return do_expr_implies_predicate(seq->array[seq->count-1], info, _involves_k_cross, fuel-1, ignore_vars);
- -: 3446: }
- -: 3447: case scheme_with_cont_mark_type:
- -: 3448: {
- 165: 3449: Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)expr;
- -: 3450:
- 165: 3451: return do_expr_implies_predicate(wcm->body, info, _involves_k_cross, fuel-1, ignore_vars);
- -: 3452: }
- -: 3453: case scheme_ir_let_header_type:
- -: 3454: {
- 30921: 3455: Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)expr;
- -: 3456: Scheme_IR_Let_Value *irlv;
- -: 3457: int i, j;
- 30921: 3458: expr = lh->body;
- 67998: 3459: for (i = 0; i < lh->num_clauses; i++) {
- 37077: 3460: irlv = (Scheme_IR_Let_Value *)expr;
- 75037: 3461: for (j = 0; j < irlv->count; j++) {
- 37960: 3462: ignore_vars = scheme_hash_tree_set(ignore_vars, (Scheme_Object *)irlv->vars[j],
- -: 3463: scheme_true);
- -: 3464: }
- 37077: 3465: expr = irlv->body;
- -: 3466: }
- 30921: 3467: return do_expr_implies_predicate(expr, info, _involves_k_cross, fuel-1, ignore_vars);
- -: 3468: }
- -: 3469: break;
- -: 3470: case scheme_begin0_sequence_type:
- -: 3471: {
- 48: 3472: Scheme_Sequence *seq = (Scheme_Sequence *)expr;
- -: 3473:
- 48: 3474: return do_expr_implies_predicate(seq->array[0], info, _involves_k_cross, fuel-1, ignore_vars);
- -: 3475: }
- -: 3476: case scheme_vector_type:
- 2360: 3477: return scheme_vector_p_proc;
- -: 3478: break;
- -: 3479: case scheme_box_type:
- #####: 3480: return scheme_box_p_proc;
- -: 3481: break;
- -: 3482: default:
- 1176155: 3483: if (SCHEME_FLOATP(expr))
- 283: 3484: return scheme_flonum_p_proc;
- 1175872: 3485: if (SCHEME_LONG_DBLP(expr))
- 32: 3486: return scheme_extflonum_p_proc;
- 1175840: 3487: if (SCHEME_INTP(expr)
- 29748: 3488: && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(expr)))
- 29499: 3489: return scheme_fixnum_p_proc;
- 1146341: 3490: if (SCHEME_REALP(expr))
- 331: 3491: return scheme_real_p_proc;
- 1146010: 3492: if (SCHEME_NUMBERP(expr))
- 10: 3493: return scheme_number_p_proc;
- -: 3494:
- 1146000: 3495: if (SCHEME_NULLP(expr))
- 7548: 3496: return scheme_null_p_proc;
- 1138452: 3497: if (scheme_is_list(expr))
- 2047: 3498: return scheme_list_pair_p_proc;
- 1136405: 3499: if (SCHEME_PAIRP(expr))
- 24: 3500: return scheme_pair_p_proc;
- 1136381: 3501: if (SCHEME_MPAIRP(expr))
- #####: 3502: return scheme_mpair_p_proc;
- 1136381: 3503: if (SCHEME_CHAR_STRINGP(expr))
- 5526: 3504: return scheme_string_p_proc;
- 1130855: 3505: if (SCHEME_BYTE_STRINGP(expr))
- 482: 3506: return scheme_byte_string_p_proc;
- 1130373: 3507: if (SCHEME_VOIDP(expr))
- 98: 3508: return scheme_void_p_proc;
- 1130275: 3509: if (SCHEME_EOFP(expr))
- 54: 3510: return scheme_eof_object_p_proc;
- 1130221: 3511: if (SCHEME_KEYWORDP(expr))
- 3348: 3512: return scheme_keyword_p_proc;
- 1126873: 3513: if (SCHEME_SYMBOLP(expr))
- 9137: 3514: return scheme_symbol_p_proc;
- 1117736: 3515: if (SCHEME_CHARP(expr) && SCHEME_CHAR_VAL(expr) < 256)
- 166: 3516: return scheme_interned_char_p_proc;
- 1117570: 3517: if (SCHEME_CHARP(expr))
- 26: 3518: return scheme_char_p_proc;
- 1117544: 3519: if (SAME_OBJ(expr, scheme_true))
- 7214: 3520: return scheme_true_object_p_proc;
- 1110330: 3521: if (SCHEME_FALSEP(expr))
- 26840: 3522: return scheme_not_proc;
- 1083490: 3523: if (SCHEME_PROCP(expr))
- 620643: 3524: return scheme_procedure_p_proc;
- -: 3525: }
- -: 3526:
- -: 3527: /* This test is slower, so put it at the end */
- 1580352: 3528: if (info
- 1282511: 3529: && lookup_constant_proc(info, expr, -1)) {
- 46531: 3530: return scheme_procedure_p_proc;
- -: 3531: }
- -: 3532:
- 1533821: 3533: return NULL;
- -: 3534:}
- -: 3535:
- 2895017: 3536:static Scheme_Object *expr_implies_predicate(Scheme_Object *expr, Optimize_Info *info)
- -: 3537:{
- 2895017: 3538: return do_expr_implies_predicate(expr, info, NULL, 5, empty_eq_hash_tree);
- -: 3539:}
- -: 3540:
- 676: 3541:static Scheme_Object *finish_optimize_app(Scheme_Object *o, Optimize_Info *info, int context)
- -: 3542:{
- 676: 3543: switch(SCHEME_TYPE(o)) {
- -: 3544: case scheme_application_type:
- 612: 3545: return finish_optimize_application((Scheme_App_Rec *)o, info, context);
- -: 3546: case scheme_application2_type:
- 31: 3547: return finish_optimize_application2((Scheme_App2_Rec *)o, info, context);
- -: 3548: case scheme_application3_type:
- 33: 3549: return finish_optimize_application3((Scheme_App3_Rec *)o, info, context);
- -: 3550: default:
- #####: 3551: return o; /* may be a constant due to constant-folding */
- -: 3552: }
- -: 3553:}
- -: 3554:
- 861337: 3555:static Scheme_Object *direct_apply(Scheme_Object *expr, Scheme_Object *rator, Scheme_Object *last_rand, Optimize_Info *info)
- -: 3556:/* Convert `(apply f arg1 ... (list arg2 ...))` to `(f arg1 ... arg2 ...)` */
- -: 3557:{
- 861337: 3558: if (SAME_OBJ(rator, scheme_apply_proc)) {
- 10239: 3559: switch(SCHEME_TYPE(last_rand)) {
- -: 3560: case scheme_application_type:
- 816: 3561: rator = ((Scheme_App_Rec *)last_rand)->args[0];
- 816: 3562: break;
- -: 3563: case scheme_application2_type:
- 586: 3564: rator = ((Scheme_App2_Rec *)last_rand)->rator;
- 586: 3565: break;
- -: 3566: case scheme_application3_type:
- 2060: 3567: rator = ((Scheme_App3_Rec *)last_rand)->rator;
- 2060: 3568: break;
- -: 3569: case scheme_pair_type:
- 24: 3570: if (scheme_is_list(last_rand))
- 24: 3571: rator = scheme_list_proc;
- -: 3572: else
- #####: 3573: rator = NULL;
- 24: 3574: break;
- -: 3575: case scheme_null_type:
- 227: 3576: rator = scheme_list_proc;
- 227: 3577: break;
- -: 3578: default:
- 6526: 3579: rator = NULL;
- 6526: 3580: break;
- -: 3581: }
- -: 3582:
- 10239: 3583: if (rator && SAME_OBJ(rator, scheme_list_proc)) {
- -: 3584: /* Convert (apply f arg1 ... (list arg2 ...))
- -: 3585: to (f arg1 ... arg2 ...) */
- 820: 3586: Scheme_Object *l = scheme_null;
- -: 3587: int i;
- -: 3588:
- 820: 3589: switch(SCHEME_TYPE(last_rand)) {
- -: 3590: case scheme_application_type:
- 1547: 3591: for (i = ((Scheme_App_Rec *)last_rand)->num_args; i--; ) {
- 945: 3592: l = scheme_make_pair(((Scheme_App_Rec *)last_rand)->args[i+1], l);
- -: 3593: }
- 301: 3594: break;
- -: 3595: case scheme_application2_type:
- 89: 3596: l = scheme_make_pair(((Scheme_App2_Rec *)last_rand)->rand, l);
- 89: 3597: break;
- -: 3598: case scheme_application3_type:
- 179: 3599: l = scheme_make_pair(((Scheme_App3_Rec *)last_rand)->rand2, l);
- 179: 3600: l = scheme_make_pair(((Scheme_App3_Rec *)last_rand)->rand1, l);
- 179: 3601: break;
- -: 3602: case scheme_pair_type:
- 24: 3603: l = last_rand;
- 24: 3604: break;
- -: 3605: case scheme_null_type:
- 227: 3606: l = scheme_null;
- 227: 3607: break;
- -: 3608: }
- -: 3609:
- 820: 3610: switch(SCHEME_TYPE(expr)) {
- -: 3611: case scheme_application_type:
- 3648: 3612: for (i = ((Scheme_App_Rec *)expr)->num_args - 1; i--; ) {
- 2148: 3613: l = scheme_make_pair(((Scheme_App_Rec *)expr)->args[i+1], l);
- -: 3614: }
- 750: 3615: break;
- -: 3616: default:
- -: 3617: case scheme_application3_type:
- 70: 3618: l = scheme_make_pair(((Scheme_App3_Rec *)expr)->rand1, l);
- 70: 3619: break;
- -: 3620: }
- -: 3621:
- 820: 3622: return scheme_make_application(l, info);
- -: 3623: }
- -: 3624: }
- -: 3625:
- 860517: 3626: return NULL;
- -: 3627:}
- -: 3628:
- 366503: 3629:static Scheme_Object *call_with_immed_mark(Scheme_Object *rator,
- -: 3630: Scheme_Object *rand1,
- -: 3631: Scheme_Object *rand2,
- -: 3632: Scheme_Object *rand3,
- -: 3633: Optimize_Info *info)
- -: 3634:/* Convert `(call-with-immediate-continuation-mark (lambda (arg) M))`
- -: 3635: to the with-immediate-mark bytecode form. */
- -: 3636:{
- 366503: 3637: if (SAME_OBJ(rator, scheme_call_with_immed_mark_proc)
- 131: 3638: && SAME_TYPE(SCHEME_TYPE(rand2), scheme_ir_lambda_type)
- 131: 3639: && (((Scheme_Lambda *)rand2)->num_params == 1)
- 131: 3640: && !(SCHEME_LAMBDA_FLAGS(((Scheme_Lambda *)rand2)) & LAMBDA_HAS_REST)) {
- -: 3641: Scheme_With_Continuation_Mark *wcm;
- -: 3642: Scheme_Object *e;
- -: 3643:
- 131: 3644: wcm = MALLOC_ONE_TAGGED(Scheme_With_Continuation_Mark);
- 131: 3645: wcm->so.type = scheme_with_immed_mark_type;
- -: 3646:
- 131: 3647: wcm->key = rand1;
- 131: 3648: wcm->val = (rand3 ? rand3 : scheme_false);
- -: 3649:
- 131: 3650: e = (Scheme_Object *)((Scheme_Lambda *)rand2)->ir_info->vars[0];
- 131: 3651: e = scheme_make_mutable_pair(e, ((Scheme_Lambda *)rand2)->body);
- 131: 3652: wcm->body = e;
- -: 3653:
- 131: 3654: return (Scheme_Object *)wcm;
- -: 3655: }
- -: 3656:
- 366372: 3657: return NULL;
- -: 3658:}
- -: 3659:
- 157486: 3660:static Scheme_Object *optimize_application(Scheme_Object *o, Optimize_Info *info, int context)
- -: 3661:{
- -: 3662: Scheme_Object *le;
- -: 3663: Scheme_App_Rec *app;
- 157486: 3664: int i, n, rator_apply_escapes = 0, sub_context = 0;
- -: 3665: Optimize_Info_Sequence info_seq;
- -: 3666:
- 157486: 3667: app = (Scheme_App_Rec *)o;
- -: 3668:
- -: 3669: /* Check for (apply ... (list ...)) early: */
- 157486: 3670: le = direct_apply((Scheme_Object *)app, app->args[0], app->args[app->num_args], info);
- 157486: 3671: if (le)
- 124: 3672: return scheme_optimize_expr(le, info, context);
- -: 3673:
- 157362: 3674: if (app->num_args == 3) {
- 72861: 3675: le = call_with_immed_mark(app->args[0], app->args[1], app->args[2], app->args[3], info);
- 72861: 3676: if (le)
- #####: 3677: return scheme_optimize_expr(le, info, context);
- -: 3678: }
- -: 3679:
- 157362: 3680: le = check_app_let_rator(o, app->args[0], info, app->num_args, context);
- 157362: 3681: if (le)
- 563: 3682: return le;
- -: 3683:
- 156799: 3684: n = app->num_args + 1;
- -: 3685:
- 156799: 3686: optimize_info_seq_init(info, &info_seq);
- -: 3687:
- 800996: 3688: for (i = 0; i < n; i++) {
- 656879: 3689: if (!i) {
- 156799: 3690: le = optimize_for_inline(info, app->args[i], n - 1, app, NULL, NULL, context, 0);
- 156799: 3691: if (le)
- 12608: 3692: return le;
- -: 3693: }
- -: 3694:
- 644271: 3695: sub_context = OPT_CONTEXT_SINGLED;
- 644271: 3696: if (i > 0) {
- -: 3697: int ty;
- 500080: 3698: ty = wants_local_type_arguments(app->args[0], i - 1);
- 500080: 3699: if (ty)
- 346: 3700: sub_context |= (ty << OPT_CONTEXT_TYPE_SHIFT);
- -: 3701: }
- -: 3702:
- 644271: 3703: optimize_info_seq_step(info, &info_seq);
- 644271: 3704: le = scheme_optimize_expr(app->args[i], info, sub_context);
- 644271: 3705: app->args[i] = le;
- 644271: 3706: if (info->escapes) {
- -: 3707: int j;
- -: 3708: Scheme_Object *e, *l;
- 23: 3709: optimize_info_seq_done(info, &info_seq);
- -: 3710:
- 23: 3711: l = scheme_make_pair(app->args[i], scheme_null);
- -: 3712:
- 88: 3713: for (j = i - 1; j >= 0; j--) {
- 65: 3714: e = app->args[j];
- 65: 3715: e = optimize_ignored(e, info, 1, 1, 5);
- 65: 3716: if (e) {
- 24: 3717: e = ensure_single_value(e);
- 24: 3718: l = scheme_make_pair(e, l);
- -: 3719: }
- -: 3720: }
- 23: 3721: return ensure_noncm(scheme_make_sequence_compilation(l, 1, 0));
- -: 3722: }
- -: 3723:
- 644248: 3724: if (!i) {
- -: 3725: /* Maybe found "((lambda" after optimizing; try again */
- 144189: 3726: le = optimize_for_inline(info, app->args[i], n - 1, app, NULL, NULL, context, 1);
- 144189: 3727: if (le)
- 51: 3728: return le;
- 144138: 3729: if (SAME_OBJ(app->args[0], scheme_values_proc)
- 135754: 3730: || SAME_OBJ(app->args[0], scheme_apply_proc))
- 11281: 3731: info->maybe_values_argument = 1;
- 144138: 3732: rator_apply_escapes = info->escapes;
- -: 3733: }
- -: 3734: }
- -: 3735:
- 144117: 3736: optimize_info_seq_done(info, &info_seq);
- -: 3737:
- -: 3738: /* Check for (apply ... (list ...)) after some optimizations: */
- 144117: 3739: le = direct_apply((Scheme_Object *)app, app->args[0], app->args[app->num_args], info);
- 144117: 3740: if (le) return finish_optimize_app(le, info, context);
- -: 3741:
- -: 3742: /* Convert (hash-ref '#hash... key (lambda () literal))
- -: 3743: to (hash-ref '#hash... key literal) */
- 143491: 3744: if ((app->num_args == 3)
- 67681: 3745: && SAME_OBJ(scheme_hash_ref_proc, app->args[0])
- 2002: 3746: && SCHEME_HASHTRP(app->args[1])
- 37: 3747: && SAME_TYPE(scheme_ir_lambda_type, SCHEME_TYPE(app->args[3]))
- 12: 3748: && (SCHEME_TYPE(((Scheme_Lambda *)app->args[3])->body) > _scheme_ir_values_types_)
- 12: 3749: && !SCHEME_PROCP(((Scheme_Lambda *)app->args[3])->body)) {
- 10: 3750: app->args[3] = ((Scheme_Lambda *)app->args[3])->body;
- -: 3751: }
- -: 3752:
- 143491: 3753: if (rator_apply_escapes) {
- 52: 3754: info->escapes = 1;
- 52: 3755: SCHEME_APPN_FLAGS(app) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- -: 3756: }
- -: 3757:
- 143491: 3758: return finish_optimize_application(app, info, context);
- -: 3759:}
- -: 3760:
- 1180703: 3761:static int appn_flags(Scheme_Object *rator, Optimize_Info *info)
- -: 3762:/* Record some properties of an application that are useful to the SFS pass. */
- -: 3763:{
- 1180703: 3764: if (SAME_TYPE(SCHEME_TYPE(rator), scheme_ir_toplevel_type)) {
- 232512: 3765: if (info->top_level_consts) {
- -: 3766: int pos;
- 88793: 3767: pos = SCHEME_TOPLEVEL_POS(rator);
- 88793: 3768: rator = scheme_hash_get(info->top_level_consts, scheme_make_integer(pos));
- 88793: 3769: rator = no_potential_size(rator);
- 88793: 3770: if (!rator) return 0;
- 20447: 3771: if (SAME_TYPE(SCHEME_TYPE(rator), scheme_proc_shape_type)) {
- #####: 3772: return APPN_FLAG_SFS_TAIL;
- 20447: 3773: } else if (SAME_TYPE(SCHEME_TYPE(rator), scheme_struct_proc_shape_type)) {
- 6415: 3774: int ps = SCHEME_PROC_SHAPE_MODE(rator);
- 6415: 3775: if ((ps == STRUCT_PROC_SHAPE_PRED)
- 4508: 3776: || (ps == STRUCT_PROC_SHAPE_GETTER)
- 3548: 3777: || (ps == STRUCT_PROC_SHAPE_SETTER))
- 2867: 3778: return (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- 3548: 3779: return 0;
- -: 3780: }
- -: 3781: }
- -: 3782: }
- -: 3783:
- 1105942: 3784: if (SCHEME_PRIMP(rator)) {
- 813567: 3785: int opt = (SCHEME_PRIM_PROC_FLAGS(rator) & SCHEME_PRIM_OPT_MASK);
- 813567: 3786: if (opt >= SCHEME_PRIM_OPT_IMMEDIATE)
- 653376: 3787: return (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- 160191: 3788: return 0;
- -: 3789: }
- -: 3790:
- 292375: 3791: if (SCHEME_LAMBDAP(rator)
- 281137: 3792: || SAME_TYPE(scheme_noninline_proc_type, SCHEME_TYPE(rator)))
- 13301: 3793: return APPN_FLAG_SFS_TAIL;
- -: 3794:
- 279074: 3795: return 0;
- -: 3796:}
- -: 3797:
- 18870174: 3798:static int check_known_variant(Optimize_Info *info, Scheme_Object *app,
- -: 3799: Scheme_Object *rator, Scheme_Object *rand,
- -: 3800: const char *who, Scheme_Object *expect_pred, Scheme_Object *unsafe,
- -: 3801: Scheme_Object *implies_pred)
- -: 3802:/* Replace the rator with an unsafe version if we know that it's ok:
- -: 3803: if the argument is consistent with `expect_pred`; if `unsafe` is
- -: 3804: #t, then just mark the application as omittable. Alternatively, the
- -: 3805: rator implies a check, so add type information for subsequent
- -: 3806: expressions: the argument is consistent with `implies_pred` (which
- -: 3807: must be itself implied by `expected_pred`, but might be weaker). If
- -: 3808: the rand has already an incompatible type, mark that this will
- -: 3809: generate an error. If unsafe is NULL then rator has no unsafe
- -: 3810: version, so only check the type. */
- -: 3811:{
- 18870174: 3812: if (SCHEME_PRIMP(rator) && (!who || IS_NAMED_PRIM(rator, who))) {
- -: 3813: Scheme_Object *pred;
- -: 3814:
- 265035: 3815: pred = expr_implies_predicate(rand, info);
- 265035: 3816: if (pred) {
- 161814: 3817: if (predicate_implies(pred, expect_pred)) {
- 154424: 3818: if (unsafe) {
- 31202: 3819: if (SAME_OBJ(unsafe, scheme_true))
- 17634: 3820: set_application_omittable(app, unsafe);
- -: 3821: else
- 13568: 3822: reset_rator(app, unsafe);
- -: 3823: }
- 154424: 3824: return 1;
- 7390: 3825: } else if (predicate_implies_not(pred, implies_pred)) {
- 117: 3826: info->escapes = 1;
- -: 3827: }
- -: 3828: } else {
- 103221: 3829: if (SAME_TYPE(SCHEME_TYPE(rand), scheme_ir_local_type))
- 84085: 3830: add_type(info, rand, implies_pred);
- -: 3831: }
- -: 3832: }
- -: 3833:
- 18715750: 3834: return 0;
- -: 3835:}
- -: 3836:
- 18127802: 3837:static void check_known(Optimize_Info *info, Scheme_Object *app,
- -: 3838: Scheme_Object *rator, Scheme_Object *rand,
- -: 3839: const char *who, Scheme_Object *expect_pred, Scheme_Object *unsafe)
- -: 3840:/* When the expected predicate for unsafe substitution is the same as the implied predicate. */
- -: 3841:{
- 18127802: 3842: (void)check_known_variant(info, app, rator, rand, who, expect_pred, unsafe, expect_pred);
- 18127802: 3843:}
- -: 3844:
- 914681: 3845:static void check_known_rator(Optimize_Info *info, Scheme_Object *rator)
- -: 3846:/* Check that rator is a procedure or add type information for subsequent expressions. */
- -: 3847:{
- -: 3848: Scheme_Object *pred;
- -: 3849:
- 914681: 3850: pred = expr_implies_predicate(rator, info);
- 914681: 3851: if (pred) {
- 704966: 3852: if (predicate_implies_not(pred, scheme_procedure_p_proc))
- 2: 3853: info->escapes = 1;
- -: 3854: } else {
- 209715: 3855: if (SAME_TYPE(SCHEME_TYPE(rator), scheme_ir_local_type))
- 32836: 3856: add_type(info, rator, scheme_procedure_p_proc);
- -: 3857: }
- 914681: 3858:}
- -: 3859:
- 2709602: 3860:static void check_known_both_try(Optimize_Info *info, Scheme_Object *app,
- -: 3861: Scheme_Object *rator, Scheme_Object *rand1, Scheme_Object *rand2,
- -: 3862: const char *who, Scheme_Object *expect_pred, Scheme_Object *unsafe)
- -: 3863:/* Replace the rator with an unsafe version if both rands have the right type.
- -: 3864: If not, don't save the type, nor mark this as an error */
- -: 3865:{
- 2709602: 3866: if (SCHEME_PRIMP(rator) && (!who || IS_NAMED_PRIM(rator, who))) {
- -: 3867: Scheme_Object *pred1, *pred2;
- -: 3868:
- 10664: 3869: pred1 = expr_implies_predicate(rand1, info);
- 10664: 3870: if (pred1 && SAME_OBJ(pred1, expect_pred)) {
- 1844: 3871: pred2 = expr_implies_predicate(rand2, info);
- 1844: 3872: if (pred2 && SAME_OBJ(pred2, expect_pred)) {
- 777: 3873: reset_rator(app, unsafe);
- -: 3874: }
- -: 3875: }
- -: 3876: }
- 2709602: 3877:}
- -: 3878:
- 1568123: 3879:static void check_known_both_variant(Optimize_Info *info, Scheme_Object *app,
- -: 3880: Scheme_Object *rator, Scheme_Object *rand1, Scheme_Object *rand2,
- -: 3881: const char *who, Scheme_Object *expect_pred, Scheme_Object *unsafe,
- -: 3882: Scheme_Object *implies_pred)
- -: 3883:{
- 1568123: 3884: if (SCHEME_PRIMP(rator) && (!who || IS_NAMED_PRIM(rator, who))) {
- -: 3885: int ok1;
- 21554: 3886: ok1 = check_known_variant(info, app, rator, rand1, who, expect_pred, NULL, implies_pred);
- 21554: 3887: check_known_variant(info, app, rator, rand2, who, expect_pred, (ok1 ? unsafe : NULL), implies_pred);
- -: 3888: }
- 1568123: 3889:}
- -: 3890:
- 406865: 3891:static void check_known_both(Optimize_Info *info, Scheme_Object *app,
- -: 3892: Scheme_Object *rator, Scheme_Object *rand1, Scheme_Object *rand2,
- -: 3893: const char *who, Scheme_Object *expect_pred, Scheme_Object *unsafe)
- -: 3894:{
- 406865: 3895: check_known_both_variant(info, app, rator, rand1, rand2, who, expect_pred, unsafe, expect_pred);
- 406865: 3896:}
- -: 3897:
- -: 3898:
- 554756: 3899:static void check_known_all(Optimize_Info *info, Scheme_Object *_app, int skip_head, int skip_tail,
- -: 3900: const char *who, Scheme_Object *expect_pred, Scheme_Object *unsafe)
- -: 3901:{
- 554756: 3902: Scheme_App_Rec *app = (Scheme_App_Rec *)_app;
- 554756: 3903: if (SCHEME_PRIMP(app->args[0]) && (!who || IS_NAMED_PRIM(app->args[0], who))) {
- 2794: 3904: int ok_so_far = 1, i;
- -: 3905:
- 10858: 3906: for (i = skip_head; i < app->num_args - skip_tail; i++) {
- 8064: 3907: if (!check_known_variant(info, _app, app->args[0], app->args[i+1], who, expect_pred,
- -: 3908: NULL, expect_pred))
- 4670: 3909: ok_so_far = 0;
- -: 3910: }
- -: 3911:
- 2794: 3912: if (ok_so_far && unsafe) {
- 483: 3913: if (SAME_OBJ(unsafe, scheme_true))
- 483: 3914: set_application_omittable(_app, unsafe);
- -: 3915: else
- #####: 3916: reset_rator(_app, unsafe);
- -: 3917: }
- -: 3918: }
- 554756: 3919:}
- -: 3920:
- 914681: 3921:static Scheme_Object *finish_optimize_any_application(Scheme_Object *app, Scheme_Object *rator, int argc,
- -: 3922: Optimize_Info *info, int context)
- -: 3923:{
- 914681: 3924: check_known_rator(info, rator);
- -: 3925:
- 914681: 3926: if ((context & OPT_CONTEXT_BOOLEAN) && !info->escapes) {
- -: 3927: Scheme_Object *pred;
- 184264: 3928: pred = rator_implies_predicate(rator, info, argc);
- 184264: 3929: if (pred && predicate_implies_not(pred, scheme_not_proc))
- 25: 3930: return make_discarding_sequence(app, scheme_true, info);
- 184239: 3931: else if (pred && predicate_implies(pred, scheme_not_proc))
- #####: 3932: return make_discarding_sequence(app, scheme_false, info);
- -: 3933: }
- -: 3934:
- 914656: 3935: if (SAME_OBJ(rator, scheme_void_proc))
- 94: 3936: return make_discarding_sequence(app, scheme_void, info);
- -: 3937:
- 914562: 3938: if (is_always_escaping_primitive(rator)) {
- 18853: 3939: info->escapes = 1;
- -: 3940: }
- -: 3941:
- 914562: 3942: return app;
- -: 3943:}
- -: 3944:
- 931185: 3945:static void increment_clock_counts_for_application(GC_CAN_IGNORE int *_vclock,
- -: 3946: GC_CAN_IGNORE int *_aclock,
- -: 3947: GC_CAN_IGNORE int *_kclock,
- -: 3948: GC_CAN_IGNORE int *_sclock,
- -: 3949: Scheme_Object *rator,
- -: 3950: int argc)
- -: 3951:{
- 931185: 3952: if (!is_nonmutating_nondependant_primitive(rator, argc))
- 735224: 3953: *_vclock += 1;
- 195961: 3954: else if (is_primitive_allocating(rator, argc))
- 76213: 3955: *_aclock += 1;
- -: 3956:
- 931185: 3957: if (!is_noncapturing_primitive(rator, argc))
- 388486: 3958: *_kclock += 1;
- -: 3959:
- 931185: 3960: if (!is_nonsaving_primitive(rator, argc))
- 410815: 3961: *_sclock += 1;
- 931185: 3962:}
- -: 3963:
- 926492: 3964:static void increment_clocks_for_application(Optimize_Info *info,
- -: 3965: Scheme_Object *rator,
- -: 3966: int argc)
- -: 3967:{
- -: 3968: int v, a, k, s;
- -: 3969:
- 926492: 3970: v = info->vclock;
- 926492: 3971: a = info->aclock;
- 926492: 3972: k = info->kclock;
- 926492: 3973: s = info->sclock;
- -: 3974:
- 926492: 3975: increment_clock_counts_for_application(&v, &a, &k, &s, rator, argc);
- -: 3976:
- 926492: 3977: info->vclock = v;
- 926492: 3978: info->aclock = a;
- 926492: 3979: info->kclock = k;
- 926492: 3980: info->sclock = s;
- 926492: 3981:}
- -: 3982:
- 144103: 3983:static Scheme_Object *finish_optimize_application(Scheme_App_Rec *app, Optimize_Info *info, int context)
- -: 3984:{
- -: 3985: Scheme_Object *le;
- 144103: 3986: Scheme_Object *rator = app->args[0], *rator_for_flags;
- 144103: 3987: int all_vals = 1, i, flags, rator_flags;
- -: 3988:
- 788190: 3989: for (i = app->num_args; i--; ) {
- 499984: 3990: if (SCHEME_TYPE(app->args[i+1]) < _scheme_ir_values_types_)
- 324698: 3991: all_vals = 0;
- -: 3992: }
- -: 3993:
- 144103: 3994: info->size += 1;
- 144103: 3995: increment_clocks_for_application(info, rator, app->num_args);
- -: 3996:
- 144103: 3997: if (all_vals) {
- 34136: 3998: le = try_optimize_fold(rator, NULL, (Scheme_Object *)app, info);
- 34136: 3999: if (le)
- 2: 4000: return le;
- -: 4001: }
- -: 4002:
- 144101: 4003: if (!app->num_args
- 25404: 4004: && (SAME_OBJ(rator, scheme_list_proc)
- 23105: 4005: || (SCHEME_PRIMP(rator) && IS_NAMED_PRIM(rator, "append")))) {
- 2308: 4006: info->preserves_marks = 1;
- 2308: 4007: info->single_result = 1;
- 2308: 4008: return scheme_null;
- -: 4009: }
- -: 4010:
- 141793: 4011: rator_for_flags = lookup_constant_proc(info, rator, app->num_args);
- 141793: 4012: rator_flags = scheme_get_rator_flags(rator_for_flags);
- 141793: 4013: info->preserves_marks = !!(rator_flags & LAMBDA_PRESERVES_MARKS);
- 141793: 4014: info->single_result = !!(rator_flags & LAMBDA_SINGLE_RESULT);
- 141793: 4015: if (rator_flags & LAMBDA_RESULT_TENTATIVE) {
- 6358: 4016: info->preserves_marks = -info->preserves_marks;
- 6358: 4017: info->single_result = -info->single_result;
- -: 4018: }
- -: 4019:
- 141793: 4020: if (SCHEME_PRIMP(app->args[0])
- 79193: 4021: && (app->num_args >= ((Scheme_Primitive_Proc *)app->args[0])->mina)
- 79183: 4022: && (app->num_args <= ((Scheme_Primitive_Proc *)app->args[0])->mu.maxa)) {
- 79163: 4023: Scheme_Object *app_o = (Scheme_Object *)app, *rator = app->args[0];
- 79163: 4024: Scheme_Object *rand1 = NULL, *rand2 = NULL, *rand3 = NULL;
- -: 4025:
- 79163: 4026: if (app->num_args >= 1)
- 65953: 4027: rand1 = app->args[1];
- -: 4028:
- 79163: 4029: if (app->num_args >= 2)
- 65953: 4030: rand2 = app->args[2];
- -: 4031:
- 79163: 4032: if (app->num_args >= 3)
- 65953: 4033: rand3 = app->args[3];
- -: 4034:
- 79163: 4035: check_known(info, app_o, rator, rand1, "vector-set!", scheme_vector_p_proc, NULL);
- 79163: 4036: check_known(info, app_o, rator, rand2, "vector-set!", scheme_fixnum_p_proc, NULL);
- -: 4037:
- 79163: 4038: check_known(info, app_o, rator, rand1, "procedure-arity-includes?", scheme_procedure_p_proc, NULL);
- -: 4039:
- 79163: 4040: check_known(info, app_o, rator, rand1, "map", scheme_procedure_p_proc, NULL);
- 79163: 4041: check_known(info, app_o, rator, rand1, "for-each", scheme_procedure_p_proc, NULL);
- 79163: 4042: check_known(info, app_o, rator, rand1, "andmap", scheme_procedure_p_proc, NULL);
- 79163: 4043: check_known(info, app_o, rator, rand1, "ormap", scheme_procedure_p_proc, NULL);
- 79163: 4044: check_known_all(info, app_o, 1, 0, "map", scheme_list_p_proc, NULL);
- 79163: 4045: check_known_all(info, app_o, 1, 0, "for-each", scheme_list_p_proc, NULL);
- 79163: 4046: check_known_all(info, app_o, 1, 0, "andmap", scheme_list_p_proc, NULL);
- 79163: 4047: check_known_all(info, app_o, 1, 0, "ormap", scheme_list_p_proc, NULL);
- -: 4048:
- 79163: 4049: check_known(info, app_o, rator, rand1, "string-set!", scheme_string_p_proc, NULL);
- 79163: 4050: check_known(info, app_o, rator, rand2, "string-set!", scheme_fixnum_p_proc, NULL);
- 79163: 4051: check_known(info, app_o, rator, rand3, "string-set!", scheme_char_p_proc, NULL);
- 79163: 4052: check_known(info, app_o, rator, rand1, "bytes-set!", scheme_byte_string_p_proc, NULL);
- 79163: 4053: check_known(info, app_o, rator, rand2, "bytes-set!", scheme_fixnum_p_proc, NULL);
- 79163: 4054: check_known(info, app_o, rator, rand3, "bytes-set!", scheme_fixnum_p_proc, NULL);
- -: 4055:
- 79163: 4056: check_known_all(info, app_o, 0, 0, "string-append", scheme_string_p_proc, scheme_true);
- 79163: 4057: check_known_all(info, app_o, 0, 0, "bytes-append", scheme_byte_string_p_proc, scheme_true);
- -: 4058:
- 79163: 4059: check_known_all(info, app_o, 0, 1, "append", scheme_list_p_proc, scheme_true);
- -: 4060:
- 79163: 4061: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_WANTS_REAL)
- 282: 4062: check_known_all(info, app_o, 0, 0, NULL, scheme_real_p_proc,
- 282: 4063: (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_OMITTABLE_ON_GOOD_ARGS) ? scheme_true : NULL);
- 79163: 4064: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_WANTS_NUMBER)
- 333: 4065: check_known_all(info, app_o, 0, 0, NULL, scheme_number_p_proc,
- 333: 4066: (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_OMITTABLE_ON_GOOD_ARGS) ? scheme_true : NULL);
- -: 4067: }
- -: 4068:
- 141793: 4069: register_local_argument_types(app, NULL, NULL, info);
- -: 4070:
- 141793: 4071: flags = appn_flags(app->args[0], info);
- 141793: 4072: SCHEME_APPN_FLAGS(app) |= flags;
- -: 4073:
- 141793: 4074: return finish_optimize_any_application((Scheme_Object *)app, app->args[0], app->num_args,
- -: 4075: info, context);
- -: 4076:}
- -: 4077:
- 349625: 4078:static Scheme_Object *try_reduce_predicate(Scheme_Object *rator, Scheme_Object *rand,
- -: 4079: Optimize_Info *info)
- -: 4080:/* Change (pair? (list X complex-Y Z)) => (begin complex-Y #t), etc.
- -: 4081: It's especially nice to avoid the constructions. */
- -: 4082:{
- -: 4083: Scheme_Object *pred;
- -: 4084:
- 349625: 4085: if (!relevant_predicate(rator))
- 263476: 4086: return NULL;
- -: 4087:
- 86149: 4088: pred = expr_implies_predicate(rand, info);
- -: 4089:
- 86149: 4090: if (!pred)
- 75954: 4091: return NULL;
- -: 4092:
- 10195: 4093: if (predicate_implies(pred, rator))
- 2407: 4094: return make_discarding_sequence(rand, scheme_true, info);
- 7788: 4095: else if (predicate_implies_not(pred, rator))
- 768: 4096: return make_discarding_sequence(rand, scheme_false, info);
- -: 4097:
- 7020: 4098: return NULL;
- -: 4099:}
- -: 4100:
- 533183: 4101:static Scheme_Object *check_ignored_call_cc(Scheme_Object *rator, Scheme_Object *rand,
- -: 4102: Optimize_Info *info, int context)
- -: 4103:/* Convert (call/cc (lambda (ignored) body ...)) to (begin body ...) */
- -: 4104:{
- 533183: 4105: if (SCHEME_PRIMP(rator)
- 351589: 4106: && (IS_NAMED_PRIM(rator, "call-with-current-continuation")
- 351585: 4107: || IS_NAMED_PRIM(rator, "call-with-composable-continuation")
- 351576: 4108: || IS_NAMED_PRIM(rator, "call-with-escape-continuation"))) {
- -: 4109: Scheme_Object *proc;
- -: 4110:
- 587: 4111: proc = lookup_constant_proc(info, rand, 1);
- -: 4112:
- 587: 4113: if (proc && SAME_TYPE(SCHEME_TYPE(proc), scheme_ir_lambda_type)) {
- 587: 4114: Scheme_Lambda *lam = (Scheme_Lambda *)proc;
- 587: 4115: if (lam->num_params == 1) {
- 587: 4116: Scheme_IR_Lambda_Info *cl = lam->ir_info;
- 587: 4117: if (!cl->vars[0]->use_count) {
- -: 4118: Scheme_Object *expr;
- 8: 4119: info->vclock++;
- 8: 4120: expr = make_application_2(rand, scheme_void, info);
- 8: 4121: if (IS_NAMED_PRIM(rator, "call-with-escape-continuation")) {
- -: 4122: Scheme_Sequence *seq;
- -: 4123:
- 2: 4124: seq = scheme_malloc_sequence(1);
- 2: 4125: seq->so.type = scheme_begin0_sequence_type;
- 2: 4126: seq->count = 1;
- 2: 4127: seq->array[0] = expr;
- -: 4128:
- 2: 4129: expr = (Scheme_Object *)seq;
- -: 4130: }
- 8: 4131: return scheme_optimize_expr(expr, info, context);
- -: 4132: }
- -: 4133: }
- -: 4134: }
- -: 4135: }
- 533175: 4136: return NULL;
- -: 4137:}
- -: 4138:
- 579: 4139:static Scheme_Object *make_optimize_prim_application2(Scheme_Object *prim, Scheme_Object *rand,
- -: 4140: Optimize_Info *info, int context)
- -: 4141:/* make (prim rand) and optimize it. rand must be already optimized */
- -: 4142:{
- -: 4143: Scheme_Object *alt;
- 579: 4144: alt = make_application_2(prim, rand, info);
- -: 4145: /* scheme_make_application may use constant folding, check that alt is not a constant */
- 579: 4146: if (SAME_TYPE(SCHEME_TYPE(alt), scheme_application2_type)) {
- 579: 4147: return finish_optimize_application2((Scheme_App2_Rec *)alt, info, context);
- -: 4148: } else
- #####: 4149: return alt;
- -: 4150:}
- -: 4151:
- -: 4152:
- 534503: 4153:static Scheme_Object *optimize_application2(Scheme_Object *o, Optimize_Info *info, int context)
- -: 4154:{
- -: 4155: Scheme_App2_Rec *app;
- -: 4156: Scheme_Object *le;
- -: 4157: int rator_apply_escapes, sub_context, ty;
- -: 4158: Optimize_Info_Sequence info_seq;
- -: 4159:
- 534503: 4160: app = (Scheme_App2_Rec *)o;
- -: 4161:
- 534503: 4162: le = check_app_let_rator(o, app->rator, info, 1, context);
- 534503: 4163: if (le)
- 1320: 4164: return le;
- -: 4165:
- 533183: 4166: le = check_ignored_call_cc(app->rator, app->rand, info, context);
- 533183: 4167: if (le)
- 8: 4168: return le;
- -: 4169:
- 533175: 4170: le = optimize_for_inline(info, app->rator, 1, NULL, app, NULL, context, 0);
- 533174: 4171: if (le)
- 15322: 4172: return le;
- -: 4173:
- 517852: 4174: optimize_info_seq_init(info, &info_seq);
- -: 4175:
- 517852: 4176: sub_context = OPT_CONTEXT_SINGLED;
- -: 4177:
- 517852: 4178: le = scheme_optimize_expr(app->rator, info, sub_context);
- 517852: 4179: app->rator = le;
- 517852: 4180: if (info->escapes) {
- 2: 4181: optimize_info_seq_done(info, &info_seq);
- 2: 4182: return ensure_noncm(app->rator);
- -: 4183: }
- -: 4184:
- -: 4185: {
- -: 4186: /* Maybe found "((lambda" after optimizing; try again */
- 517850: 4187: le = optimize_for_inline(info, app->rator, 1, NULL, app, NULL, context, 1);
- 517850: 4188: if (le)
- 189: 4189: return le;
- 517661: 4190: rator_apply_escapes = info->escapes;
- -: 4191: }
- -: 4192:
- 517661: 4193: if (SAME_PTR(scheme_not_proc, app->rator)){
- 5223: 4194: sub_context |= OPT_CONTEXT_BOOLEAN;
- -: 4195: } else {
- 512438: 4196: ty = wants_local_type_arguments(app->rator, 0);
- 512438: 4197: if (ty)
- 8: 4198: sub_context |= (ty << OPT_CONTEXT_TYPE_SHIFT);
- -: 4199: }
- -: 4200:
- 517661: 4201: optimize_info_seq_step(info, &info_seq);
- -: 4202:
- 517661: 4203: le = scheme_optimize_expr(app->rand, info, sub_context);
- 517661: 4204: app->rand = le;
- 517661: 4205: optimize_info_seq_done(info, &info_seq);
- 517661: 4206: if (info->escapes) {
- 18: 4207: info->size += 1;
- 18: 4208: return ensure_noncm(make_discarding_first_sequence(app->rator, app->rand, info));
- -: 4209: }
- -: 4210:
- 517643: 4211: if (rator_apply_escapes) {
- 10: 4212: info->escapes = 1;
- 10: 4213: SCHEME_APPN_FLAGS(app) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- -: 4214: }
- -: 4215:
- 517643: 4216: return finish_optimize_application2(app, info, context);
- -: 4217:}
- -: 4218:
- 518253: 4219:static Scheme_Object *finish_optimize_application2(Scheme_App2_Rec *app, Optimize_Info *info, int context)
- -: 4220:{
- -: 4221: int flags, rator_flags;
- 518253: 4222: Scheme_Object *rator = app->rator, *rator_for_flags;
- 518253: 4223: Scheme_Object *rand, *inside = NULL, *alt;
- -: 4224:
- 518253: 4225: info->size += 1;
- -: 4226:
- -: 4227: /* Path for direct constant folding */
- 518253: 4228: if (SCHEME_TYPE(app->rand) > _scheme_ir_values_types_) {
- -: 4229: Scheme_Object *le;
- 34235: 4230: le = try_optimize_fold(rator, NULL, (Scheme_Object *)app, info);
- 34235: 4231: if (le)
- 2510: 4232: return le;
- -: 4233: }
- -: 4234:
- 515743: 4235: rand = app->rand;
- -: 4236:
- -: 4237: /* We can go inside a `begin' and a `let', which is useful in case
- -: 4238: the argument was a function call that has been inlined. */
- 515743: 4239: extract_tail_inside(&rand, &inside);
- -: 4240:
- 515743: 4241: if (SCHEME_TYPE(rand) > _scheme_ir_values_types_) {
- -: 4242: Scheme_Object *le;
- 31737: 4243: le = try_optimize_fold(rator, scheme_make_pair(rand, scheme_null), NULL, info);
- 31737: 4244: if (le)
- 12: 4245: return replace_tail_inside(le, inside, app->rand);
- -: 4246: }
- -: 4247:
- 515731: 4248: increment_clocks_for_application(info, rator, 1);
- -: 4249:
- 515731: 4250: rator_for_flags = lookup_constant_proc(info, rator, 1);
- 515731: 4251: rator_flags = scheme_get_rator_flags(rator_for_flags);
- 515731: 4252: info->preserves_marks = !!(rator_flags & LAMBDA_PRESERVES_MARKS);
- 515731: 4253: info->single_result = !!(rator_flags & LAMBDA_SINGLE_RESULT);
- 515731: 4254: if (rator_flags & LAMBDA_RESULT_TENTATIVE) {
- 8504: 4255: info->preserves_marks = -info->preserves_marks;
- 8504: 4256: info->single_result = -info->single_result;
- -: 4257: }
- -: 4258:
- 515731: 4259: if (SAME_OBJ(scheme_values_proc, rator)
- 511164: 4260: || SAME_OBJ(scheme_list_star_proc, rator)
- 511158: 4261: || (SCHEME_PRIMP(rator) && IS_NAMED_PRIM(rator, "append"))) {
- 4589: 4262: SCHEME_APPN_FLAGS(app) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- 4589: 4263: info->preserves_marks = 1;
- 4589: 4264: info->single_result = 1;
- 4589: 4265: if ((context & OPT_CONTEXT_SINGLED)
- 4123: 4266: || scheme_omittable_expr(rand, 1, -1, 0, info, info)
- 3936: 4267: || single_valued_noncm_expression(rand, 5)) {
- 701: 4268: return replace_tail_inside(rand, inside, app->rand);
- -: 4269: }
- 3888: 4270: app->rator = scheme_values_proc;
- 3888: 4271: rator = scheme_values_proc;
- -: 4272: }
- -: 4273:
- 515030: 4274: if (SCHEME_PRIMP(rator)) {
- -: 4275: /* Check for things like (cXr (cons X Y)): */
- 349785: 4276: switch (SCHEME_TYPE(rand)) {
- -: 4277: case scheme_application2_type:
- -: 4278: {
- 29322: 4279: Scheme_App2_Rec *app2 = (Scheme_App2_Rec *)rand;
- 29322: 4280: if (IS_NAMED_PRIM(rator, "car")
- 27722: 4281: || IS_NAMED_PRIM(rator, "unsafe-car")) {
- 3198: 4282: if (SAME_OBJ(scheme_list_proc, app2->rator)) {
- -: 4283: /* (car (list X)) */
- 2: 4284: alt = ensure_single_value_noncm(app2->rand);
- 2: 4285: return replace_tail_inside(alt, inside, app->rand);
- -: 4286: }
- 27722: 4287: } else if (IS_NAMED_PRIM(rator, "cdr")
- 26652: 4288: || IS_NAMED_PRIM(rator, "unsafe-cdr")) {
- 2112: 4289: if (SAME_OBJ(scheme_list_proc, app2->rator)) {
- -: 4290: /* (cdr (list X)) */
- 28: 4291: alt = make_discarding_sequence(app2->rand, scheme_null, info);
- 28: 4292: return replace_tail_inside(alt, inside, app->rand);
- -: 4293: }
- 26652: 4294: } else if (IS_NAMED_PRIM(rator, "unbox")
- 26412: 4295: || IS_NAMED_PRIM(rator, "unsafe-unbox")
- 26410: 4296: || IS_NAMED_PRIM(rator, "unsafe-unbox*")) {
- 244: 4297: if (SAME_OBJ(scheme_box_proc, app2->rator)) {
- -: 4298: /* (unbox (box X)) */
- 6: 4299: alt = ensure_single_value_noncm(app2->rand);
- 6: 4300: return replace_tail_inside(alt, inside, app->rand);
- -: 4301: }
- -: 4302: }
- 29286: 4303: break;
- -: 4304: }
- -: 4305: case scheme_application3_type:
- -: 4306: {
- 22893: 4307: Scheme_App3_Rec *app3 = (Scheme_App3_Rec *)rand;
- 22893: 4308: if (IS_NAMED_PRIM(rator, "car")
- 22792: 4309: || IS_NAMED_PRIM(rator, "unsafe-car")) {
- 154: 4310: if (SAME_OBJ(scheme_cons_proc, app3->rator)
- 65: 4311: || SAME_OBJ(scheme_unsafe_cons_list_proc, app3->rator)
- 63: 4312: || SAME_OBJ(scheme_list_proc, app3->rator)
- 55: 4313: || SAME_OBJ(scheme_list_star_proc, app3->rator)) {
- -: 4314: /* (car ({cons|list|list*} X Y)) */
- 52: 4315: alt = make_discarding_reverse_sequence(app3->rand2, app3->rand1, info);
- 52: 4316: return replace_tail_inside(alt, inside, app->rand);
- -: 4317: }
- 22790: 4318: } else if (IS_NAMED_PRIM(rator, "cdr")
- 22505: 4319: || IS_NAMED_PRIM(rator, "unsafe-cdr")) {
- 730: 4320: if (SAME_OBJ(scheme_cons_proc, app3->rator)
- 367: 4321: || SAME_OBJ(scheme_unsafe_cons_list_proc, app3->rator)
- 365: 4322: || SAME_OBJ(scheme_list_star_proc, app3->rator)) {
- -: 4323: /* (cdr ({cons|list*} X Y)) */
- 32: 4324: alt = make_discarding_sequence(app3->rand1, app3->rand2, info);
- 32: 4325: return replace_tail_inside(alt, inside, app->rand);
- 363: 4326: } else if (SAME_OBJ(scheme_list_proc, app3->rator)) {
- -: 4327: /* (cdr (list X Y)) */
- 28: 4328: alt = make_application_2(scheme_list_proc, app3->rand2, info);
- 28: 4329: SCHEME_APPN_FLAGS(((Scheme_App_Rec *)alt)) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- 28: 4330: alt = make_discarding_sequence(app3->rand1, alt, info);
- 28: 4331: return replace_tail_inside(alt, inside, app->rand);
- -: 4332: }
- 22395: 4333: } else if (IS_NAMED_PRIM(rator, "cadr")) {
- 34: 4334: if (SAME_OBJ(scheme_list_proc, app3->rator)) {
- -: 4335: /* (cadr (list X Y)) */
- 2: 4336: alt = make_discarding_sequence(app3->rand1, app3->rand2, info);
- 2: 4337: return replace_tail_inside(alt, inside, app->rand);
- -: 4338: }
- -: 4339: }
- 22779: 4340: break;
- -: 4341: }
- -: 4342: case scheme_application_type:
- -: 4343: {
- 3058: 4344: Scheme_App_Rec *appr = (Scheme_App_Rec *)rand;
- 3058: 4345: Scheme_Object *r = appr->args[0];
- 3058: 4346: if (IS_NAMED_PRIM(rator, "car")
- 3046: 4347: || IS_NAMED_PRIM(rator, "unsafe-car")) {
- 20: 4348: if ((appr->args > 0)
- 12: 4349: && (SAME_OBJ(scheme_list_proc, r)
- 10: 4350: || SAME_OBJ(scheme_list_star_proc, r))) {
- -: 4351: /* (car ({list|list*} X Y ...)) */
- 4: 4352: alt = make_discarding_app_sequence(appr, 0, NULL, info);
- 4: 4353: return replace_tail_inside(alt, inside, app->rand);
- -: 4354: }
- 3046: 4355: } else if (IS_NAMED_PRIM(rator, "cdr")
- 3029: 4356: || IS_NAMED_PRIM(rator, "unsafe-cdr")) {
- -: 4357: /* (cdr ({list|list*} X Y ...)) */
- 17: 4358: if ((appr->args > 0)
- 17: 4359: && (SAME_OBJ(scheme_list_proc, r)
- 13: 4360: || SAME_OBJ(scheme_list_star_proc, r))) {
- 6: 4361: Scheme_Object *al = scheme_null;
- -: 4362: int k;
- 18: 4363: for (k = appr->num_args; k > 1; k--) {
- 12: 4364: al = scheme_make_pair(appr->args[k], al);
- -: 4365: }
- 6: 4366: al = scheme_make_pair(r, al);
- 6: 4367: alt = scheme_make_application(al, info);
- 6: 4368: SCHEME_APPN_FLAGS(((Scheme_App_Rec *)alt)) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- 6: 4369: alt = make_discarding_sequence(appr->args[1], alt, info);
- 6: 4370: return replace_tail_inside(alt, inside, app->rand);
- -: 4371: }
- -: 4372: }
- 3048: 4373: break;
- -: 4374: }
- -: 4375: }
- -: 4376:
- 349625: 4377: alt = try_reduce_predicate(rator, rand, info);
- 349625: 4378: if (alt)
- 3175: 4379: return replace_tail_inside(alt, inside, app->rand);
- -: 4380:
- 346450: 4381: if (SAME_OBJ(scheme_struct_type_p_proc, rator)) {
- -: 4382: Scheme_Object *c;
- 148: 4383: c = get_struct_proc_shape(rand, info, 0);
- 148: 4384: if (c && ((SCHEME_PROC_SHAPE_MODE(c) & STRUCT_PROC_SHAPE_MASK)
- -: 4385: == STRUCT_PROC_SHAPE_STRUCT)) {
- 4: 4386: info->preserves_marks = 1;
- 4: 4387: info->single_result = 1;
- 4: 4388: return replace_tail_inside(scheme_true, inside, app->rand);
- -: 4389: }
- -: 4390: }
- -: 4391:
- 346446: 4392: if (SAME_OBJ(scheme_varref_const_p_proc, rator)
- 801: 4393: && SAME_TYPE(SCHEME_TYPE(rand), scheme_varref_form_type)) {
- 801: 4394: Scheme_Object *var = SCHEME_PTR1_VAL(rand);
- 801: 4395: if (SAME_OBJ(var, scheme_true)) {
- 6: 4396: info->preserves_marks = 1;
- 6: 4397: info->single_result = 1;
- 6: 4398: return replace_tail_inside(scheme_true, inside, app->rand);
- 795: 4399: } else if (SAME_OBJ(var, scheme_false)) {
- 4: 4400: info->preserves_marks = 1;
- 4: 4401: info->single_result = 1;
- 4: 4402: return replace_tail_inside(scheme_false, inside, app->rand);
- -: 4403: } else {
- 791: 4404: if (var && scheme_ir_propagate_ok(var, info)) {
- -: 4405: /* can propagate => is a constant */
- 726: 4406: info->preserves_marks = 1;
- 726: 4407: info->single_result = 1;
- 726: 4408: return replace_tail_inside(scheme_true, inside, app->rand);
- -: 4409: }
- -: 4410: }
- -: 4411: }
- -: 4412:
- -: 4413:
- 345710: 4414: if (SCHEME_PRIMP(rator) && IS_NAMED_PRIM(rator, "zero?")) {
- -: 4415: Scheme_Object* pred;
- -: 4416: Scheme_App3_Rec *new;
- -: 4417:
- 2804: 4418: pred = expr_implies_predicate(rand, info);
- 2804: 4419: if (pred && SAME_OBJ(pred, scheme_fixnum_p_proc)) {
- 110: 4420: new = (Scheme_App3_Rec *)make_application_3(scheme_unsafe_fx_eq_proc, app->rand, scheme_make_integer(0), info);
- 110: 4421: SCHEME_APPN_FLAGS(new) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- 110: 4422: return finish_optimize_application3(new, info, context);
- -: 4423: }
- -: 4424: }
- -: 4425:
- -: 4426: {
- -: 4427: /* Try to check the argument's type, and use the unsafe versions if possible. */
- 345600: 4428: Scheme_Object *app_o = (Scheme_Object *)app;
- -: 4429:
- 345600: 4430: check_known_variant(info, app_o, rator, rand, "bitwise-not", scheme_fixnum_p_proc, scheme_unsafe_fxnot_proc, scheme_real_p_proc);
- 345600: 4431: check_known_variant(info, app_o, rator, rand, "fxnot", scheme_fixnum_p_proc, scheme_unsafe_fxnot_proc, scheme_real_p_proc);
- -: 4432:
- 345600: 4433: check_known(info, app_o, rator, rand, "car", scheme_pair_p_proc, scheme_unsafe_car_proc);
- 345600: 4434: check_known(info, app_o, rator, rand, "unsafe-car", scheme_pair_p_proc, NULL);
- 345600: 4435: check_known(info, app_o, rator, rand, "cdr", scheme_pair_p_proc, scheme_unsafe_cdr_proc);
- 345600: 4436: check_known(info, app_o, rator, rand, "unsafe-cdr", scheme_pair_p_proc, NULL);
- 345600: 4437: check_known(info, app_o, rator, rand, "mcar", scheme_mpair_p_proc, scheme_unsafe_mcar_proc);
- 345600: 4438: check_known(info, app_o, rator, rand, "unsafe-mcar", scheme_mpair_p_proc, NULL);
- 345600: 4439: check_known(info, app_o, rator, rand, "mcdr", scheme_mpair_p_proc, scheme_unsafe_mcdr_proc);
- 345600: 4440: check_known(info, app_o, rator, rand, "unsafe-mcdr", scheme_mpair_p_proc, NULL);
- 345600: 4441: check_known(info, app_o, rator, rand, "string-length", scheme_string_p_proc, scheme_unsafe_string_length_proc);
- 345600: 4442: check_known(info, app_o, rator, rand, "bytes-length", scheme_byte_string_p_proc, scheme_unsafe_byte_string_length_proc);
- -: 4443: /* It's not clear that these are useful, since a chaperone check is needed anyway: */
- 345600: 4444: check_known(info, app_o, rator, rand, "unbox", scheme_box_p_proc, scheme_unsafe_unbox_proc);
- 345600: 4445: check_known(info, app_o, rator, rand, "unsafe-unbox", scheme_box_p_proc, NULL);
- 345600: 4446: check_known(info, app_o, rator, rand, "unsafe-unbox*", scheme_box_p_proc, NULL);
- 345600: 4447: check_known(info, app_o, rator, rand, "vector-length", scheme_vector_p_proc, scheme_unsafe_vector_length_proc);
- -: 4448:
- 345600: 4449: check_known(info, app_o, rator, rand, "length", scheme_list_p_proc, scheme_true);
- -: 4450:
- 345600: 4451: check_known(info, app_o, rator, rand, "string-append", scheme_string_p_proc, scheme_true);
- 345600: 4452: check_known(info, app_o, rator, rand, "bytes-append", scheme_byte_string_p_proc, scheme_true);
- 345600: 4453: check_known(info, app_o, rator, rand, "string->immutable-string", scheme_string_p_proc, scheme_true);
- 345600: 4454: check_known(info, app_o, rator, rand, "bytes->immutable-bytes", scheme_byte_string_p_proc, scheme_true);
- -: 4455:
- 345600: 4456: check_known(info, app_o, rator, rand, "string->symbol", scheme_string_p_proc, scheme_true);
- 345600: 4457: check_known(info, app_o, rator, rand, "symbol->string", scheme_symbol_p_proc, scheme_true);
- 345600: 4458: check_known(info, app_o, rator, rand, "string->keyword", scheme_string_p_proc, scheme_true);
- 345600: 4459: check_known(info, app_o, rator, rand, "keyword->string", scheme_keyword_p_proc, scheme_true);
- -: 4460:
- 345600: 4461: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_WANTS_REAL)
- 512: 4462: check_known(info, app_o, rator, rand, NULL, scheme_real_p_proc,
- 512: 4463: (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_OMITTABLE_ON_GOOD_ARGS) ? scheme_true : NULL);
- 345600: 4464: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_WANTS_NUMBER)
- 11539: 4465: check_known(info, app_o, rator, rand, NULL, scheme_number_p_proc,
- 11539: 4466: (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_OMITTABLE_ON_GOOD_ARGS) ? scheme_true : NULL);
- -: 4467:
- -: 4468: /* These operation don't have an unsafe replacement. Check to record types and detect errors: */
- 345600: 4469: check_known(info, app_o, rator, rand, "caar", scheme_pair_p_proc, NULL);
- 345600: 4470: check_known(info, app_o, rator, rand, "cadr", scheme_pair_p_proc, NULL);
- 345600: 4471: check_known(info, app_o, rator, rand, "cdar", scheme_pair_p_proc, NULL);
- 345600: 4472: check_known(info, app_o, rator, rand, "cddr", scheme_pair_p_proc, NULL);
- -: 4473:
- 345600: 4474: check_known(info, app_o, rator, rand, "caddr", scheme_pair_p_proc, NULL);
- 345600: 4475: check_known(info, app_o, rator, rand, "cdddr", scheme_pair_p_proc, NULL);
- 345600: 4476: check_known(info, app_o, rator, rand, "cadddr", scheme_pair_p_proc, NULL);
- 345600: 4477: check_known(info, app_o, rator, rand, "cddddr", scheme_pair_p_proc, NULL);
- -: 4478:
- 345600: 4479: check_known(info, app_o, rator, rand, "list->vector", scheme_list_p_proc, scheme_true);
- 345600: 4480: check_known(info, app_o, rator, rand, "vector->list", scheme_vector_p_proc, NULL);
- 345600: 4481: check_known(info, app_o, rator, rand, "vector->values", scheme_vector_p_proc, NULL);
- 345600: 4482: check_known(info, app_o, rator, rand, "vector->immutable-vector", scheme_vector_p_proc, NULL);
- 345600: 4483: check_known(info, app_o, rator, rand, "make-vector", scheme_fixnum_p_proc, NULL);
- -: 4484:
- -: 4485: /* Some of these may have changed app->rator. */
- 345600: 4486: rator = app->rator;
- -: 4487: }
- -: 4488: }
- -: 4489:
- -: 4490: /* Using a struct getter or predicate? */
- 510845: 4491: alt = get_struct_proc_shape(rator, info, 0);
- 510845: 4492: if (alt) {
- 11051: 4493: int mode = (SCHEME_PROC_SHAPE_MODE(alt) & STRUCT_PROC_SHAPE_MASK);
- -: 4494:
- 11051: 4495: if ((mode == STRUCT_PROC_SHAPE_PRED)
- 8223: 4496: || (mode == STRUCT_PROC_SHAPE_GETTER)) {
- -: 4497: Scheme_Object *pred;
- 9887: 4498: pred = expr_implies_predicate(rand, info);
- -: 4499:
- 9887: 4500: if (pred
- 2578: 4501: && SAME_TYPE(SCHEME_TYPE(pred), scheme_struct_proc_shape_type)
- 2548: 4502: && is_struct_identity_subtype(SCHEME_PROC_SHAPE_IDENTITY(pred),
- -: 4503: SCHEME_PROC_SHAPE_IDENTITY(alt))) {
- 2296: 4504: if (mode == STRUCT_PROC_SHAPE_PRED) {
- -: 4505: /* We know that the predicate will succeed */
- 18: 4506: return replace_tail_inside(make_discarding_sequence(rand, scheme_true, info),
- -: 4507: inside,
- -: 4508: app->rand);
- -: 4509: } else {
- -: 4510: /* Struct type matches, so use `unsafe-struct-ref` */
- -: 4511: Scheme_App3_Rec *new;
- 2278: 4512: new = (Scheme_App3_Rec *)make_application_3(scheme_unsafe_struct_ref_proc,
- -: 4513: app->rand,
- 2278: 4514: scheme_make_integer(SCHEME_PROC_SHAPE_MODE(alt) >> STRUCT_PROC_SHAPE_SHIFT),
- -: 4515: info);
- 2278: 4516: SCHEME_APPN_FLAGS(new) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- 2278: 4517: return finish_optimize_application3(new, info, context);
- -: 4518: }
- -: 4519: }
- -: 4520:
- -: 4521: /* Register type based on getter succeeding: */
- 7591: 4522: if ((mode == STRUCT_PROC_SHAPE_GETTER)
- 4781: 4523: && SCHEME_PAIRP(SCHEME_PROC_SHAPE_IDENTITY(alt))
- 4781: 4524: && SAME_TYPE(SCHEME_TYPE(rand), scheme_ir_local_type))
- 3489: 4525: add_type(info, rand, scheme_make_struct_proc_shape(STRUCT_PROC_SHAPE_PRED,
- -: 4526: SCHEME_PROC_SHAPE_IDENTITY(alt)));
- -: 4527: }
- -: 4528: }
- -: 4529:
- 508549: 4530: register_local_argument_types(NULL, app, NULL, info);
- -: 4531:
- 508549: 4532: flags = appn_flags(rator, info);
- 508549: 4533: SCHEME_APPN_FLAGS(app) |= flags;
- -: 4534:
- 508549: 4535: return finish_optimize_any_application((Scheme_Object *)app, rator, 1, info, context);
- -: 4536:}
- -: 4537:
- 293662: 4538:static Scheme_Object *optimize_application3(Scheme_Object *o, Optimize_Info *info, int context)
- -: 4539:{
- -: 4540: Scheme_App3_Rec *app;
- -: 4541: Scheme_Object *le;
- -: 4542: int rator_apply_escapes, sub_context, ty, flags;
- -: 4543: Optimize_Info_Sequence info_seq;
- -: 4544:
- 293662: 4545: app = (Scheme_App3_Rec *)o;
- -: 4546:
- 293662: 4547: if (SAME_OBJ(app->rator, scheme_check_not_undefined_proc)
- 178: 4548: && SCHEME_SYMBOLP(app->rand2)) {
- 178: 4549: scheme_log(info->logger,
- -: 4550: SCHEME_LOG_DEBUG,
- -: 4551: 0,
- -: 4552: "warning%s: use-before-definition check inserted on variable: %S",
- -: 4553: scheme_optimize_context_to_string(info->context),
- -: 4554: app->rand2);
- -: 4555: }
- -: 4556:
- -: 4557: /* Check for (apply ... (list ...)) early: */
- 293662: 4558: le = direct_apply((Scheme_Object *)app, app->rator, app->rand2, info);
- 293662: 4559: if (le)
- 20: 4560: return scheme_optimize_expr(le, info, context);
- -: 4561:
- 293642: 4562: le = call_with_immed_mark(app->rator, app->rand1, app->rand2, NULL, info);
- 293642: 4563: if (le)
- 131: 4564: return scheme_optimize_expr(le, info, context);
- -: 4565:
- 293511: 4566: le = check_app_let_rator(o, app->rator, info, 2, context);
- 293511: 4567: if (le)
- 1090: 4568: return le;
- -: 4569:
- 292421: 4570: le = optimize_for_inline(info, app->rator, 2, NULL, NULL, app, context, 0);
- 292421: 4571: if (le)
- 26273: 4572: return le;
- -: 4573:
- 266148: 4574: optimize_info_seq_init(info, &info_seq);
- -: 4575:
- 266148: 4576: sub_context = OPT_CONTEXT_SINGLED;
- -: 4577:
- 266148: 4578: le = scheme_optimize_expr(app->rator, info, sub_context);
- 266148: 4579: app->rator = le;
- 266148: 4580: if (info->escapes) {
- 2: 4581: optimize_info_seq_done(info, &info_seq);
- 2: 4582: return ensure_noncm(app->rator);
- -: 4583: }
- -: 4584:
- -: 4585: {
- -: 4586: /* Maybe found "((lambda" after optimizing; try again */
- 266146: 4587: le = optimize_for_inline(info, app->rator, 2, NULL, NULL, app, context, 1);
- 266146: 4588: if (le)
- 21: 4589: return le;
- 266125: 4590: rator_apply_escapes = info->escapes;
- -: 4591: }
- -: 4592:
- 266125: 4593: if (SAME_OBJ(app->rator, scheme_values_proc)
- 260922: 4594: || SAME_OBJ(app->rator, scheme_apply_proc))
- 7354: 4595: info->maybe_values_argument = 1;
- -: 4596:
- -: 4597: /* 1st arg */
- -: 4598:
- 266125: 4599: ty = wants_local_type_arguments(app->rator, 0);
- 266125: 4600: if (ty)
- 516: 4601: sub_context |= (ty << OPT_CONTEXT_TYPE_SHIFT);
- -: 4602:
- 266125: 4603: optimize_info_seq_step(info, &info_seq);
- -: 4604:
- 266125: 4605: le = scheme_optimize_expr(app->rand1, info, sub_context);
- 266125: 4606: app->rand1 = le;
- 266125: 4607: if (info->escapes) {
- 25: 4608: info->size += 1;
- 25: 4609: return ensure_noncm(make_discarding_first_sequence(app->rator, app->rand1, info));
- -: 4610: }
- -: 4611:
- -: 4612: /* 2nd arg */
- -: 4613:
- 266100: 4614: ty = wants_local_type_arguments(app->rator, 1);
- 266100: 4615: if (ty)
- 516: 4616: sub_context |= (ty << OPT_CONTEXT_TYPE_SHIFT);
- -: 4617: else
- 265584: 4618: sub_context &= ~OPT_CONTEXT_TYPE_MASK;
- -: 4619:
- 266100: 4620: optimize_info_seq_step(info, &info_seq);
- -: 4621:
- 266100: 4622: le = scheme_optimize_expr(app->rand2, info, sub_context);
- 266100: 4623: app->rand2 = le;
- 266100: 4624: optimize_info_seq_done(info, &info_seq);
- 266100: 4625: if (info->escapes) {
- 28: 4626: info->size += 1;
- 28: 4627: le = make_discarding_first_sequence(app->rator,
- -: 4628: make_discarding_first_sequence(app->rand1, app->rand2,
- -: 4629: info),
- -: 4630: info);
- 28: 4631: return ensure_noncm(le);
- -: 4632: }
- -: 4633:
- -: 4634: /* Check for (apply ... (list ...)) after some optimizations: */
- 266072: 4635: le = direct_apply((Scheme_Object *)app, app->rator, app->rand2, info);
- 266072: 4636: if (le) return finish_optimize_app(le, info, context);
- -: 4637:
- 266022: 4638: flags = appn_flags(app->rator, info);
- 266022: 4639: SCHEME_APPN_FLAGS(app) |= flags;
- -: 4640:
- 266022: 4641: if (rator_apply_escapes) {
- 102: 4642: info->escapes = 1;
- 102: 4643: SCHEME_APPN_FLAGS(app) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- -: 4644: }
- -: 4645:
- 266022: 4646: return finish_optimize_application3(app, info, context);
- -: 4647:}
- -: 4648:
- 268443: 4649:static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimize_Info *info, int context)
- -: 4650:{
- -: 4651: int flags, rator_flags;
- -: 4652: Scheme_Object *le, *rator_for_flags;
- 268443: 4653: int all_vals = 1;
- -: 4654:
- 268443: 4655: info->size += 1;
- -: 4656:
- 268443: 4657: if (SCHEME_TYPE(app->rand1) < _scheme_ir_values_types_)
- 214388: 4658: all_vals = 0;
- 268443: 4659: if (SCHEME_TYPE(app->rand2) < _scheme_ir_values_types_)
- 200600: 4660: all_vals = 0;
- -: 4661:
- -: 4662:
- 268443: 4663: if (all_vals) {
- 8043: 4664: le = try_optimize_fold(app->rator, NULL, (Scheme_Object *)app, info);
- 8043: 4665: if (le)
- 1785: 4666: return le;
- -: 4667: }
- -: 4668:
- 266658: 4669: increment_clocks_for_application(info, app->rator, 2);
- -: 4670:
- -: 4671: /* Check for (call-with-values (lambda () M) N): */
- 266658: 4672: if (SAME_OBJ(app->rator, scheme_call_with_values_proc)) {
- 615: 4673: if (SAME_TYPE(SCHEME_TYPE(app->rand1), scheme_ir_lambda_type)) {
- 547: 4674: Scheme_Lambda *lam = (Scheme_Lambda *)app->rand1;
- -: 4675:
- 547: 4676: if (!lam->num_params) {
- -: 4677: /* Convert to apply-values form: */
- 865: 4678: return optimize_apply_values(app->rand2, lam->body, info,
- 547: 4679: ((SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_SINGLE_RESULT)
- 318: 4680: ? ((SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_RESULT_TENTATIVE)
- -: 4681: ? -1
- 318: 4682: : 1)
- -: 4683: : 0),
- -: 4684: context);
- -: 4685: }
- -: 4686: }
- -: 4687: }
- -: 4688:
- 266111: 4689: if (SAME_OBJ(scheme_procedure_arity_includes_proc, app->rator)) {
- 2754: 4690: if (SCHEME_INTP(app->rand2) && SCHEME_INT_VAL(app->rand2) >= 0) {
- -: 4691: Scheme_Object *proc;
- -: 4692:
- 2502: 4693: proc = lookup_constant_proc(info, app->rand1, SCHEME_INT_VAL(app->rand2));
- 2502: 4694: if (proc) {
- 826: 4695: info->preserves_marks = 1;
- 826: 4696: info->single_result = 1;
- 826: 4697: return make_discarding_sequence(app->rand1,
- -: 4698: SAME_OBJ(proc, scheme_true) ? scheme_false : scheme_true,
- -: 4699: info);
- -: 4700: }
- -: 4701: }
- -: 4702: }
- -: 4703:
- 265285: 4704: if (SAME_OBJ(app->rator, scheme_equal_proc)
- 261701: 4705: || SAME_OBJ(app->rator, scheme_eqv_proc)
- 261325: 4706: || SAME_OBJ(app->rator, scheme_eq_proc)) {
- 19271: 4707: if (equivalent_exprs(app->rand1, app->rand2, NULL, NULL, 0)) {
- 207: 4708: info->preserves_marks = 1;
- 207: 4709: info->single_result = 1;
- 207: 4710: return make_discarding_sequence_3(app->rand1, app->rand2, scheme_true, info);
- -: 4711: }
- -: 4712: {
- 19064: 4713: Scheme_Object *pred1, *pred2, *pred_new = NULL;
- 19064: 4714: int rel1=0, rel2=0, rel_max, eq_type=0;
- -: 4715:
- 19064: 4716: pred1 = expr_implies_predicate(app->rand1, info);
- 19064: 4717: pred2 = expr_implies_predicate(app->rand2, info);
- 19064: 4718: rel1 = relevant_predicate(pred1);
- 19064: 4719: rel2 = relevant_predicate(pred2);
- 19064: 4720: if ((pred1 && pred2)
- 1176: 4721: && (predicate_implies_not(pred1, pred2)
- 1132: 4722: || predicate_implies_not(pred2, pred1))) {
- 44: 4723: info->preserves_marks = 1;
- 44: 4724: info->single_result = 1;
- 44: 4725: return make_discarding_sequence_3(app->rand1, app->rand2, scheme_false, info);
- -: 4726: }
- -: 4727:
- -: 4728: /* Try to transform it into a predicate */
- 19020: 4729: if (rel1 >= RLV_SINGLETON) {
- -: 4730: Scheme_Object *new_app;
- 36: 4731: new_app = make_optimize_prim_application2(pred1, app->rand2, info, context);
- 36: 4732: return make_discarding_sequence(app->rand1, new_app, info);
- -: 4733: }
- 18984: 4734: if (rel2 >= RLV_SINGLETON) {
- -: 4735: Scheme_Object *new_app;
- 449: 4736: new_app = make_optimize_prim_application2(pred2, app->rand1, info, context);
- 449: 4737: return make_discarding_reverse_sequence(app->rand2, new_app, info);
- -: 4738: }
- -: 4739:
- -: 4740: /* Optimize `equal?' or `eqv?' test on certain types
- -: 4741: to `eqv?` or `eq?'. This is especially helpful for the JIT. */
- 18535: 4742: if (SAME_OBJ(app->rator, scheme_eqv_proc))
- 354: 4743: eq_type = RLV_EQV_TESTEABLE;
- 18535: 4744: if (SAME_OBJ(app->rator, scheme_eq_proc))
- 14999: 4745: eq_type = RLV_EQ_TESTEABLE;
- -: 4746:
- 18535: 4747: rel_max = (rel1 >= rel2) ? rel1 : rel2;
- 18535: 4748: if (rel_max >= RLV_EQ_TESTEABLE && eq_type < RLV_EQ_TESTEABLE)
- 923: 4749: pred_new = scheme_eq_proc;
- 17612: 4750: else if (rel_max >= RLV_EQV_TESTEABLE && eq_type < RLV_EQV_TESTEABLE)
- 71: 4751: pred_new = scheme_eqv_proc;
- -: 4752:
- 18535: 4753: if (pred_new) {
- 994: 4754: app->rator = pred_new;
- 994: 4755: SCHEME_APPN_FLAGS(app) |= (APPN_FLAG_IMMED | APPN_FLAG_SFS_TAIL);
- -: 4756:
- -: 4757: /* eq? and eqv? are foldable */
- 994: 4758: if (all_vals) {
- 4: 4759: le = try_optimize_fold(app->rator, NULL, (Scheme_Object *)app, info);
- 4: 4760: if (le)
- 4: 4761: return le;
- -: 4762: }
- -: 4763: }
- -: 4764: }
- -: 4765: }
- -: 4766:
- 264545: 4767: rator_for_flags = lookup_constant_proc(info, app->rator, 2);
- 264545: 4768: rator_flags = scheme_get_rator_flags(rator_for_flags);
- 264545: 4769: info->preserves_marks = !!(rator_flags & LAMBDA_PRESERVES_MARKS);
- 264545: 4770: info->single_result = !!(rator_flags & LAMBDA_SINGLE_RESULT);
- 264545: 4771: if (rator_flags & LAMBDA_RESULT_TENTATIVE) {
- 6421: 4772: info->preserves_marks = -info->preserves_marks;
- 6421: 4773: info->single_result = -info->single_result;
- -: 4774: }
- -: 4775:
- -: 4776: /* Ad hoc optimization of (unsafe-+ <x> 0), etc. */
- 264545: 4777: if (SCHEME_PRIMP(app->rator)
- 226353: 4778: && (SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_IS_UNSAFE_NONMUTATING)) {
- -: 4779: int z1, z2;
- -: 4780:
- 32798: 4781: z1 = SAME_OBJ(app->rand1, scheme_make_integer(0));
- 32798: 4782: z2 = SAME_OBJ(app->rand2, scheme_make_integer(0));
- 32798: 4783: if (IS_NAMED_PRIM(app->rator, "unsafe-fx+")) {
- 6421: 4784: if (z1)
- 52: 4785: return ensure_single_value_noncm(app->rand2);
- 6369: 4786: else if (z2)
- 122: 4787: return ensure_single_value_noncm(app->rand1);
- 26377: 4788: } else if (IS_NAMED_PRIM(app->rator, "unsafe-fx-")) {
- 326: 4789: if (z2)
- 2: 4790: return ensure_single_value_noncm(app->rand1);
- 26051: 4791: } else if (IS_NAMED_PRIM(app->rator, "unsafe-fx*")) {
- 4: 4792: if (z1 || z2) {
- #####: 4793: if (z1 && z2)
- #####: 4794: return scheme_make_integer(0);
- #####: 4795: else if (z2)
- #####: 4796: return make_discarding_sequence(app->rand1, scheme_make_integer(0), info);
- -: 4797: else
- #####: 4798: return make_discarding_sequence(app->rand2, scheme_make_integer(0), info);
- -: 4799: }
- 4: 4800: if (SAME_OBJ(app->rand1, scheme_make_integer(1)))
- 2: 4801: return ensure_single_value_noncm(app->rand2);
- 2: 4802: if (SAME_OBJ(app->rand2, scheme_make_integer(1)))
- 2: 4803: return ensure_single_value_noncm(app->rand1);
- 26047: 4804: } else if (IS_NAMED_PRIM(app->rator, "unsafe-fxquotient")) {
- 2: 4805: if (z1)
- #####: 4806: return make_discarding_sequence(app->rand2, scheme_make_integer(0), info);
- 2: 4807: if (SAME_OBJ(app->rand2, scheme_make_integer(1)))
- 2: 4808: return ensure_single_value_noncm(app->rand1);
- 26045: 4809: } else if (IS_NAMED_PRIM(app->rator, "unsafe-fxremainder")
- 26045: 4810: || IS_NAMED_PRIM(app->rator, "unsafe-fxmodulo")) {
- #####: 4811: if (z1)
- #####: 4812: return make_discarding_sequence(app->rand2, scheme_make_integer(0), info);
- #####: 4813: if (SAME_OBJ(app->rand2, scheme_make_integer(1)))
- #####: 4814: return make_discarding_sequence(app->rand1, scheme_make_integer(0), info);
- -: 4815: }
- -: 4816:
- 32616: 4817: z1 = (SCHEME_FLOATP(app->rand1) && (SCHEME_FLOAT_VAL(app->rand1) == 0.0));
- 32616: 4818: z2 = (SCHEME_FLOATP(app->rand2) && (SCHEME_FLOAT_VAL(app->rand2) == 0.0));
- -: 4819:
- 32616: 4820: if (IS_NAMED_PRIM(app->rator, "unsafe-fl+")) {
- 20: 4821: if (z1)
- 2: 4822: return ensure_single_value_noncm(app->rand2);
- 18: 4823: else if (z2)
- 2: 4824: return ensure_single_value_noncm(app->rand1);
- 32596: 4825: } else if (IS_NAMED_PRIM(app->rator, "unsafe-fl-")) {
- 4: 4826: if (z2)
- 2: 4827: return ensure_single_value_noncm(app->rand1);
- 32592: 4828: } else if (IS_NAMED_PRIM(app->rator, "unsafe-fl*")) {
- 22: 4829: if (SCHEME_FLOATP(app->rand1) && (SCHEME_FLOAT_VAL(app->rand1) == 1.0))
- 2: 4830: return ensure_single_value_noncm(app->rand2);
- 20: 4831: if (SCHEME_FLOATP(app->rand2) && (SCHEME_FLOAT_VAL(app->rand2) == 1.0))
- 2: 4832: return ensure_single_value_noncm(app->rand1);
- 32570: 4833: } else if (IS_NAMED_PRIM(app->rator, "unsafe-fl/")) {
- 2: 4834: if (SCHEME_FLOATP(app->rand2) && (SCHEME_FLOAT_VAL(app->rand2) == 1.0))
- 2: 4835: return ensure_single_value_noncm(app->rand1);
- -: 4836: }
- -: 4837:
- -: 4838: /* Possible improvement: detect 0 and 1 constants even when general
- -: 4839: extflonum operations are not supported. */
- -: 4840:#ifdef MZ_LONG_DOUBLE
- 32604: 4841: z1 = (SCHEME_LONG_DBLP(app->rand1) && long_double_is_zero(SCHEME_LONG_DBL_VAL(app->rand1)));
- 32604: 4842: z2 = (SCHEME_LONG_DBLP(app->rand2) && long_double_is_zero(SCHEME_LONG_DBL_VAL(app->rand2)));
- -: 4843:
- 32604: 4844: if (IS_NAMED_PRIM(app->rator, "unsafe-extfl+")) {
- 16: 4845: if (z1)
- #####: 4846: return ensure_single_value_noncm(app->rand2);
- 16: 4847: else if (z2)
- #####: 4848: return ensure_single_value_noncm(app->rand1);
- 32588: 4849: } else if (IS_NAMED_PRIM(app->rator, "unsafe-extfl-")) {
- #####: 4850: if (z2)
- #####: 4851: return ensure_single_value_noncm(app->rand1);
- 32588: 4852: } else if (IS_NAMED_PRIM(app->rator, "unsafe-extfl*")) {
- 18: 4853: if (SCHEME_LONG_DBLP(app->rand1) && long_double_is_1(SCHEME_LONG_DBL_VAL(app->rand1)))
- #####: 4854: return ensure_single_value_noncm(app->rand2);
- 18: 4855: if (SCHEME_LONG_DBLP(app->rand2) && long_double_is_1(SCHEME_LONG_DBL_VAL(app->rand2)))
- #####: 4856: return ensure_single_value_noncm(app->rand1);
- 32570: 4857: } else if (IS_NAMED_PRIM(app->rator, "unsafe-extfl/")) {
- #####: 4858: if (SCHEME_LONG_DBLP(app->rand2) && long_double_is_1(SCHEME_LONG_DBL_VAL(app->rand2)))
- #####: 4859: return ensure_single_value_noncm(app->rand1);
- -: 4860: }
- -: 4861:#endif
- 231747: 4862: } else if (SCHEME_PRIMP(app->rator)
- 160951: 4863: && (SCHEME_PRIM_PROC_OPT_FLAGS(app->rator) & SCHEME_PRIM_IS_BINARY_INLINED)) {
- 108123: 4864: if (IS_NAMED_PRIM(app->rator, "arithmetic-shift")) {
- 287: 4865: if (SCHEME_INTP(app->rand2) && (SCHEME_INT_VAL(app->rand2) <= 0)
- 76: 4866: && (is_local_type_expression(app->rand1, info) == SCHEME_LOCAL_TYPE_FIXNUM)) {
- 1: 4867: app->rator = scheme_unsafe_fxrshift_proc;
- 1: 4868: app->rand2 = scheme_make_integer(-(SCHEME_INT_VAL(app->rand2)));
- -: 4869: }
- 107836: 4870: } else if (IS_NAMED_PRIM(app->rator, "string=?")) {
- 377: 4871: if (SAME_TYPE(SCHEME_TYPE(app->rand1), scheme_char_string_type)
- 282: 4872: && SAME_TYPE(SCHEME_TYPE(app->rand2), scheme_char_string_type)) {
- 6: 4873: return scheme_string_eq_2(app->rand1, app->rand2);
- -: 4874: }
- 107459: 4875: } else if (IS_NAMED_PRIM(app->rator, "bytes=?")) {
- 60: 4876: if (SAME_TYPE(SCHEME_TYPE(app->rand1), scheme_byte_string_type)
- 8: 4877: && SAME_TYPE(SCHEME_TYPE(app->rand2), scheme_byte_string_type)) {
- 6: 4878: return scheme_byte_string_eq_2(app->rand1, app->rand2);
- -: 4879: }
- 107399: 4880: } else if (IS_NAMED_PRIM(app->rator, "char=?")) {
- 113: 4881: if (SAME_TYPE(SCHEME_TYPE(app->rand1), scheme_char_type)
- 72: 4882: && SAME_TYPE(SCHEME_TYPE(app->rand2), scheme_char_type)) {
- #####: 4883: return (SCHEME_CHAR_VAL(app->rand1) == SCHEME_CHAR_VAL(app->rand2)) ? scheme_true : scheme_false;
- -: 4884: }
- -: 4885: }
- -: 4886: }
- -: 4887:
- 264339: 4888: if (SCHEME_PRIMP(app->rator)) {
- 193543: 4889: Scheme_Object *app_o = (Scheme_Object *)app, *rator = app->rator, *rand1 = app->rand1, *rand2 = app->rand2;
- -: 4890:
- 193543: 4891: check_known_both_variant(info, app_o, rator, rand1, rand2, "bitwise-and", scheme_fixnum_p_proc, scheme_unsafe_fxand_proc, scheme_real_p_proc);
- 193543: 4892: check_known_both_variant(info, app_o, rator, rand1, rand2, "bitwise-ior", scheme_fixnum_p_proc, scheme_unsafe_fxior_proc, scheme_real_p_proc);
- 193543: 4893: check_known_both_variant(info, app_o, rator, rand1, rand2, "bitwise-xor", scheme_fixnum_p_proc, scheme_unsafe_fxxor_proc, scheme_real_p_proc);
- -: 4894:
- 193543: 4895: check_known_both_variant(info, app_o, rator, rand1, rand2, "fxand", scheme_fixnum_p_proc, scheme_unsafe_fxand_proc, scheme_real_p_proc);
- 193543: 4896: check_known_both_variant(info, app_o, rator, rand1, rand2, "fxior", scheme_fixnum_p_proc, scheme_unsafe_fxior_proc, scheme_real_p_proc);
- 193543: 4897: check_known_both_variant(info, app_o, rator, rand1, rand2, "fxxor", scheme_fixnum_p_proc, scheme_unsafe_fxxor_proc, scheme_real_p_proc);
- -: 4898:
- 193543: 4899: check_known_both_try(info, app_o, rator, rand1, rand2, "=", scheme_fixnum_p_proc, scheme_unsafe_fx_eq_proc);
- 193543: 4900: check_known_both_try(info, app_o, rator, rand1, rand2, "<", scheme_fixnum_p_proc, scheme_unsafe_fx_lt_proc);
- 193543: 4901: check_known_both_try(info, app_o, rator, rand1, rand2, ">", scheme_fixnum_p_proc, scheme_unsafe_fx_gt_proc);
- 193543: 4902: check_known_both_try(info, app_o, rator, rand1, rand2, "<=", scheme_fixnum_p_proc, scheme_unsafe_fx_lt_eq_proc);
- 193543: 4903: check_known_both_try(info, app_o, rator, rand1, rand2, ">=", scheme_fixnum_p_proc, scheme_unsafe_fx_gt_eq_proc);
- 193543: 4904: check_known_both_try(info, app_o, rator, rand1, rand2, "min", scheme_fixnum_p_proc, scheme_unsafe_fx_min_proc);
- 193543: 4905: check_known_both_try(info, app_o, rator, rand1, rand2, "max", scheme_fixnum_p_proc, scheme_unsafe_fx_max_proc);
- -: 4906:
- 193543: 4907: check_known_both_try(info, app_o, rator, rand1, rand2, "fx=", scheme_fixnum_p_proc, scheme_unsafe_fx_eq_proc);
- 193543: 4908: check_known_both_try(info, app_o, rator, rand1, rand2, "fx<", scheme_fixnum_p_proc, scheme_unsafe_fx_lt_proc);
- 193543: 4909: check_known_both_try(info, app_o, rator, rand1, rand2, "fx>", scheme_fixnum_p_proc, scheme_unsafe_fx_gt_proc);
- 193543: 4910: check_known_both_try(info, app_o, rator, rand1, rand2, "fx<=", scheme_fixnum_p_proc, scheme_unsafe_fx_lt_eq_proc);
- 193543: 4911: check_known_both_try(info, app_o, rator, rand1, rand2, "fx>=", scheme_fixnum_p_proc, scheme_unsafe_fx_gt_eq_proc);
- 193543: 4912: check_known_both_try(info, app_o, rator, rand1, rand2, "fxmin", scheme_fixnum_p_proc, scheme_unsafe_fx_min_proc);
- 193543: 4913: check_known_both_try(info, app_o, rator, rand1, rand2, "fxmax", scheme_fixnum_p_proc, scheme_unsafe_fx_max_proc);
- -: 4914:
- 193543: 4915: rator = app->rator; /* in case it was updated */
- -: 4916:
- 193543: 4917: check_known_both(info, app_o, rator, rand1, rand2, "string-append", scheme_string_p_proc, scheme_true);
- 193543: 4918: check_known_both(info, app_o, rator, rand1, rand2, "bytes-append", scheme_byte_string_p_proc, scheme_true);
- 193543: 4919: check_known(info, app_o, rator, rand1, "string-ref", scheme_string_p_proc, NULL);
- 193543: 4920: check_known(info, app_o, rator, rand2, "string-ref", scheme_fixnum_p_proc, NULL);
- 193543: 4921: check_known(info, app_o, rator, rand1, "bytes-ref", scheme_byte_string_p_proc, NULL);
- 193543: 4922: check_known(info, app_o, rator, rand2, "bytes-ref", scheme_fixnum_p_proc, NULL);
- -: 4923:
- 193543: 4924: check_known(info, app_o, rator, rand1, "append", scheme_list_p_proc, scheme_true);
- 193543: 4925: check_known(info, app_o, rator, rand1, "list-ref", scheme_pair_p_proc, NULL);
- 193543: 4926: check_known(info, app_o, rator, rand2, "list-ref", scheme_fixnum_p_proc, NULL);
- -: 4927:
- 193543: 4928: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_WANTS_REAL)
- 7125: 4929: check_known_both(info, app_o, rator, rand1, rand2, NULL, scheme_real_p_proc,
- 7125: 4930: (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_OMITTABLE_ON_GOOD_ARGS) ? scheme_true : NULL);
- 193543: 4931: if (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_WANTS_NUMBER)
- 12654: 4932: check_known_both(info, app_o, rator, rand1, rand2, NULL, scheme_number_p_proc,
- 12654: 4933: (SCHEME_PRIM_PROC_OPT_FLAGS(rator) & SCHEME_PRIM_OMITTABLE_ON_GOOD_ARGS) ? scheme_true : NULL);
- -: 4934:
- 193543: 4935: check_known(info, app_o, rator, rand1, "vector-ref", scheme_vector_p_proc, NULL);
- 193543: 4936: check_known(info, app_o, rator, rand2, "vector-ref", scheme_fixnum_p_proc, NULL);
- 193543: 4937: check_known(info, app_o, rator, rand1, "make-vector", scheme_fixnum_p_proc, NULL);
- -: 4938:
- 193543: 4939: check_known(info, app_o, rator, rand1, "set-box!", scheme_box_p_proc, NULL);
- 193543: 4940: check_known(info, app_o, rator, rand1, "unsafe-set-box!", scheme_box_p_proc, NULL);
- 193543: 4941: check_known(info, app_o, rator, rand1, "unsafe-set-box*!", scheme_box_p_proc, NULL);
- -: 4942:
- 193543: 4943: check_known(info, app_o, rator, rand1, "procedure-closure-contents-eq?", scheme_procedure_p_proc, NULL);
- 193543: 4944: check_known(info, app_o, rator, rand2, "procedure-closure-contents-eq?", scheme_procedure_p_proc, NULL);
- 193543: 4945: check_known(info, app_o, rator, rand1, "procedure-arity-includes?", scheme_procedure_p_proc, NULL);
- -: 4946:
- 193543: 4947: check_known(info, app_o, rator, rand1, "map", scheme_procedure_p_proc, NULL);
- 193543: 4948: check_known(info, app_o, rator, rand1, "for-each", scheme_procedure_p_proc, NULL);
- 193543: 4949: check_known(info, app_o, rator, rand1, "andmap", scheme_procedure_p_proc, NULL);
- 193543: 4950: check_known(info, app_o, rator, rand1, "ormap", scheme_procedure_p_proc, NULL);
- 193543: 4951: check_known(info, app_o, rator, rand2, "map", scheme_list_p_proc, NULL);
- 193543: 4952: check_known(info, app_o, rator, rand2, "for-each", scheme_list_p_proc, NULL);
- 193543: 4953: check_known(info, app_o, rator, rand2, "andmap", scheme_list_p_proc, NULL);
- 193543: 4954: check_known(info, app_o, rator, rand2, "ormap", scheme_list_p_proc, NULL);
- -: 4955:
- 193543: 4956: rator = app->rator; /* in case it was updated */
- -: 4957: }
- -: 4958:
- 264339: 4959: register_local_argument_types(NULL, NULL, app, info);
- -: 4960:
- 264339: 4961: flags = appn_flags(app->rator, info);
- 264339: 4962: SCHEME_APPN_FLAGS(app) |= flags;
- -: 4963:
- 264339: 4964: return finish_optimize_any_application((Scheme_Object *)app, app->rator, 2,
- -: 4965: info, context);
- -: 4966:}
- -: 4967:
- -: 4968:/*========================================================================*/
- -: 4969:/* the apply-values bytecode form */
- -: 4970:/*========================================================================*/
- -: 4971:
- 1271: 4972:Scheme_Object *optimize_apply_values(Scheme_Object *f, Scheme_Object *e,
- -: 4973: Optimize_Info *info,
- -: 4974: int e_single_result,
- -: 4975: int context)
- -: 4976:/* f and e are already optimized */
- -: 4977:{
- -: 4978: Scheme_Object *o_f;
- -: 4979:
- 1271: 4980: info->preserves_marks = 0;
- 1271: 4981: info->single_result = 0;
- -: 4982:
- 1271: 4983: o_f = lookup_constant_proc(info, f, (e_single_result > 0) ? 1 : -1);
- 1271: 4984: if (o_f) {
- 375: 4985: if (SAME_TYPE(SCHEME_TYPE(o_f), scheme_ir_lambda_type)) {
- 126: 4986: Scheme_Lambda *lam = (Scheme_Lambda *)o_f;
- 126: 4987: int flags = SCHEME_LAMBDA_FLAGS(lam);
- 126: 4988: info->preserves_marks = !!(flags & LAMBDA_PRESERVES_MARKS);
- 126: 4989: info->single_result = !!(flags & LAMBDA_SINGLE_RESULT);
- 126: 4990: if (flags & LAMBDA_RESULT_TENTATIVE) {
- #####: 4991: info->preserves_marks = -info->preserves_marks;
- #####: 4992: info->single_result = -info->single_result;
- -: 4993: }
- -: 4994: }
- -: 4995: }
- -: 4996:
- 1271: 4997: if (o_f && (e_single_result > 0)) {
- -: 4998: /* Just make it an application (N M): */
- -: 4999: Scheme_App2_Rec *app2;
- -: 5000: Scheme_Object *e_cloned, *f_cloned;
- -: 5001:
- 10: 5002: app2 = MALLOC_ONE_TAGGED(Scheme_App2_Rec);
- 10: 5003: app2->iso.so.type = scheme_application2_type;
- -: 5004:
- -: 5005: /* Try to inline... */
- -: 5006:
- 10: 5007: e_cloned = optimize_clone(1, e, info, empty_eq_hash_tree, 0);
- 10: 5008: if (e_cloned) {
- 10: 5009: if (SAME_TYPE(SCHEME_TYPE(f), scheme_ir_lambda_type))
- #####: 5010: f_cloned = optimize_clone(1, f, info, empty_eq_hash_tree, 0);
- -: 5011: else {
- -: 5012: /* Otherwise, no clone is needed. */
- 10: 5013: f_cloned = f;
- -: 5014: }
- -: 5015:
- 10: 5016: if (f_cloned) {
- 10: 5017: app2->rator = f_cloned;
- 10: 5018: app2->rand = e_cloned;
- 10: 5019: info->inline_fuel >>= 1; /* because we've already optimized the rand */
- 10: 5020: return optimize_application2((Scheme_Object *)app2, info, context);
- -: 5021: }
- -: 5022: }
- -: 5023:
- #####: 5024: app2->rator = f;
- #####: 5025: app2->rand = e;
- #####: 5026: return (Scheme_Object *)app2;
- -: 5027: }
- -: 5028:
- -: 5029: {
- -: 5030: Scheme_Object *av;
- 1261: 5031: av = scheme_alloc_object();
- 1261: 5032: av->type = scheme_apply_values_type;
- 1261: 5033: SCHEME_PTR1_VAL(av) = f;
- 1261: 5034: SCHEME_PTR2_VAL(av) = e;
- 1261: 5035: return av;
- -: 5036: }
- -: 5037:}
- -: 5038:
- -: 5039:/*========================================================================*/
- -: 5040:/* begin and begin0 */
- -: 5041:/*========================================================================*/
- -: 5042:
- -: 5043:static Scheme_Object *optimize_sequence(Scheme_Object *o, Optimize_Info *info, int context, int sub_opt);
- -: 5044:
- 31636: 5045:static Scheme_Object *flatten_sequence(Scheme_Object *o, Optimize_Info *info, int context)
- -: 5046:{
- 31636: 5047: Scheme_Sequence *s = (Scheme_Sequence *)o, *s2, *s3;
- -: 5048: Scheme_Object *o3;
- 31636: 5049: int i, j, k, count, extra = 0, split = 0, b0, new_count;
- -: 5050:
- 31636: 5051: if (SAME_TYPE(SCHEME_TYPE(o), scheme_splice_sequence_type))
- 38: 5052: return o;
- -: 5053:
- 31598: 5054: if (!info->flatten_fuel)
- 15: 5055: return o;
- -: 5056:
- 31583: 5057: b0 = SAME_TYPE(SCHEME_TYPE(o), scheme_begin0_sequence_type);
- 31583: 5058: count = s->count;
- -: 5059:
- -: 5060: /* exceptions: (begin ... (begin0 ...)) and (begin0 (begin ...) ...) */
- 112676: 5061: for (i = 0; i < count; i++) {
- 81093: 5062: o3 = s->array[i];
- 81093: 5063: if ((SAME_TYPE(SCHEME_TYPE(o3), scheme_sequence_type) && !(!i && b0))
- 80125: 5064: || (SAME_TYPE(SCHEME_TYPE(o3), scheme_begin0_sequence_type) && !(i == count - 1 && !b0))) {
- 978: 5065: s3 = (Scheme_Sequence *)o3;
- 978: 5066: extra += s3->count;
- 978: 5067: split++;
- -: 5068: }
- -: 5069: }
- -: 5070:
- 31583: 5071: if (!split)
- 30628: 5072: return o;
- -: 5073:
- 955: 5074: info->flatten_fuel--;
- 955: 5075: info->size -= split;
- -: 5076:
- 955: 5077: new_count = s->count + extra - split;
- 955: 5078: if (new_count > 0) {
- 955: 5079: s2 = scheme_malloc_sequence(new_count);
- 955: 5080: s2->so.type = s->so.type;
- 955: 5081: s2->count = new_count;
- -: 5082: } else
- #####: 5083: s2 = NULL;
- 955: 5084: k = 0;
- -: 5085:
- -: 5086: /* exceptions: (begin ... (begin0 ...)) and (begin0 (begin ...) ...) */
- 3323: 5087: for (i = 0; i < count; i++) {
- 2368: 5088: o3 = s->array[i];
- 3346: 5089: if ((SAME_TYPE(SCHEME_TYPE(o3), scheme_sequence_type) && !(!i && b0))
- 1400: 5090: || (SAME_TYPE(SCHEME_TYPE(o3), scheme_begin0_sequence_type) && !(i == count - 1 && !b0))) {
- 978: 5091: s3 = (Scheme_Sequence *)o3;
- 4838: 5092: for (j = 0; j < s3->count; j++) {
- 3860: 5093: s2->array[k++] = s3->array[j];
- -: 5094: }
- -: 5095: } else {
- 1390: 5096: s2->array[k++] = o3;
- -: 5097: }
- -: 5098: }
- -: 5099:
- -: 5100: MZ_ASSERT(k == new_count);
- -: 5101:
- 955: 5102: if (s2->count == 1)
- #####: 5103: return s2->array[0];
- -: 5104:
- 955: 5105: if (SAME_TYPE(SCHEME_TYPE(s2), scheme_sequence_type))
- 944: 5106: return optimize_sequence((Scheme_Object *)s2, info, context, 0);
- -: 5107: else
- 11: 5108: return (Scheme_Object *)s2;
- -: 5109:}
- -: 5110:
- 32158: 5111:static Scheme_Object *optimize_sequence(Scheme_Object *o, Optimize_Info *info, int context, int sub_opt)
- -: 5112:{
- 32158: 5113: Scheme_Sequence *s = (Scheme_Sequence *)o;
- -: 5114: Scheme_Object *le;
- -: 5115: int i, count, prev_size;
- 32158: 5116: int drop = 0, preserves_marks = 0, single_result = 0;
- -: 5117: Optimize_Info_Sequence info_seq;
- -: 5118:
- -: 5119: /* If !sub_opt, then just inspect already-optimized results. Note
- -: 5120: that `info` doesn't change in this mode, so we shouldn't try to
- -: 5121: check whether an expression escapes, for example. */
- -: 5122:
- 32158: 5123: if (sub_opt)
- 30988: 5124: optimize_info_seq_init(info, &info_seq);
- -: 5125: else
- 1170: 5126: memset(&info_seq, 0, sizeof(info_seq));
- -: 5127:
- 32158: 5128: count = s->count;
- 114773: 5129: for (i = 0; i < count; i++) {
- 82777: 5130: prev_size = info->size;
- -: 5131:
- 82777: 5132: if (sub_opt) {
- 77118: 5133: optimize_info_seq_step(info, &info_seq);
- 77118: 5134: le = scheme_optimize_expr(s->array[i], info,
- 77118: 5135: ((i + 1 == count)
- -: 5136: ? scheme_optimize_tail_context(context)
- -: 5137: : 0));
- -: 5138: } else
- 5659: 5139: le = s->array[i];
- -: 5140:
- 82777: 5141: if (i + 1 == count) {
- 31996: 5142: single_result = info->single_result;
- 31996: 5143: preserves_marks = info->preserves_marks;
- 31996: 5144: s->array[i] = le;
- -: 5145: } else {
- 50781: 5146: if (!sub_opt || !info->escapes) {
- -: 5147: /* Inlining and constant propagation can expose omittable expressions. */
- 50619: 5148: le = optimize_ignored(le, info, -1, 1, 5);
- 101238: 5149: if (!le) {
- 1095: 5150: drop++;
- 1095: 5151: info->size = prev_size;
- 1095: 5152: s->array[i] = NULL;
- -: 5153: } else {
- 49524: 5154: s->array[i] = le;
- -: 5155: }
- -: 5156: } else {
- -: 5157: int j;
- -: 5158:
- 162: 5159: single_result = info->single_result;
- 162: 5160: preserves_marks = info->preserves_marks;
- -: 5161: /* Move to last position in case the begin form is dropped */
- 162: 5162: s->array[count - 1] = le;
- 326: 5163: for (j = i; j < count - 1; j++) {
- 164: 5164: drop++;
- 164: 5165: s->array[j] = NULL;
- -: 5166: }
- 162: 5167: break;
- -: 5168: }
- -: 5169: }
- -: 5170: }
- -: 5171:
- 32158: 5172: if (sub_opt)
- 30988: 5173: optimize_info_seq_done(info, &info_seq);
- -: 5174:
- 32158: 5175: info->preserves_marks = preserves_marks;
- 32158: 5176: info->single_result = single_result;
- -: 5177:
- 32158: 5178: if (drop + 1 == s->count) {
- 840: 5179: le = s->array[drop];
- 840: 5180: if (info->escapes)
- 146: 5181: le = ensure_noncm(le);
- 840: 5182: return le;
- -: 5183: }
- -: 5184:
- 31318: 5185: if (drop) {
- -: 5186: Scheme_Sequence *s2;
- 327: 5187: int j = 0;
- -: 5188:
- 327: 5189: s2 = scheme_malloc_sequence(s->count - drop);
- 327: 5190: s2->so.type = s->so.type;
- 327: 5191: s2->count = s->count - drop;
- -: 5192:
- 1615: 5193: for (i = 0; i < s->count; i++) {
- 1288: 5194: if (s->array[i]) {
- 920: 5195: s2->array[j++] = s->array[i];
- -: 5196: }
- -: 5197: }
- -: 5198:
- 327: 5199: s = s2;
- -: 5200: }
- -: 5201:
- 31318: 5202: return flatten_sequence((Scheme_Object *)s, info, context);
- -: 5203:}
- -: 5204:
- -: 5205:/*========================================================================*/
- -: 5206:/* conditionals and types */
- -: 5207:/*========================================================================*/
- -: 5208:
- 1061321: 5209:static Scheme_Object *collapse_local(Scheme_Object *var, Optimize_Info *info, int context)
- -: 5210:/* Replace `var` in the given context with a constant, if possible based on its type */
- -: 5211:{
- 1061321: 5212: if (!SCHEME_VAR(var)->mutated) {
- -: 5213: Scheme_Object *pred;
- -: 5214:
- 1061300: 5215: pred = expr_implies_predicate(var, info);
- 1061300: 5216: if (pred) {
- 338742: 5217: if (predicate_implies(pred, scheme_not_proc))
- 723: 5218: return scheme_false;
- -: 5219:
- 338019: 5220: if (context & OPT_CONTEXT_BOOLEAN) {
- 6323: 5221: if (predicate_implies_not(pred, scheme_not_proc))
- 242: 5222: return scheme_true;
- -: 5223: }
- -: 5224:
- 337777: 5225: if (SAME_OBJ(pred, scheme_true_object_p_proc))
- 114: 5226: return scheme_true;
- 337663: 5227: if (SAME_OBJ(pred, scheme_null_p_proc))
- 774: 5228: return scheme_null;
- 336889: 5229: if (SAME_OBJ(pred, scheme_void_p_proc))
- 25: 5230: return scheme_void;
- 336864: 5231: if (SAME_OBJ(pred, scheme_eof_object_p_proc))
- 7: 5232: return scheme_eof;
- -: 5233: }
- -: 5234: }
- 1059436: 5235: return NULL;
- -: 5236:}
- -: 5237:
- -: 5238:/* This function is used to reduce:
- -: 5239: (if <x> a b) => (begin <x> <result-a-or-b>)
- -: 5240: (if a b #f) => a , and similar
- -: 5241: (eq? a b) => (begin a b #t)
- -: 5242: The function considers only values and variable references, so <a> and <b> don't have side effects.
- -: 5243: But each reduction has a very different behavior for expressions with side effects. */
- 596764: 5244:static Scheme_Object *equivalent_exprs(Scheme_Object *a, Scheme_Object *b,
- -: 5245: Optimize_Info *a_info, Optimize_Info *b_info, int context)
- -: 5246:{
- 596764: 5247: if (SAME_OBJ(a, b))
- 422: 5248: return a;
- -: 5249:
- 596342: 5250: if (SAME_TYPE(SCHEME_TYPE(a), scheme_ir_toplevel_type)
- 1121: 5251: && SAME_TYPE(SCHEME_TYPE(b), scheme_ir_toplevel_type)
- 294: 5252: && (SCHEME_TOPLEVEL_POS(a) == SCHEME_TOPLEVEL_POS(b)))
- 41: 5253: return a;
- -: 5254:
- 596301: 5255: if (b_info
- 227818: 5256: && SAME_TYPE(SCHEME_TYPE(a), scheme_ir_local_type)
- 20933: 5257: && (SCHEME_TYPE(b) > _scheme_ir_values_types_)) {
- -: 5258: Scheme_Object *n;
- 5830: 5259: n = collapse_local(a, b_info, context);
- 5830: 5260: if (n && SAME_OBJ(n, b))
- 24: 5261: return a;
- -: 5262: }
- -: 5263:
- 596277: 5264: if (a_info
- 227794: 5265: && SAME_TYPE(SCHEME_TYPE(b), scheme_ir_local_type)
- 16268: 5266: && (SCHEME_TYPE(a) > _scheme_ir_values_types_)) {
- -: 5267: Scheme_Object *n;
- 666: 5268: n = collapse_local(b, a_info, context);
- 666: 5269: if (n && SAME_OBJ(n, a))
- 6: 5270: return b;
- -: 5271: }
- -: 5272:
- 596271: 5273: return NULL;
- -: 5274:}
- -: 5275:
- 402164: 5276:static void add_type(Optimize_Info *info, Scheme_Object *var, Scheme_Object *pred)
- -: 5277:/* This is conceptually an intersection, but `Any` is represented by a
- -: 5278: missing entry, so the implementation looks like an union. */
- -: 5279:{
- 402164: 5280: Scheme_Hash_Tree *new_types = info->types;
- -: 5281: Scheme_Object *old_pred;
- -: 5282:
- 402164: 5283: if (SCHEME_VAR(var)->mutated)
- 1760: 5284: return;
- -: 5285:
- -: 5286: /* Don't add the type if something is already there, which may happen when no_types,
- -: 5287: as long as the existing predicate implies the new one. */
- 400404: 5288: if (SCHEME_VAR(var)->val_type) /* => more specific than other predicates */
- 5487: 5289: return;
- 394917: 5290: old_pred = optimize_get_predicate(info, var, 1);
- 394917: 5291: if (old_pred && predicate_implies(old_pred, pred))
- 30911: 5292: return;
- -: 5293:
- -: 5294: /* special case: list? and pair? => list-pair? */
- 364006: 5295: if (old_pred) {
- 23220: 5296: if ((SAME_OBJ(old_pred, scheme_list_p_proc)
- 9466: 5297: && (SAME_OBJ(pred, scheme_pair_p_proc)))
- 21528: 5298: || (SAME_OBJ(old_pred, scheme_pair_p_proc)
- 281: 5299: && (SAME_OBJ(pred, scheme_list_p_proc)))) {
- 1891: 5300: pred = scheme_list_pair_p_proc;
- -: 5301: }
- -: 5302: }
- -: 5303:
- 364006: 5304: if (!new_types)
- 301818: 5305: new_types = scheme_make_hash_tree(SCHEME_hashtr_eq);
- 364006: 5306: new_types = scheme_hash_tree_set(new_types, var, pred);
- 364006: 5307: info->types = new_types;
- -: 5308:}
- -: 5309:
- 119659: 5310:static void add_type_no(Optimize_Info *info, Scheme_Object *var, Scheme_Object *pred)
- -: 5311:/* Currently only check a few special cases for lists and booleans. */
- -: 5312:{
- -: 5313: Scheme_Object *old_pred;
- -: 5314:
- 119659: 5315: if (SCHEME_VAR(var)->mutated)
- 551: 5316: return;
- -: 5317:
- 119108: 5318: old_pred = optimize_get_predicate(info, var, 1);
- -: 5319:
- 119108: 5320: if (old_pred && SAME_OBJ(old_pred, scheme_list_p_proc)) {
- -: 5321: /* list? but not null? => list-pair? */
- 4556: 5322: if (SAME_OBJ(pred, scheme_null_p_proc))
- 2943: 5323: add_type(info, var, scheme_list_pair_p_proc);
- -: 5324:
- -: 5325: /* list? but not pair? => null? */
- -: 5326: /* list? but not list-pair? => null? */
- 4556: 5327: if (SAME_OBJ(pred, scheme_pair_p_proc)
- 2964: 5328: ||SAME_OBJ(pred, scheme_list_pair_p_proc))
- 1596: 5329: add_type(info, var, scheme_null_p_proc);
- -: 5330: }
- -: 5331:
- 119108: 5332: if (old_pred && SAME_OBJ(old_pred, scheme_boolean_p_proc)) {
- -: 5333: /* boolean? but not `not` => true-object? */
- 6429: 5334: if (SAME_OBJ(pred, scheme_not_proc))
- 6425: 5335: add_type(info, var, scheme_true_object_p_proc);
- -: 5336:
- -: 5337: /* boolean? but not true-object? => `not` */
- 6429: 5338: if (SAME_OBJ(pred, scheme_true_object_p_proc))
- 4: 5339: add_type(info, var, scheme_not_proc);
- -: 5340: }
- -: 5341:}
- -: 5342:
- 305260: 5343:static void merge_types(Optimize_Info *src_info, Optimize_Info *info, Scheme_Hash_Tree *skip_vars)
- -: 5344:{
- 305260: 5345: Scheme_Hash_Tree *types = src_info->types;
- -: 5346: Scheme_Object *var, *pred;
- -: 5347: intptr_t i;
- -: 5348:
- 305260: 5349: if (!types)
- 205311: 5350: return;
- -: 5351:
- 99949: 5352: i = scheme_hash_tree_next(types, -1);
- 330761: 5353: while (i != -1) {
- 130863: 5354: scheme_hash_tree_index(types, i, &var, &pred);
- 130863: 5355: if (!skip_vars || !scheme_hash_tree_get(skip_vars, var))
- 77342: 5356: add_type(info, var, pred);
- 130863: 5357: i = scheme_hash_tree_next(types, i);
- -: 5358: }
- -: 5359:}
- -: 5360:
- 212364: 5361:static void merge_branchs_types(Optimize_Info *t_info, Optimize_Info *f_info,
- -: 5362: Optimize_Info *base_info)
- -: 5363:/* This is conceptually an union, but `Any` is represented by a
- -: 5364: missing entry, so the implementation looks like an intersection.
- -: 5365: This adds to base_info the "intersection" of the types of t_info and f_info */
- -: 5366:{
- 212364: 5367: Scheme_Hash_Tree *t_types = t_info->types, *f_types = f_info->types;
- -: 5368: Scheme_Object *var, *t_pred, *f_pred;
- -: 5369: intptr_t i;
- -: 5370:
- 212364: 5371: if (!t_types || !f_types)
- 163392: 5372: return;
- -: 5373:
- 48972: 5374: if (f_types->count > t_types->count) {
- 4804: 5375: Scheme_Hash_Tree *swap = f_types;
- 4804: 5376: f_types = t_types;
- 4804: 5377: t_types = swap;
- -: 5378: }
- -: 5379:
- 48972: 5380: i = scheme_hash_tree_next(f_types, -1);
- 148900: 5381: while (i != -1) {
- 50956: 5382: scheme_hash_tree_index(f_types, i, &var, &f_pred);
- 50956: 5383: t_pred = scheme_hash_tree_get(t_types, var);
- 50956: 5384: if (t_pred) {
- 47405: 5385: if (predicate_implies(f_pred, t_pred))
- 6306: 5386: add_type(base_info, var, t_pred);
- 41099: 5387: else if (predicate_implies(t_pred, f_pred))
- 142: 5388: add_type(base_info, var, f_pred);
- -: 5389: else {
- -: 5390: /* special case: null? or list-pair? => list? */
- 40957: 5391: if ((SAME_OBJ(t_pred, scheme_null_p_proc)
- 18448: 5392: && (SAME_OBJ(f_pred, scheme_list_pair_p_proc)))
- 38241: 5393: || (SAME_OBJ(t_pred, scheme_list_pair_p_proc)
- 1611: 5394: && (SAME_OBJ(f_pred, scheme_null_p_proc)))) {
- 4327: 5395: add_type(base_info, var, scheme_list_p_proc);
- -: 5396: }
- -: 5397: /* special case: true-object? or `not` => boolean? */
- 40957: 5398: if ((SAME_OBJ(t_pred, scheme_not_proc)
- 345: 5399: && (SAME_OBJ(f_pred, scheme_true_object_p_proc)))
- 40738: 5400: || (SAME_OBJ(t_pred, scheme_true_object_p_proc)
- 6129: 5401: && (SAME_OBJ(f_pred, scheme_not_proc)))) {
- 6348: 5402: add_type(base_info, var, scheme_boolean_p_proc);
- -: 5403: }
- -: 5404: }
- -: 5405: }
- 50956: 5406: i = scheme_hash_tree_next(f_types, i);
- -: 5407: }
- -: 5408:}
- -: 5409:
- 548359: 5410:static int relevant_predicate(Scheme_Object *pred)
- -: 5411:{
- -: 5412: /* Relevant predicates need to be disjoint for try_reduce_predicate(),
- -: 5413: finish_optimize_application3() and add_types_for_t_branch().
- -: 5414: The predicate_implies() and predicate_implies_not() functions must
- -: 5415: be kept in sync with this list. */
- -: 5416:
- 548359: 5417: if (SAME_OBJ(pred, scheme_pair_p_proc)
- 485492: 5418: || SAME_OBJ(pred, scheme_list_p_proc)
- 467147: 5419: || SAME_OBJ(pred, scheme_list_pair_p_proc)
- 466955: 5420: || SAME_OBJ(pred, scheme_mpair_p_proc)
- 466362: 5421: || SAME_OBJ(pred, scheme_box_p_proc)
- 465315: 5422: || SAME_OBJ(pred, scheme_string_p_proc)
- 459476: 5423: || SAME_OBJ(pred, scheme_byte_string_p_proc)
- 455965: 5424: || SAME_OBJ(pred, scheme_vector_p_proc)
- 451026: 5425: || SAME_OBJ(pred, scheme_procedure_p_proc)
- 442617: 5426: || SAME_OBJ(pred, scheme_syntax_p_proc)
- 432324: 5427: || SAME_OBJ(pred, scheme_extflonum_p_proc))
- 116050: 5428: return RLV_IS_RELEVANT;
- 432309: 5429: if (SAME_OBJ(pred, scheme_char_p_proc)
- 431837: 5430: || SAME_OBJ(pred, scheme_flonum_p_proc)
- 431687: 5431: || SAME_OBJ(pred, scheme_number_p_proc)
- 428897: 5432: || SAME_OBJ(pred, scheme_real_p_proc))
- 5583: 5433: return RLV_EQV_TESTEABLE;
- 426726: 5434: if (SAME_OBJ(pred, scheme_symbol_p_proc)
- 416736: 5435: || SAME_OBJ(pred, scheme_keyword_p_proc)
- 412506: 5436: || SAME_OBJ(pred, scheme_fixnum_p_proc)
- 409229: 5437: || SAME_OBJ(pred, scheme_interned_char_p_proc)
- 409117: 5438: || SAME_OBJ(pred, scheme_boolean_p_proc))
- 18219: 5439: return RLV_EQ_TESTEABLE;
- 408507: 5440: if (SAME_OBJ(pred, scheme_null_p_proc)
- 321601: 5441: || SAME_OBJ(pred, scheme_void_p_proc)
- 321223: 5442: || SAME_OBJ(pred, scheme_eof_object_p_proc)
- 318525: 5443: || SAME_OBJ(pred, scheme_true_object_p_proc)
- 317748: 5444: || SAME_OBJ(pred, scheme_not_proc))
- 96483: 5445: return RLV_SINGLETON;
- -: 5446:
- 312024: 5447: return 0;
- -: 5448:}
- -: 5449:
- 2186894: 5450:static int predicate_implies(Scheme_Object *pred1, Scheme_Object *pred2)
- -: 5451:{
- 2186894: 5452: if (!pred1 || !pred2)
- 23860: 5453: return 0;
- -: 5454:
- -: 5455: /* P => P */
- 2163034: 5456: if (SAME_OBJ(pred1, pred2))
- 914886: 5457: return 1;
- -: 5458:
- -: 5459: /* null? => list? */
- 1248148: 5460: if (SAME_OBJ(pred2, scheme_list_p_proc)
- 6233: 5461: && SAME_OBJ(pred1, scheme_null_p_proc))
- 4044: 5462: return 1;
- -: 5463:
- -: 5464: /* list-pair? => list? */
- 1244104: 5465: if (SAME_OBJ(pred2, scheme_list_p_proc)
- 2189: 5466: && SAME_OBJ(pred1, scheme_list_pair_p_proc))
- 808: 5467: return 1;
- -: 5468:
- -: 5469: /* list-pair? => pair? */
- 1243296: 5470: if (SAME_OBJ(pred2, scheme_pair_p_proc)
- 46987: 5471: && SAME_OBJ(pred1, scheme_list_pair_p_proc))
- 11292: 5472: return 1;
- -: 5473:
- -: 5474: /* interned-char? => char? */
- 1232004: 5475: if (SAME_OBJ(pred2, scheme_char_p_proc)
- 31: 5476: && SAME_OBJ(pred1, scheme_interned_char_p_proc))
- 6: 5477: return 1;
- -: 5478:
- -: 5479: /* not, true-object? => boolean? */
- 1231998: 5480: if (SAME_OBJ(pred2, scheme_boolean_p_proc)
- 242657: 5481: && (SAME_OBJ(pred1, scheme_not_proc)
- 2325: 5482: || SAME_OBJ(pred1, scheme_true_object_p_proc)))
- 242643: 5483: return 1;
- -: 5484:
- -: 5485: /* real?, fixnum?, or flonum? => number? */
- 989355: 5486: if (SAME_OBJ(pred2, scheme_number_p_proc)
- 22346: 5487: && (SAME_OBJ(pred1, scheme_real_p_proc)
- 15218: 5488: || SAME_OBJ(pred1, scheme_fixnum_p_proc)
- 2521: 5489: || SAME_OBJ(pred1, scheme_flonum_p_proc)))
- 19913: 5490: return 1;
- -: 5491:
- -: 5492: /* fixnum? or flonum? => real? */
- 969442: 5493: if (SAME_OBJ(pred2, scheme_real_p_proc)
- 24185: 5494: && (SAME_OBJ(pred1, scheme_fixnum_p_proc)
- 14343: 5495: || SAME_OBJ(pred1, scheme_flonum_p_proc)))
- 9992: 5496: return 1;
- -: 5497:
- -: 5498: /* structure subtype? */
- 959450: 5499: if (SAME_TYPE(SCHEME_TYPE(pred1), scheme_struct_proc_shape_type)
- 9740: 5500: && SAME_TYPE(SCHEME_TYPE(pred2), scheme_struct_proc_shape_type)
- 701: 5501: && is_struct_identity_subtype(SCHEME_PROC_SHAPE_IDENTITY(pred1),
- -: 5502: SCHEME_PROC_SHAPE_IDENTITY(pred2)))
- 216: 5503: return 1;
- -: 5504:
- 959234: 5505: return 0;
- -: 5506:}
- -: 5507:
- 947001: 5508:static int predicate_implies_not(Scheme_Object *pred1, Scheme_Object *pred2)
- -: 5509:{
- 947001: 5510: if (SAME_OBJ(pred1, scheme_pair_p_proc) && SAME_OBJ(pred2, scheme_list_p_proc))
- 948: 5511: return 0;
- 946053: 5512: if (SAME_OBJ(pred1, scheme_list_p_proc) && SAME_OBJ(pred2, scheme_pair_p_proc))
- 3453: 5513: return 0;
- -: 5514:
- -: 5515: /* we don't track structure-type identity precisely enough to know
- -: 5516: that structures don't rule out other structures --- or even other
- -: 5517: prdicates (such as `procedure?`) */
- 942600: 5518: if (SAME_TYPE(SCHEME_TYPE(pred1), scheme_struct_proc_shape_type)
- 942528: 5519: || SAME_TYPE(SCHEME_TYPE(pred2), scheme_struct_proc_shape_type))
- 72: 5520: return 0;
- -: 5521:
- -: 5522: /* Otherwise, with our current set of predicates, overlapping matches happen
- -: 5523: only when one implies the other: */
- 942528: 5524: return (!predicate_implies(pred1, pred2) && !predicate_implies(pred2, pred1));
- -: 5525:}
- -: 5526:
- 262854: 5527:static void add_types_for_t_branch(Scheme_Object *t, Optimize_Info *info, int fuel)
- -: 5528:{
- 262854: 5529: if (fuel < 0)
- 48: 5530: return;
- -: 5531:
- 262806: 5532: if (SAME_TYPE(SCHEME_TYPE(t), scheme_ir_local_type)) {
- 54278: 5533: add_type_no(info, t, scheme_not_proc);
- 343289: 5534: } else if (SAME_TYPE(SCHEME_TYPE(t), scheme_application2_type)) {
- 134761: 5535: Scheme_App2_Rec *app = (Scheme_App2_Rec *)t;
- 134761: 5536: if (SCHEME_PRIMP(app->rator)
- 96508: 5537: && SAME_TYPE(SCHEME_TYPE(app->rand), scheme_ir_local_type)
- 82900: 5538: && relevant_predicate(app->rator)) {
- -: 5539: /* Looks like a predicate on a local variable. Record that the
- -: 5540: predicate succeeded, which may allow conversion of safe
- -: 5541: operations to unsafe operations. */
- 70798: 5542: add_type(info, app->rand, app->rator);
- -: 5543: }
- 134761: 5544: if (SAME_OBJ(app->rator, scheme_not_proc)) {
- 1450: 5545: add_types_for_f_branch(app->rand, info, fuel-1);
- -: 5546: }
- -: 5547:
- 134761: 5548: if (SAME_TYPE(SCHEME_TYPE(app->rand), scheme_ir_local_type)) {
- -: 5549: Scheme_Object *shape;
- 115455: 5550: shape = get_struct_proc_shape(app->rator, info, 0);
- 115455: 5551: if (shape
- 3406: 5552: && ((SCHEME_PROC_SHAPE_MODE(shape) & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_PRED)
- 2634: 5553: && SCHEME_PAIRP(SCHEME_PROC_SHAPE_IDENTITY(shape))) {
- 2634: 5554: add_type(info, app->rand, shape);
- -: 5555: }
- -: 5556: }
- 117405: 5557: } else if (SAME_TYPE(SCHEME_TYPE(t), scheme_application3_type)) {
- 43638: 5558: Scheme_App3_Rec *app = (Scheme_App3_Rec *)t;
- -: 5559: Scheme_Object *pred1, *pred2;
- 43638: 5560: if (SAME_OBJ(app->rator, scheme_eq_proc)
- 29582: 5561: || SAME_OBJ(app->rator, scheme_eqv_proc)
- 29308: 5562: || SAME_OBJ(app->rator, scheme_equal_proc)) {
- 16528: 5563: if (SAME_TYPE(SCHEME_TYPE(app->rand1), scheme_ir_local_type)) {
- 6563: 5564: pred1 = expr_implies_predicate(app->rand1, info);
- 6563: 5565: if (!pred1) {
- 5506: 5566: pred2 = expr_implies_predicate(app->rand2, info);
- 5506: 5567: if (pred2)
- 3177: 5568: add_type(info, app->rand1, pred2);
- -: 5569: }
- -: 5570: }
- 16528: 5571: if (SAME_TYPE(SCHEME_TYPE(app->rand2), scheme_ir_local_type)) {
- 2608: 5572: pred2 = expr_implies_predicate(app->rand2, info);
- 2608: 5573: if (!pred2) {
- 2411: 5574: pred1 = expr_implies_predicate(app->rand1, info);
- 2411: 5575: if (pred1)
- 278: 5576: add_type(info, app->rand2, pred1);
- -: 5577: }
- -: 5578: }
- -: 5579: }
- -: 5580:
- 30129: 5581: } else if (SAME_TYPE(SCHEME_TYPE(t), scheme_branch_type)) {
- 21880: 5582: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)t;
- 21880: 5583: if (SCHEME_FALSEP(b->fbranch)) {
- 14656: 5584: add_types_for_t_branch(b->test, info, fuel-1);
- 14656: 5585: add_types_for_t_branch(b->tbranch, info, fuel-1);
- -: 5586: }
- 21880: 5587: if (SCHEME_FALSEP(b->tbranch)) {
- 585: 5588: add_types_for_f_branch(b->test, info, fuel-1);
- 585: 5589: add_types_for_t_branch(b->fbranch, info, fuel-1);
- -: 5590: }
- -: 5591: }
- -: 5592:}
- -: 5593:
- 241585: 5594:static void add_types_for_f_branch(Scheme_Object *t, Optimize_Info *info, int fuel)
- -: 5595:{
- 241585: 5596: if (fuel < 0)
- 106: 5597: return;
- -: 5598:
- 241479: 5599: if (SAME_TYPE(SCHEME_TYPE(t), scheme_ir_local_type)) {
- 50400: 5600: add_type(info, t, scheme_not_proc);
- -: 5601:
- 317495: 5602: } else if (SAME_TYPE(SCHEME_TYPE(t), scheme_application2_type)) {
- 126416: 5603: Scheme_App2_Rec *app = (Scheme_App2_Rec *)t;
- 126416: 5604: if (SCHEME_PRIMP(app->rator)
- 89134: 5605: && SAME_TYPE(SCHEME_TYPE(app->rand), scheme_ir_local_type)
- 77706: 5606: && relevant_predicate(app->rator)) {
- -: 5607: /* Looks like a predicate on a local variable. Record that the
- -: 5608: predicate failed, this is currently useful only for lists. */
- 65381: 5609: add_type_no(info, app->rand, app->rator);
- -: 5610: }
- -: 5611:
- 64663: 5612: } else if (SAME_TYPE(SCHEME_TYPE(t), scheme_branch_type)) {
- 19327: 5613: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)t;
- 19327: 5614: if (SAME_OBJ(b->fbranch, scheme_true)) {
- 2851: 5615: add_types_for_t_branch(b->test, info, fuel-1);
- 2851: 5616: add_types_for_f_branch(b->tbranch, info, fuel-1);
- -: 5617: }
- 19327: 5618: if (SAME_OBJ(b->tbranch, scheme_true)) {
- 3297: 5619: add_types_for_f_branch(b->test, info, fuel-1);
- 3297: 5620: add_types_for_f_branch(b->fbranch, info, fuel-1);
- -: 5621: }
- -: 5622: }
- -: 5623:}
- -: 5624:
- 424728: 5625:static int or_tentative(int x, int y)
- -: 5626:{
- 424728: 5627: if (x && y) {
- 295436: 5628: if ((x < 0) || (y < 0))
- 52306: 5629: return -1;
- -: 5630: else
- 243130: 5631: return 1;
- -: 5632: } else {
- 129292: 5633: return 0;
- -: 5634: }
- -: 5635:}
- -: 5636:
- 245190: 5637:static Scheme_Object *optimize_branch(Scheme_Object *o, Optimize_Info *info, int context)
- -: 5638:{
- -: 5639: Scheme_Branch_Rec *b;
- -: 5640: Scheme_Object *t, *tb, *fb;
- -: 5641: int init_vclock, init_aclock, init_kclock, init_sclock;
- -: 5642: Optimize_Info *then_info, *else_info;
- -: 5643: Optimize_Info *then_info_init, *else_info_init;
- -: 5644: Optimize_Info_Sequence info_seq;
- -: 5645:
- 245190: 5646: b = (Scheme_Branch_Rec *)o;
- -: 5647:
- 245190: 5648: t = b->test;
- 245190: 5649: tb = b->tbranch;
- 245190: 5650: fb = b->fbranch;
- -: 5651:
- -: 5652: /* Convert (if <id> expr <id>) to (if <id> expr #f) */
- 245190: 5653: if (equivalent_exprs(t, fb, NULL, NULL, 0)) {
- 26: 5654: fb = scheme_false;
- -: 5655: }
- -: 5656:
- -: 5657: /* For test position, convert (if <id> <id> expr) to (if <id> #t expr) */
- 245190: 5658: if ((context & OPT_CONTEXT_BOOLEAN)
- 40180: 5659: && equivalent_exprs(t, tb, NULL, NULL, 0)) {
- 97: 5660: tb = scheme_true;
- -: 5661: }
- -: 5662:
- 245190: 5663: optimize_info_seq_init(info, &info_seq);
- -: 5664:
- 245190: 5665: t = scheme_optimize_expr(t, info, OPT_CONTEXT_BOOLEAN | OPT_CONTEXT_SINGLED);
- -: 5666:
- 245190: 5667: if (info->escapes) {
- 8: 5668: optimize_info_seq_done(info, &info_seq);
- 8: 5669: return ensure_noncm(t);
- -: 5670: }
- -: 5671:
- -: 5672: /* Try to lift out `let`s and `begin`s around a test: */
- -: 5673: {
- 245182: 5674: Scheme_Object *inside = NULL, *t2 = t;
- -: 5675:
- -: 5676: while (1) {
- 246940: 5677: extract_tail_inside(&t2, &inside);
- -: 5678:
- -: 5679: /* Try optimize: (if (not x) y z) => (if x z y) */
- 246940: 5680: if (SAME_TYPE(SCHEME_TYPE(t2), scheme_application2_type)) {
- 121772: 5681: Scheme_App2_Rec *app = (Scheme_App2_Rec *)t2;
- -: 5682:
- 121772: 5683: if (SAME_PTR(scheme_not_proc, app->rator)) {
- 1758: 5684: t2 = tb;
- 1758: 5685: tb = fb;
- 1758: 5686: fb = t2;
- -: 5687:
- 1758: 5688: t2 = app->rand;
- 1758: 5689: t = replace_tail_inside(t2, inside, t);
- -: 5690: } else
- 120014: 5691: break;
- -: 5692: } else
- -: 5693: break;
- 1758: 5694: }
- -: 5695:
- 245182: 5696: if (!(SCHEME_TYPE(t2) > _scheme_ir_values_types_)) {
- -: 5697: /* (if (let (...) (cons x y)) a b) => (if (begin (let (...) (begin x y #<void>)) #t/#f) a b)
- -: 5698: but don't expand (if (let (...) (begin x K)) a b) */
- -: 5699: Scheme_Object *pred;
- -: 5700:
- 230107: 5701: pred = expr_implies_predicate(t2, info);
- 230107: 5702: if (pred) {
- 111226: 5703: Scheme_Object *test_val = NULL;
- -: 5704:
- 111226: 5705: if (predicate_implies(pred, scheme_not_proc))
- 1: 5706: test_val = scheme_false;
- 111225: 5707: else if (predicate_implies_not(pred, scheme_not_proc))
- #####: 5708: test_val = scheme_true;
- -: 5709:
- 111226: 5710: if (test_val) {
- 1: 5711: t2 = optimize_ignored(t2, info, 1, 0, 5);
- 1: 5712: t = replace_tail_inside(t2, inside, t);
- -: 5713:
- 1: 5714: t2 = test_val;
- 1: 5715: if (scheme_omittable_expr(t, 1, 5, 0, info, NULL)) {
- #####: 5716: t = test_val;
- #####: 5717: inside = NULL;
- -: 5718: } else {
- 1: 5719: t = make_sequence_2(t, test_val);
- 1: 5720: inside = t;
- -: 5721: }
- -: 5722: }
- -: 5723: }
- -: 5724: }
- -: 5725:
- 245182: 5726: if (SCHEME_TYPE(t2) > _scheme_ir_values_types_) {
- -: 5727: /* Branch is statically known */
- -: 5728: Scheme_Object *xb;
- -: 5729:
- 15076: 5730: optimize_info_seq_done(info, &info_seq);
- 15076: 5731: info->size -= 1;
- -: 5732:
- 15076: 5733: if (SCHEME_FALSEP(t2))
- 4106: 5734: xb = scheme_optimize_expr(fb, info, scheme_optimize_tail_context(context));
- -: 5735: else
- 10970: 5736: xb = scheme_optimize_expr(tb, info, scheme_optimize_tail_context(context));
- -: 5737:
- 15075: 5738: optimize_info_seq_done(info, &info_seq);
- 15075: 5739: return replace_tail_inside(xb, inside, t);
- -: 5740: }
- -: 5741: }
- -: 5742:
- 230106: 5743: optimize_info_seq_step(info, &info_seq);
- -: 5744:
- 230106: 5745: info->vclock += 1; /* model branch as clock increment */
- -: 5746:
- 230106: 5747: init_vclock = info->vclock;
- 230106: 5748: init_aclock = info->aclock;
- 230106: 5749: init_kclock = info->kclock;
- 230106: 5750: init_sclock = info->sclock;
- -: 5751:
- 230106: 5752: then_info = optimize_info_add_frame(info, 0, 0, 0);
- 230106: 5753: add_types_for_t_branch(t, then_info, 5);
- 230106: 5754: then_info_init = optimize_info_add_frame(then_info, 0, 0, 0);
- 230106: 5755: tb = scheme_optimize_expr(tb, then_info, scheme_optimize_tail_context(context));
- 230105: 5756: optimize_info_done(then_info, NULL);
- -: 5757:
- 230105: 5758: info->escapes = 0;
- 230105: 5759: info->vclock = init_vclock;
- 230105: 5760: info->aclock = init_aclock;
- 230105: 5761: info->kclock = init_kclock;
- 230105: 5762: info->sclock = init_sclock;
- -: 5763:
- 230105: 5764: optimize_info_seq_step(info, &info_seq);
- -: 5765:
- 230105: 5766: else_info = optimize_info_add_frame(info, 0, 0, 0);
- 230105: 5767: add_types_for_f_branch(t, else_info, 5);
- 230105: 5768: else_info_init = optimize_info_add_frame(else_info, 0, 0, 0);
- 230105: 5769: fb = scheme_optimize_expr(fb, else_info, scheme_optimize_tail_context(context));
- 230104: 5770: optimize_info_done(else_info, NULL);
- -: 5771:
- 230104: 5772: if (then_info->escapes && else_info->escapes) {
- -: 5773: /* both branches escaped */
- 1012: 5774: info->preserves_marks = 1;
- 1012: 5775: info->single_result = 1;
- 1012: 5776: info->kclock = init_kclock;
- -: 5777:
- 229092: 5778: } else if (info->escapes) {
- 14525: 5779: info->preserves_marks = then_info->preserves_marks;
- 14525: 5780: info->single_result = then_info->single_result;
- 14525: 5781: info->kclock = then_info->kclock;
- 14525: 5782: merge_types(then_info, info, NULL);
- 14525: 5783: info->escapes = 0;
- -: 5784:
- 214567: 5785: } else if (then_info->escapes) {
- 2203: 5786: info->preserves_marks = else_info->preserves_marks;
- 2203: 5787: info->single_result = else_info->single_result;
- 2203: 5788: merge_types(else_info, info, NULL);
- 2203: 5789: info->escapes = 0;
- -: 5790:
- -: 5791: } else {
- -: 5792: int new_preserves_marks, new_single_result;
- -: 5793:
- 212364: 5794: new_preserves_marks = or_tentative(then_info->preserves_marks, else_info->preserves_marks);
- 212364: 5795: info->preserves_marks = new_preserves_marks;
- 212364: 5796: new_single_result = or_tentative(then_info->single_result, else_info->single_result);
- 212364: 5797: info->single_result = new_single_result;
- 212364: 5798: if (then_info->kclock > info->kclock)
- 77675: 5799: info->kclock = then_info->kclock;
- 212364: 5800: merge_branchs_types(then_info, else_info, info);
- -: 5801: }
- -: 5802:
- 230104: 5803: if (then_info->sclock > info->sclock)
- 82696: 5804: info->sclock = then_info->sclock;
- 230104: 5805: if (then_info->aclock > info->aclock)
- 27751: 5806: info->aclock = then_info->aclock;
- -: 5807:
- 230104: 5808: if ((init_vclock == then_info->vclock) && (init_vclock == info->vclock)) {
- -: 5809: /* we can rewind the vclock to just after the test, because the
- -: 5810: `if` as a whole has no effect */
- 23987: 5811: info->vclock--;
- -: 5812: }
- -: 5813:
- 230104: 5814: optimize_info_seq_done(info, &info_seq);
- -: 5815:
- -: 5816: /* Try optimize: (if x #f #t) => (not x) */
- 230104: 5817: if (SCHEME_FALSEP(tb)
- 13356: 5818: && SAME_OBJ(fb, scheme_true)) {
- 94: 5819: info->size -= 2;
- 94: 5820: return make_optimize_prim_application2(scheme_not_proc, t, info, context);
- -: 5821: }
- -: 5822:
- -: 5823: /* Convert (if <boolean> #t #f) to <boolean>
- -: 5824: and, for test position, convert (if <expr> #t #f) to <expr> */
- 230010: 5825: if (SAME_OBJ(tb, scheme_true) && SAME_OBJ(fb, scheme_false)) {
- -: 5826: Scheme_Object *pred;
- -: 5827:
- 2186: 5828: if (context & OPT_CONTEXT_BOOLEAN)
- -: 5829: /* In a boolean context, any expression can be extrated. */
- 2056: 5830: pred = scheme_boolean_p_proc;
- -: 5831: else
- 130: 5832: pred = expr_implies_predicate(t, info);
- -: 5833:
- 2186: 5834: if (pred && predicate_implies(pred, scheme_boolean_p_proc)) {
- 2074: 5835: info->size -= 2;
- 2074: 5836: return ensure_single_value_noncm(t);
- -: 5837: }
- -: 5838: }
- -: 5839:
- -: 5840: /* Try optimize: (if <expr> v v) => (begin <expr> v) */
- -: 5841: {
- -: 5842: Scheme_Object *nb;
- -: 5843:
- 227936: 5844: nb = equivalent_exprs(tb, fb, then_info_init, else_info_init, context);
- 227936: 5845: if (nb) {
- 148: 5846: info->size -= 1;
- 148: 5847: return make_discarding_first_sequence(t, nb, info);
- -: 5848: }
- -: 5849: }
- -: 5850:
- -: 5851: /* Try optimize: (if x x #f) => x
- -: 5852: This pattern is included in the previous reduction,
- -: 5853: but this is still useful if x is mutable or a top level*/
- 227788: 5854: if (SCHEME_FALSEP(fb)
- 64145: 5855: && equivalent_exprs(t, tb, NULL, NULL, 0)) {
- 4: 5856: info->size -= 2;
- 4: 5857: return ensure_single_value(t);
- -: 5858: }
- -: 5859:
- -: 5860: /* Convert: expressions like
- -: 5861: (if (if M N #f) P K) => (if M (if N P K) K)
- -: 5862: for simple constants K. This is useful to expose simple
- -: 5863: tests to the JIT. */
- 227784: 5864: if (SAME_TYPE(SCHEME_TYPE(t), scheme_branch_type)) {
- 17457: 5865: Scheme_Branch_Rec *b2 = (Scheme_Branch_Rec *)t;
- 17457: 5866: Scheme_Object *ntb, *nfb, *nt2 = NULL;
- 17457: 5867: if (SCHEME_FALSEP(b2->fbranch)
- 11338: 5868: && scheme_ir_duplicate_ok(fb, 0)) {
- -: 5869: /* (if (if M N #f) P K) => (if M (if N P K) K) */
- 1124: 5870: ntb = (Scheme_Object *)b2;
- 1124: 5871: nfb = optimize_clone(0, fb, info, empty_eq_hash_tree, 0);
- 1124: 5872: nt2 = b2->tbranch;
- 16333: 5873: } else if (SCHEME_FALSEP(b2->tbranch)
- 377: 5874: && scheme_ir_duplicate_ok(fb, 0)) {
- -: 5875: /* (if (if M #f N) P K) => (if M K (if N P K)) */
- 72: 5876: ntb = optimize_clone(0, fb, info, empty_eq_hash_tree, 0);
- 72: 5877: nfb = (Scheme_Object *)b2;
- 72: 5878: nt2 = b2->fbranch;
- 16261: 5879: } else if (SAME_OBJ(b2->fbranch, scheme_true)
- 2731: 5880: && scheme_ir_duplicate_ok(tb, 0)) {
- -: 5881: /* (if (if M N #t) K P) => (if M (if N K P) K) */
- 288: 5882: ntb = (Scheme_Object *)b2;
- 288: 5883: nfb = optimize_clone(0, tb, info, empty_eq_hash_tree, 0);
- 288: 5884: nt2 = b2->tbranch;
- 15973: 5885: } else if (SAME_OBJ(b2->tbranch, scheme_true)
- 2521: 5886: && scheme_ir_duplicate_ok(tb, 0)) {
- -: 5887: /* (if (if M #t N) K P) => (if M K (if N K P)) */
- 628: 5888: ntb = optimize_clone(0, tb, info, empty_eq_hash_tree, 0);
- 628: 5889: nfb = (Scheme_Object *)b2;
- 628: 5890: nt2 = b2->fbranch;
- -: 5891: }
- 17457: 5892: if (nt2) {
- 2112: 5893: t = b2->test;
- 2112: 5894: b2->test = nt2;
- 2112: 5895: b2->tbranch = tb;
- 2112: 5896: b2->fbranch = fb;
- 2112: 5897: tb = ntb;
- 2112: 5898: fb = nfb;
- -: 5899: }
- -: 5900: }
- -: 5901:
- 227784: 5902: b->test = t;
- 227784: 5903: b->tbranch = tb;
- 227784: 5904: b->fbranch = fb;
- -: 5905:
- -: 5906: if (OPT_BRANCH_ADDS_NO_SIZE) {
- -: 5907: /* Seems to work better to not to increase the size
- -: 5908: specifically for `if' */
- -: 5909: } else {
- -: 5910: info->size += 1;
- -: 5911: }
- -: 5912:
- 227784: 5913: return o;
- -: 5914:}
- -: 5915:
- -: 5916:/*========================================================================*/
- -: 5917:/* with-continuation-marks */
- -: 5918:/*========================================================================*/
- -: 5919:
- 3341: 5920:static int omittable_key(Scheme_Object *k, Optimize_Info *info)
- -: 5921:{
- -: 5922: /* A key is not omittable if it might refer to a chaperoned/impersonated
- -: 5923: continuation mark key, so that's why we pass OMITTABLE_KEEP_VARS: */
- 3341: 5924: return scheme_omittable_expr(k, 1, 20, OMITTABLE_KEEP_VARS, info, info);
- -: 5925:}
- -: 5926:
- 3345: 5927:static Scheme_Object *optimize_wcm(Scheme_Object *o, Optimize_Info *info, int context)
- -: 5928:{
- 3345: 5929: Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)o;
- -: 5930: Scheme_Object *k, *v, *b;
- -: 5931: int init_vclock;
- -: 5932: Optimize_Info_Sequence info_seq;
- -: 5933:
- 3345: 5934: optimize_info_seq_init(info, &info_seq);
- -: 5935:
- 3345: 5936: k = scheme_optimize_expr(wcm->key, info, OPT_CONTEXT_SINGLED);
- -: 5937:
- 3345: 5938: if (info->escapes) {
- 2: 5939: optimize_info_seq_done(info, &info_seq);
- 2: 5940: return ensure_noncm(k);
- -: 5941: }
- -: 5942:
- 3343: 5943: optimize_info_seq_step(info, &info_seq);
- -: 5944:
- 3343: 5945: v = scheme_optimize_expr(wcm->val, info, OPT_CONTEXT_SINGLED);
- -: 5946:
- 3343: 5947: if (info->escapes) {
- 2: 5948: optimize_info_seq_done(info, &info_seq);
- 2: 5949: info->size += 1;
- 2: 5950: return ensure_noncm(make_discarding_first_sequence(k, v, info));
- -: 5951: }
- -: 5952:
- -: 5953: /* The presence of a key can be detected by other expressions,
- -: 5954: to increment vclock to prevent expressions incorrectly
- -: 5955: moving under the mark: */
- 3341: 5956: info->vclock++;
- 3341: 5957: init_vclock = info->vclock;
- -: 5958:
- 3341: 5959: optimize_info_seq_step(info, &info_seq);
- -: 5960:
- 3341: 5961: b = scheme_optimize_expr(wcm->body, info, scheme_optimize_tail_context(context));
- -: 5962:
- 3341: 5963: if (init_vclock == info->vclock) {
- -: 5964: /* body has no effect itself, so we can rewind the clock */
- 22: 5965: info->vclock--;
- -: 5966: }
- -: 5967:
- 3341: 5968: optimize_info_seq_done(info, &info_seq);
- -: 5969:
- -: 5970: /* If the body cannot inspect the continution, and if the key is not
- -: 5971: a chaperone, no need to add the mark: */
- 3341: 5972: if (omittable_key(k, info)
- 2031: 5973: && scheme_omittable_expr(b, -1, 20, 0, info, info))
- 50: 5974: return make_discarding_first_sequence(v, b, info);
- -: 5975:
- -: 5976: /* info->single_result is already set */
- 3291: 5977: info->preserves_marks = 0;
- -: 5978:
- 3291: 5979: wcm->key = k;
- 3291: 5980: wcm->val = v;
- 3291: 5981: wcm->body = b;
- -: 5982:
- 3291: 5983: info->size += 1;
- -: 5984:
- -: 5985: /* Simplify (with-continuation-mark <same-key> <val1>
- -: 5986: (with-continuation-mark <same-key> <val2>
- -: 5987: <body>))
- -: 5988: to (begin
- -: 5989: <val1>
- -: 5990: (with-continuation-mark <same-key> <val2>
- -: 5991: <body>))
- -: 5992: as long as <val2> doesn't inspect the continuation. */
- 3291: 5993: if (SAME_TYPE(SCHEME_TYPE(wcm->body), scheme_with_cont_mark_type)
- 21: 5994: && equivalent_exprs(wcm->key, ((Scheme_With_Continuation_Mark *)wcm->body)->key, NULL, NULL, 0)
- 11: 5995: && scheme_omittable_expr(((Scheme_With_Continuation_Mark *)wcm->body)->val, 1, 20, 0, info, info))
- 4: 5996: return make_discarding_first_sequence(wcm->val, wcm->body, info);
- -: 5997:
- 3287: 5998: return (Scheme_Object *)wcm;
- -: 5999:}
- -: 6000:
- -: 6001:/*========================================================================*/
- -: 6002:/* other syntax */
- -: 6003:/*========================================================================*/
- -: 6004:
- -: 6005:static Scheme_Object *
- 15830: 6006:define_values_optimize(Scheme_Object *data, Optimize_Info *info, int context)
- -: 6007:{
- 15830: 6008: Scheme_Object *vars = SCHEME_VEC_ELS(data)[0];
- 15830: 6009: Scheme_Object *val = SCHEME_VEC_ELS(data)[1];
- -: 6010:
- 15830: 6011: optimize_info_used_top(info);
- 15830: 6012: val = scheme_optimize_expr(val, info, 0);
- -: 6013:
- 15829: 6014: SCHEME_VEC_ELS(data)[0] = vars;
- 15829: 6015: SCHEME_VEC_ELS(data)[1] = val;
- -: 6016:
- 15829: 6017: return data;
- -: 6018:}
- -: 6019:
- -: 6020:static Scheme_Object *
- 2793: 6021:set_optimize(Scheme_Object *data, Optimize_Info *info, int context)
- -: 6022:{
- 2793: 6023: Scheme_Set_Bang *sb = (Scheme_Set_Bang *)data;
- -: 6024: Scheme_Object *var, *val;
- -: 6025:
- 2793: 6026: var = sb->var;
- 2793: 6027: val = sb->val;
- -: 6028:
- 2793: 6029: val = scheme_optimize_expr(val, info, OPT_CONTEXT_SINGLED);
- -: 6030:
- 2793: 6031: if (info->escapes)
- 10: 6032: return ensure_noncm(val);
- -: 6033:
- 2783: 6034: info->preserves_marks = 1;
- 2783: 6035: info->single_result = 1;
- -: 6036:
- 2783: 6037: if (SAME_TYPE(SCHEME_TYPE(var), scheme_ir_local_type)) {
- 2490: 6038: register_use(SCHEME_VAR(var), info);
- -: 6039: } else {
- 293: 6040: optimize_info_used_top(info);
- -: 6041: }
- -: 6042:
- 2783: 6043: info->vclock++;
- -: 6044:
- 2783: 6045: sb->var = var;
- 2783: 6046: sb->val = val;
- -: 6047:
- 2783: 6048: return (Scheme_Object *)sb;
- -: 6049:}
- -: 6050:
- -: 6051:static Scheme_Object *
- 1696: 6052:set_clone(int single_use, Scheme_Object *data, Optimize_Info *info, Scheme_Hash_Tree *var_map)
- -: 6053:{
- 1696: 6054: Scheme_Set_Bang *sb = (Scheme_Set_Bang *)data, *naya;
- -: 6055: Scheme_Object *var, *val;
- -: 6056:
- 1696: 6057: naya = MALLOC_ONE_TAGGED(Scheme_Set_Bang);
- 1696: 6058: memcpy(naya, sb, sizeof(Scheme_Set_Bang));
- -: 6059:
- 1696: 6060: var = naya->var;
- 1696: 6061: val = naya->val;
- -: 6062:
- 1696: 6063: val = optimize_clone(single_use, val, info, var_map, 0);
- 1696: 6064: if (!val) return NULL;
- 1672: 6065: if (SAME_TYPE(SCHEME_TYPE(var), scheme_ir_local_type)) {
- 1524: 6066: var = optimize_clone(single_use, var, info, var_map, 0);
- 1524: 6067: if (!var) return NULL;
- -: 6068: }
- -: 6069:
- 1672: 6070: naya->var = var;
- 1672: 6071: naya->val = val;
- -: 6072:
- 1672: 6073: return (Scheme_Object *)naya;
- -: 6074:}
- -: 6075:
- -: 6076:static Scheme_Object *
- 1049: 6077:ref_optimize(Scheme_Object *data, Optimize_Info *info, int context)
- -: 6078:{
- -: 6079: Scheme_Object *v;
- -: 6080:
- 1049: 6081: optimize_info_used_top(info);
- -: 6082:
- 1049: 6083: v = SCHEME_PTR1_VAL(data);
- 1049: 6084: if (SAME_TYPE(SCHEME_TYPE(v), scheme_ir_local_type)) {
- 18: 6085: SCHEME_PTR1_VAL(data) = (SCHEME_VAR(v)->mutated ? scheme_false : scheme_true);
- 1031: 6086: } else if (SAME_TYPE(SCHEME_TYPE(v), scheme_ir_toplevel_type)) {
- -: 6087: /* Knowing whether a top-level variable is fixed lets up optimize
- -: 6088: uses of `variable-reference-constant?` */
- 1031: 6089: if (info->top_level_consts) {
- 857: 6090: int pos = SCHEME_TOPLEVEL_POS(v);
- 857: 6091: int fixed = 0;
- -: 6092:
- 857: 6093: if (scheme_hash_get(info->top_level_consts, scheme_make_integer(pos)))
- #####: 6094: fixed = 1;
- -: 6095: else {
- -: 6096: GC_CAN_IGNORE Scheme_Object *t;
- 857: 6097: t = scheme_hash_get(info->top_level_consts, scheme_false);
- 857: 6098: if (t) {
- 645: 6099: if (scheme_hash_get((Scheme_Hash_Table *)t, scheme_make_integer(pos)))
- 57: 6100: fixed = 1;
- -: 6101: }
- -: 6102: }
- -: 6103:
- 857: 6104: if (fixed) {
- 57: 6105: v = scheme_toplevel_to_flagged_toplevel(v, SCHEME_TOPLEVEL_FIXED);
- 57: 6106: SCHEME_PTR1_VAL(data) = v;
- -: 6107: }
- -: 6108: }
- -: 6109: }
- -: 6110:
- 1049: 6111: info->preserves_marks = 1;
- 1049: 6112: info->single_result = 1;
- 1049: 6113: info->size++;
- -: 6114:
- 1049: 6115: return data;
- -: 6116:}
- -: 6117:
- -: 6118:static Scheme_Object *
- 150: 6119:ref_clone(int single_use, Scheme_Object *data, Optimize_Info *info, Scheme_Hash_Tree *var_map)
- -: 6120:{
- -: 6121: Scheme_Object *naya;
- -: 6122: Scheme_Object *a, *b;
- -: 6123:
- 150: 6124: a = SCHEME_PTR1_VAL(data);
- 150: 6125: a = optimize_clone(single_use, a, info, var_map, 0);
- 150: 6126: if (!a) return NULL;
- -: 6127:
- 150: 6128: b = SCHEME_PTR2_VAL(data);
- 150: 6129: b = optimize_clone(single_use, b, info, var_map, 0);
- 150: 6130: if (!b) return NULL;
- -: 6131:
- 150: 6132: naya = scheme_alloc_object();
- 150: 6133: naya->type = scheme_varref_form_type;
- 150: 6134: SCHEME_PTR1_VAL(naya) = a;
- 150: 6135: SCHEME_PTR2_VAL(naya) = b;
- -: 6136:
- 150: 6137: return naya;
- -: 6138:}
- -: 6139:
- -: 6140:static Scheme_Object *
- 726: 6141:apply_values_optimize(Scheme_Object *data, Optimize_Info *info, int context)
- -: 6142:{
- -: 6143: Scheme_Object *f, *e;
- -: 6144: Optimize_Info_Sequence info_seq;
- -: 6145:
- 726: 6146: f = SCHEME_PTR1_VAL(data);
- 726: 6147: e = SCHEME_PTR2_VAL(data);
- -: 6148:
- 726: 6149: optimize_info_seq_init(info, &info_seq);
- -: 6150:
- 726: 6151: f = scheme_optimize_expr(f, info, OPT_CONTEXT_SINGLED);
- -: 6152:
- 726: 6153: if (info->escapes) {
- #####: 6154: optimize_info_seq_done(info, &info_seq);
- #####: 6155: return ensure_noncm(f);
- -: 6156: }
- 726: 6157: optimize_info_seq_step(info, &info_seq);
- -: 6158:
- 726: 6159: e = scheme_optimize_expr(e, info, 0);
- -: 6160:
- 726: 6161: optimize_info_seq_done(info, &info_seq);
- -: 6162:
- 726: 6163: if (info->escapes) {
- 2: 6164: info->size += 1;
- 2: 6165: return ensure_noncm(make_discarding_first_sequence(f, e, info));
- -: 6166: }
- -: 6167:
- 724: 6168: info->size += 1;
- 724: 6169: info->vclock += 1;
- 724: 6170: info->kclock += 1;
- 724: 6171: info->sclock += 1;
- -: 6172:
- 724: 6173: return optimize_apply_values(f, e, info, info->single_result, context);
- -: 6174:}
- -: 6175:
- -: 6176:static Scheme_Object *
- 340: 6177:apply_values_clone(int single_use, Scheme_Object *data, Optimize_Info *info, Scheme_Hash_Tree *var_map)
- -: 6178:{
- -: 6179: Scheme_Object *f, *e;
- -: 6180:
- 340: 6181: f = SCHEME_PTR1_VAL(data);
- 340: 6182: e = SCHEME_PTR2_VAL(data);
- -: 6183:
- 340: 6184: f = optimize_clone(single_use, f, info, var_map, 0);
- 340: 6185: if (!f) return NULL;
- 340: 6186: e = optimize_clone(single_use, e, info, var_map, 0);
- 340: 6187: if (!e) return NULL;
- -: 6188:
- 340: 6189: data = scheme_alloc_object();
- 340: 6190: data->type = scheme_apply_values_type;
- 340: 6191: SCHEME_PTR1_VAL(data) = f;
- 340: 6192: SCHEME_PTR2_VAL(data) = e;
- -: 6193:
- 340: 6194: return data;
- -: 6195:}
- -: 6196:
- -: 6197:static Scheme_Object *
- 267: 6198:with_immed_mark_optimize(Scheme_Object *data, Optimize_Info *info, int context)
- -: 6199:{
- 267: 6200: Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)data;
- -: 6201: Scheme_Object *key, *val, *body;
- -: 6202: Optimize_Info_Sequence info_seq;
- -: 6203: Optimize_Info *body_info;
- -: 6204: Scheme_IR_Local *var;
- -: 6205:
- 267: 6206: optimize_info_seq_init(info, &info_seq);
- -: 6207:
- 267: 6208: key = scheme_optimize_expr(wcm->key, info, OPT_CONTEXT_SINGLED);
- 267: 6209: optimize_info_seq_step(info, &info_seq);
- 267: 6210: if (info->escapes) {
- #####: 6211: optimize_info_seq_done(info, &info_seq);
- #####: 6212: return ensure_noncm(key);
- -: 6213: }
- -: 6214:
- 267: 6215: val = scheme_optimize_expr(wcm->val, info, OPT_CONTEXT_SINGLED);
- 267: 6216: optimize_info_seq_step(info, &info_seq);
- 267: 6217: if (info->escapes) {
- #####: 6218: optimize_info_seq_done(info, &info_seq);
- #####: 6219: return ensure_noncm(make_discarding_first_sequence(key, val, info));
- -: 6220: }
- -: 6221:
- 267: 6222: optimize_info_seq_done(info, &info_seq);
- -: 6223:
- 267: 6224: body_info = optimize_info_add_frame(info, 1, 1, 0);
- 267: 6225: var = SCHEME_VAR(SCHEME_CAR(wcm->body));
- 267: 6226: set_optimize_mode(var);
- 267: 6227: var->optimize.lambda_depth = body_info->lambda_depth;
- 267: 6228: var->optimize_used = 0;
- 267: 6229: var->optimize.init_kclock = info->kclock;
- -: 6230:
- 267: 6231: body = scheme_optimize_expr(SCHEME_CDR(wcm->body), body_info, 0);
- -: 6232:
- 267: 6233: optimize_info_done(body_info, NULL);
- -: 6234:
- 267: 6235: wcm->key = key;
- 267: 6236: wcm->val = val;
- 267: 6237: SCHEME_CDR(wcm->body) = body;
- -: 6238:
- 267: 6239: return data;
- -: 6240:}
- -: 6241:
- -: 6242:static Scheme_Object *
- 112: 6243:with_immed_mark_clone(int single_use, Scheme_Object *data, Optimize_Info *info, Scheme_Hash_Tree *var_map)
- -: 6244:{
- 112: 6245: Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)data;
- -: 6246: Scheme_With_Continuation_Mark *wcm2;
- -: 6247: Scheme_Object *e;
- -: 6248: Scheme_IR_Local *var;
- -: 6249:
- 112: 6250: wcm2 = MALLOC_ONE_TAGGED(Scheme_With_Continuation_Mark);
- 112: 6251: wcm2->so.type = scheme_with_immed_mark_type;
- -: 6252:
- 112: 6253: e = optimize_clone(single_use, wcm->key, info, var_map, 0);
- 112: 6254: if (!e) return NULL;
- 112: 6255: wcm2->key = e;
- -: 6256:
- 112: 6257: e = optimize_clone(single_use, wcm->val, info, var_map, 0);
- 112: 6258: if (!e) return NULL;
- 112: 6259: wcm2->val = e;
- -: 6260:
- 112: 6261: var = clone_variable(SCHEME_VAR(SCHEME_CAR(wcm->body)));
- 112: 6262: var_map = scheme_hash_tree_set(var_map, SCHEME_CAR(wcm->body), (Scheme_Object *)var);
- -: 6263:
- 112: 6264: e = optimize_clone(single_use, SCHEME_CDR(wcm->body), info, var_map, 0);
- 112: 6265: if (!e) return NULL;
- 112: 6266: e = scheme_make_mutable_pair((Scheme_Object *)var, e);
- 112: 6267: wcm2->body = e;
- -: 6268:
- 112: 6269: return (Scheme_Object *)wcm2;
- -: 6270:}
- -: 6271:
- -: 6272:static Scheme_Object *
- 2026: 6273:case_lambda_optimize(Scheme_Object *expr, Optimize_Info *info, int context)
- -: 6274:{
- -: 6275: Scheme_Object *le;
- -: 6276: int i;
- 2026: 6277: Scheme_Case_Lambda *seq = (Scheme_Case_Lambda *)expr;
- -: 6278:
- 6785: 6279: for (i = 0; i < seq->count; i++) {
- 4759: 6280: le = seq->array[i];
- 4759: 6281: le = scheme_optimize_expr(le, info, 0);
- 4759: 6282: seq->array[i] = le;
- -: 6283: }
- -: 6284:
- 2026: 6285: info->preserves_marks = 1;
- 2026: 6286: info->single_result = 1;
- 2026: 6287: info->size += 1;
- -: 6288:
- 2026: 6289: return expr;
- -: 6290:}
- -: 6291:
- -: 6292:static Scheme_Object *
- 764: 6293:case_lambda_clone(int single_use, Scheme_Object *data, Optimize_Info *info, Scheme_Hash_Tree *var_map)
- -: 6294:{
- -: 6295: Scheme_Object *le;
- -: 6296: int i, sz;
- 764: 6297: Scheme_Case_Lambda *seq = (Scheme_Case_Lambda *)data;
- -: 6298: Scheme_Case_Lambda *seq2;
- -: 6299:
- 764: 6300: sz = sizeof(Scheme_Case_Lambda) + ((seq->count - mzFLEX_DELTA) * sizeof(Scheme_Object*));
- 764: 6301: seq2 = (Scheme_Case_Lambda *)scheme_malloc_tagged(sz);
- 764: 6302: memcpy(seq2, seq, sz);
- -: 6303:
- 2529: 6304: for (i = 0; i < seq->count; i++) {
- 1765: 6305: le = seq->array[i];
- 1765: 6306: le = optimize_clone(single_use, le, info, var_map, 0);
- 1765: 6307: if (!le) return NULL;
- 1765: 6308: seq2->array[i] = le;
- -: 6309: }
- -: 6310:
- 764: 6311: return (Scheme_Object *)seq2;
- -: 6312:}
- -: 6313:
- 370: 6314:static Scheme_Object *begin0_optimize(Scheme_Object *obj, Optimize_Info *info, int context)
- -: 6315:{
- 370: 6316: int i, count, drop = 0, prev_size, single_result = 0, preserves_marks = 0, kclock = 0, sclock = 0;
- 370: 6317: Scheme_Sequence *s = (Scheme_Sequence *)obj;
- 370: 6318: Scheme_Object *inside = NULL, *expr, *orig_first;
- -: 6319: Scheme_Object *le;
- -: 6320: Optimize_Info_Sequence info_seq;
- -: 6321:
- 370: 6322: count = s->count;
- 370: 6323: optimize_info_seq_init(info, &info_seq);
- -: 6324:
- 1087: 6325: for (i = 0; i < count; i++) {
- 747: 6326: prev_size = info->size;
- -: 6327:
- 747: 6328: optimize_info_seq_step(info, &info_seq);
- -: 6329:
- 747: 6330: le = scheme_optimize_expr(s->array[i],
- -: 6331: info,
- -: 6332: (!i
- -: 6333: ? scheme_optimize_result_context(context)
- -: 6334: : 0));
- -: 6335:
- 747: 6336: if (!i) {
- 370: 6337: single_result = info->single_result;
- 370: 6338: preserves_marks = info->preserves_marks;
- 370: 6339: kclock = info->kclock;
- 370: 6340: sclock = info->sclock;
- 370: 6341: s->array[0] = le;
- -: 6342: } else {
- -: 6343: /* Inlining and constant propagation can expose omittable expressions: */
- 377: 6344: le = optimize_ignored(le, info, -1, 1, 5);
- 377: 6345: if (!le) {
- 99: 6346: drop++;
- 99: 6347: info->size = prev_size;
- 99: 6348: s->array[i] = NULL;
- -: 6349: } else {
- 278: 6350: s->array[i] = le;
- -: 6351: }
- -: 6352: }
- -: 6353:
- 747: 6354: if (info->escapes) {
- -: 6355: int j;
- 30: 6356: single_result = info->single_result;
- 30: 6357: preserves_marks = info->preserves_marks;
- 42: 6358: for (j = i + 1; j < count; j++) {
- 12: 6359: drop++;
- 12: 6360: s->array[j] = NULL;
- -: 6361: }
- 30: 6362: break;
- -: 6363: }
- -: 6364: }
- -: 6365:
- 370: 6366: optimize_info_seq_done(info, &info_seq);
- -: 6367:
- 370: 6368: if (info->escapes) {
- -: 6369: /* In case of an error, optimize (begin0 ... <error> ...) => (begin ... <error>) */
- -: 6370: Scheme_Sequence *s2;
- 30: 6371: int j = 0;
- -: 6372:
- 30: 6373: info->single_result = 1;
- 30: 6374: info->preserves_marks = 1;
- -: 6375:
- 30: 6376: if (i != 0) {
- -: 6377: /* We will ignore the first expression too */
- 6: 6378: le = optimize_ignored(s->array[0], info, -1, 1, 5);
- 6: 6379: if (!le) {
- 2: 6380: drop++;
- 2: 6381: info->size = prev_size;
- 2: 6382: s->array[0] = NULL;
- -: 6383: } else {
- 4: 6384: s->array[0] = le;
- -: 6385: }
- -: 6386: }
- -: 6387:
- 30: 6388: if ((count - drop) == 1) {
- -: 6389: /* If it's only one expression we can drop the begin0 */
- 26: 6390: return ensure_noncm(s->array[i]);
- -: 6391: }
- -: 6392:
- 4: 6393: s2 = scheme_malloc_sequence(count - drop);
- 4: 6394: s2->so.type = scheme_sequence_type;
- 4: 6395: s2->count = count - drop;
- -: 6396:
- 20: 6397: for (i = 0; i < count; i++) {
- 16: 6398: if (s->array[i]) {
- 12: 6399: s2->array[j++] = s->array[i];
- -: 6400: }
- -: 6401: }
- 4: 6402: return flatten_sequence((Scheme_Object *)s2, info, context);
- -: 6403: }
- -: 6404:
- 340: 6405: info->preserves_marks = 1;
- 340: 6406: info->single_result = single_result;
- -: 6407:
- 340: 6408: if ((s->count - drop) == 1 && (preserves_marks == 1)) {
- -: 6409: /* If the first expression preserves marks we can drop the begin0 */
- 26: 6410: return s->array[0];
- -: 6411: }
- -: 6412:
- 314: 6413: expr = s->array[0];
- 314: 6414: orig_first = s->array[0];
- 314: 6415: extract_tail_inside(&expr, &inside);
- -: 6416:
- -: 6417: /* Try optimize (begin0 <movable> ...) => (begin ... <movable>) */
- 314: 6418: if (movable_expression(expr, info, 0, kclock != info->kclock,
- 314: 6419: sclock != info->sclock, 0, 50)) {
- 12: 6420: if ((s->count - drop) == 1) {
- -: 6421: /* drop the begin0 */
- #####: 6422: info->size -= 1;
- -: 6423: /* expr = expr */
- -: 6424: } else {
- -: 6425: Scheme_Sequence *s2;
- 12: 6426: int j = 0;
- -: 6427:
- 12: 6428: s2 = scheme_malloc_sequence(s->count - drop);
- 12: 6429: s2->so.type = scheme_sequence_type;
- 12: 6430: s2->count = s->count - drop;
- -: 6431:
- 24: 6432: for (i = 1; i < s->count; i++) {
- 12: 6433: if (s->array[i]) {
- 12: 6434: s2->array[j++] = s->array[i];
- -: 6435: }
- -: 6436: }
- 12: 6437: s2->array[j++] = expr;
- -: 6438:
- 12: 6439: expr = (Scheme_Object *)s2;
- -: 6440: }
- -: 6441: } else {
- 302: 6442: if (drop) {
- -: 6443: Scheme_Sequence *s2;
- 15: 6444: int j = 0;
- -: 6445:
- 15: 6446: s2 = scheme_malloc_sequence(s->count - drop);
- 15: 6447: s2->so.type = s->so.type;
- 15: 6448: s2->count = s->count - drop;
- -: 6449:
- 15: 6450: s2->array[j++] = expr;
- 89: 6451: for (i = 1; i < s->count; i++) {
- 74: 6452: if (s->array[i]) {
- 1: 6453: s2->array[j++] = s->array[i];
- -: 6454: }
- -: 6455: }
- -: 6456:
- 15: 6457: expr = (Scheme_Object *)s2;
- -: 6458: } else {
- 287: 6459: s->array[0] = expr;
- 287: 6460: expr = (Scheme_Object *)s;
- -: 6461: }
- -: 6462: }
- -: 6463:
- 314: 6464: info->size += 1;
- 314: 6465: expr = flatten_sequence(expr, info, context);
- 314: 6466: return replace_tail_inside(expr, inside, orig_first);
- -: 6467:}
- -: 6468:
- 7: 6469:static Scheme_Object *do_define_syntaxes_optimize(Scheme_Object *data, Optimize_Info *info)
- -: 6470:{
- -: 6471: Scheme_Object *val;
- -: 6472: Optimize_Info *einfo;
- -: 6473:
- 7: 6474: val = SCHEME_VEC_ELS(data)[3];
- -: 6475:
- 7: 6476: einfo = scheme_optimize_info_create(info->cp, info->env, info->insp, 0);
- 7: 6477: if (info->inline_fuel < 0)
- #####: 6478: einfo->inline_fuel = -1;
- 7: 6479: einfo->logger = info->logger;
- -: 6480:
- 7: 6481: val = scheme_optimize_expr(val, einfo, 0);
- -: 6482:
- 7: 6483: SCHEME_VEC_ELS(data)[3] = val;
- -: 6484:
- 7: 6485: return data;
- -: 6486:}
- -: 6487:
- 7: 6488:static Scheme_Object *define_syntaxes_optimize(Scheme_Object *data, Optimize_Info *info, int context)
- -: 6489:{
- 7: 6490: return do_define_syntaxes_optimize(data, info);
- -: 6491:}
- -: 6492:
- #####: 6493:static Scheme_Object *begin_for_syntax_optimize(Scheme_Object *data, Optimize_Info *info, int context)
- -: 6494:{
- -: 6495: Scheme_Object *l, *a;
- -: 6496: Optimize_Info *einfo;
- -: 6497:
- #####: 6498: l = SCHEME_VEC_ELS(data)[2];
- -: 6499:
- #####: 6500: while (!SCHEME_NULLP(l)) {
- #####: 6501: einfo = scheme_optimize_info_create(info->cp, info->env, info->insp, 0);
- #####: 6502: if (info->inline_fuel < 0)
- #####: 6503: einfo->inline_fuel = -1;
- #####: 6504: einfo->logger = info->logger;
- -: 6505:
- #####: 6506: a = SCHEME_CAR(l);
- #####: 6507: a = scheme_optimize_expr(a, einfo, 0);
- #####: 6508: SCHEME_CAR(l) = a;
- -: 6509:
- #####: 6510: l = SCHEME_CDR(l);
- -: 6511: }
- -: 6512:
- #####: 6513: return data;
- -: 6514:}
- -: 6515:
- -: 6516:/*========================================================================*/
- -: 6517:/* let, let-values, letrec, etc. */
- -: 6518:/*========================================================================*/
- -: 6519:
- 439: 6520:static int is_liftable_prim(Scheme_Object *v, int or_escape)
- -: 6521:/* Can we lift a call to `v` out of a `letrec` to a wrapping `let`? */
- -: 6522:{
- 439: 6523: if (SCHEME_PRIMP(v)) {
- 254: 6524: int opt = (((Scheme_Primitive_Proc *)v)->pp.flags & SCHEME_PRIM_OPT_MASK);
- 254: 6525: if (opt >= SCHEME_PRIM_OPT_IMMEDIATE)
- 112: 6526: return 1;
- 142: 6527: if (or_escape && (opt >= SCHEME_PRIM_OPT_NONCM)) {
- 24: 6528: if (SCHEME_PRIM_PROC_OPT_FLAGS(v) & SCHEME_PRIM_ALWAYS_ESCAPES)
- 20: 6529: return 1;
- -: 6530: }
- -: 6531: }
- -: 6532:
- 307: 6533: if (SAME_OBJ(v, scheme_values_proc))
- 16: 6534: return 1;
- -: 6535:
- 291: 6536: return 0;
- -: 6537:}
- -: 6538:
- 16093: 6539:int scheme_is_liftable(Scheme_Object *o, Scheme_Hash_Tree *exclude_vars, int fuel, int as_rator, int or_escape)
- -: 6540: /* Can we lift `o` out of a `letrec` to a wrapping `let`? Refences
- -: 6541: to `exclude_vars` are not allowed, since those are the LHS. */
- -: 6542:{
- 16093: 6543: Scheme_Type t = SCHEME_TYPE(o);
- -: 6544:
- 16093: 6545: if (!fuel) return 0;
- -: 6546:
- 16093: 6547: switch (t) {
- -: 6548: case scheme_ir_lambda_type:
- 14856: 6549: return !as_rator;
- -: 6550: case scheme_case_lambda_sequence_type:
- 32: 6551: return !as_rator;
- -: 6552: case scheme_ir_toplevel_type:
- 3: 6553: return 1;
- -: 6554: case scheme_ir_local_type:
- 80: 6555: if (!scheme_hash_tree_get(exclude_vars, o))
- 67: 6556: return 1;
- 13: 6557: break;
- -: 6558: case scheme_branch_type:
- -: 6559: {
- 33: 6560: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)o;
- 33: 6561: if (scheme_is_liftable(b->test, exclude_vars, fuel - 1, 0, or_escape)
- 26: 6562: && scheme_is_liftable(b->tbranch, exclude_vars, fuel - 1, as_rator, or_escape)
- 2: 6563: && scheme_is_liftable(b->fbranch, exclude_vars, fuel - 1, as_rator, or_escape))
- 2: 6564: return 1;
- -: 6565: }
- 31: 6566: break;
- -: 6567: case scheme_application_type:
- -: 6568: {
- 149: 6569: Scheme_App_Rec *app = (Scheme_App_Rec *)o;
- -: 6570: int i;
- 149: 6571: if (!is_liftable_prim(app->args[0], or_escape))
- 124: 6572: return 0;
- 74: 6573: for (i = app->num_args + 1; i--; ) {
- 25: 6574: if (!scheme_is_liftable(app->args[i], exclude_vars, fuel - 1, 1, or_escape))
- 1: 6575: return 0;
- -: 6576: }
- 24: 6577: return 1;
- -: 6578: }
- -: 6579: break;
- -: 6580: case scheme_application2_type:
- -: 6581: {
- 166: 6582: Scheme_App2_Rec *app = (Scheme_App2_Rec *)o;
- 166: 6583: if (!is_liftable_prim(app->rator, or_escape))
- 129: 6584: return 0;
- 37: 6585: if (scheme_is_liftable(app->rator, exclude_vars, fuel - 1, 1, or_escape)
- 37: 6586: && scheme_is_liftable(app->rand, exclude_vars, fuel - 1, 1, or_escape))
- 34: 6587: return 1;
- -: 6588: }
- 3: 6589: break;
- -: 6590: case scheme_application3_type:
- -: 6591: {
- 124: 6592: Scheme_App3_Rec *app = (Scheme_App3_Rec *)o;
- 124: 6593: if (!is_liftable_prim(app->rator, or_escape))
- 38: 6594: return 0;
- 86: 6595: if (scheme_is_liftable(app->rator, exclude_vars, fuel - 1, 1, or_escape)
- 86: 6596: && scheme_is_liftable(app->rand1, exclude_vars, fuel - 1, 1, or_escape)
- 65: 6597: && scheme_is_liftable(app->rand2, exclude_vars, fuel - 1, 1, or_escape))
- 65: 6598: return 1;
- -: 6599: }
- 21: 6600: break;
- -: 6601: case scheme_ir_let_header_type:
- -: 6602: {
- 53: 6603: Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)o;
- -: 6604: int i;
- -: 6605:
- 53: 6606: o = lh->body;
- 129: 6607: for (i = lh->num_clauses; i--; ) {
- 56: 6608: if (!scheme_is_liftable(((Scheme_IR_Let_Value *)o)->value, exclude_vars, fuel - 1, as_rator, or_escape))
- 33: 6609: return 0;
- 23: 6610: o = ((Scheme_IR_Let_Value *)o)->body;
- -: 6611: }
- 20: 6612: if (scheme_is_liftable(o, exclude_vars, fuel - 1, as_rator, or_escape))
- 7: 6613: return 1;
- 13: 6614: break;
- -: 6615: }
- -: 6616: default:
- 597: 6617: if (t > _scheme_ir_values_types_)
- 421: 6618: return 1;
- -: 6619: }
- -: 6620:
- 257: 6621: return 0;
- -: 6622:}
- -: 6623:
- 338120: 6624:int scheme_ir_propagate_ok(Scheme_Object *value, Optimize_Info *info)
- -: 6625:/* Can we constant-propagate the expression `value`? */
- -: 6626:{
- 338120: 6627: if (SAME_TYPE(SCHEME_TYPE(value), scheme_ir_lambda_type)) {
- -: 6628: int sz;
- 40523: 6629: sz = lambda_body_size_plus_info((Scheme_Lambda *)value, 1, info, NULL);
- 40523: 6630: if ((sz >= 0) && (sz <= MAX_PROC_INLINE_SIZE))
- 37208: 6631: return 1;
- -: 6632: else {
- 3315: 6633: Scheme_Lambda *lam = (Scheme_Lambda *)value;
- 3315: 6634: if (sz < 0)
- 52: 6635: scheme_log(info->logger,
- -: 6636: SCHEME_LOG_DEBUG,
- -: 6637: 0,
- -: 6638: /* contains non-copyable body elements that prevent inlining */
- -: 6639: "non-copyable %s size: %d threshold: %d#<separator>%s",
- 26: 6640: scheme_write_to_string(lam->name ? lam->name : scheme_false, NULL),
- -: 6641: sz,
- -: 6642: 0, /* no sensible threshold here */
- -: 6643: scheme_optimize_context_to_string(info->context));
- -: 6644: else
- 6578: 6645: scheme_log(info->logger,
- -: 6646: SCHEME_LOG_DEBUG,
- -: 6647: 0,
- -: 6648: /* too large to be an inlining candidate */
- -: 6649: "too-large %s size: %d threshold: %d#<separator>%s",
- 3289: 6650: scheme_write_to_string(lam->name ? lam->name : scheme_false, NULL),
- -: 6651: sz,
- -: 6652: 0, /* no sensible threshold here */
- -: 6653: scheme_optimize_context_to_string(info->context));
- 3315: 6654: return 0;
- -: 6655: }
- -: 6656: }
- -: 6657:
- 297597: 6658: if (SAME_TYPE(scheme_case_lambda_sequence_type, SCHEME_TYPE(value))) {
- 755: 6659: Scheme_Case_Lambda *cl = (Scheme_Case_Lambda *)value;
- -: 6660: int i;
- 3230: 6661: for (i = cl->count; i--; ) {
- 1759: 6662: if (!scheme_ir_propagate_ok(cl->array[i], info))
- 39: 6663: return 0;
- -: 6664: }
- 716: 6665: return 1;
- -: 6666: }
- -: 6667:
- 296842: 6668: if (SAME_TYPE(SCHEME_TYPE(value), scheme_ir_toplevel_type)) {
- 3657: 6669: if ((SCHEME_TOPLEVEL_FLAGS(value) & SCHEME_TOPLEVEL_FLAGS_MASK) >= SCHEME_TOPLEVEL_FIXED)
- 3221: 6670: return 1;
- 436: 6671: if (info->top_level_consts) {
- -: 6672: int pos;
- 345: 6673: pos = SCHEME_TOPLEVEL_POS(value);
- 345: 6674: value = scheme_hash_get(info->top_level_consts, scheme_make_integer(pos));
- 345: 6675: value = no_potential_size(value);
- 345: 6676: if (SAME_OBJ(value, scheme_constant_key)
- 345: 6677: || (value && SAME_TYPE(SCHEME_TYPE(value), scheme_struct_proc_shape_type)))
- #####: 6678: return 0;
- 345: 6679: if (value)
- #####: 6680: return 1;
- -: 6681: }
- 436: 6682: return 0;
- -: 6683: }
- -: 6684:
- -: 6685: /* Test this after the specific cases,
- -: 6686: because it recognizes locals and toplevels. */
- 293185: 6687: if (scheme_ir_duplicate_ok(value, 0))
- 99575: 6688: return 1;
- -: 6689:
- 193610: 6690: return 0;
- -: 6691:}
- -: 6692:
- 1237426: 6693:int scheme_is_statically_proc(Scheme_Object *value, Optimize_Info *info, int flags)
- -: 6694:/* Does `value` definitely produce a procedure of a specific shape?
- -: 6695: This function can be used on resolved (and SFS) forms, too, and it
- -: 6696: must be consistent with (i.e., as least as accepting as)
- -: 6697: optimization-time decisions. The `flags` argument is for
- -: 6698: scheme_omittable_expr(). */
- -: 6699:{
- -: 6700: while (1) {
- 1237426: 6701: if (SCHEME_LAMBDAP(value)
- 1216937: 6702: || SCHEME_PROCP(value)
- 1053515: 6703: || SAME_TYPE(SCHEME_TYPE(value), scheme_lambda_type)
- 187726: 6704: || SAME_TYPE(SCHEME_TYPE(value), scheme_case_lambda_sequence_type)
- 187726: 6705: || SAME_TYPE(SCHEME_TYPE(value), scheme_inline_variant_type))
- 1156805: 6706: return 1;
- 80732: 6707: else if (SAME_TYPE(SCHEME_TYPE(value), scheme_ir_let_header_type)) {
- -: 6708: /* Look for (let ([x <omittable>]) <proc>), which is generated for optional arguments. */
- 262: 6709: Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)value;
- 262: 6710: if (lh->num_clauses == 1) {
- 247: 6711: Scheme_IR_Let_Value *lv = (Scheme_IR_Let_Value *)lh->body;
- 247: 6712: if (scheme_omittable_expr(lv->value, lv->count, 20, flags, info, NULL)) {
- 111: 6713: value = lv->body;
- -: 6714: } else
- 136: 6715: break;
- -: 6716: } else
- 15: 6717: break;
- 82096: 6718: } else if (SAME_TYPE(SCHEME_TYPE(value), scheme_let_one_type)) {
- 4007: 6719: Scheme_Let_One *lo = (Scheme_Let_One *)value;
- 4007: 6720: if (scheme_omittable_expr(lo->value, 1, 20, flags, info, NULL)) {
- 1737: 6721: value = lo->body;
- -: 6722: } else
- 2270: 6723: break;
- 76352: 6724: } else if (SAME_TYPE(SCHEME_TYPE(value), scheme_boxenv_type)) {
- 481: 6725: value = SCHEME_PTR2_VAL(value);
- 75871: 6726: } else if (SAME_TYPE(SCHEME_TYPE(value), scheme_sequence_type)
- -: 6727: /* Handle a sequence for resolved mode, because it might
- -: 6728: be for safe-for-space clears around a procedure */
- #####: 6729: && (flags & OMITTABLE_RESOLVED)) {
- #####: 6730: Scheme_Sequence *seq = (Scheme_Sequence *)value;
- -: 6731: int i;
- #####: 6732: for (i = 0; i < seq->count-1; i++) {
- #####: 6733: if (!scheme_omittable_expr(seq->array[i], 1, 5, flags, info, NULL))
- #####: 6734: break;
- -: 6735: }
- #####: 6736: if (i == seq->count-1) {
- #####: 6737: value = seq->array[i];
- -: 6738: } else
- #####: 6739: break;
- -: 6740: } else
- -: 6741: break;
- 2329: 6742: }
- -: 6743:
- 78292: 6744: return 0;
- -: 6745:}
- -: 6746:
- 286: 6747:Scheme_Object *scheme_make_noninline_proc(Scheme_Object *e)
- -: 6748:/* Make a record that presents a procedure of a known shape, but
- -: 6749: that should not be inlined. */
- -: 6750:{
- -: 6751: Scheme_Object *ni;
- -: 6752:
- 651: 6753: while (SAME_TYPE(SCHEME_TYPE(e), scheme_ir_let_header_type)) {
- -: 6754: /* This must be (let ([x <omittable>]) <proc>); see scheme_is_statically_proc() */
- 79: 6755: Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)e;
- 79: 6756: Scheme_IR_Let_Value *lv = (Scheme_IR_Let_Value *)lh->body;
- -: 6757: MZ_ASSERT(lh->num_clauses == 1);
- 79: 6758: e = lv->body;
- -: 6759: }
- -: 6760:
- 286: 6761: ni = scheme_alloc_small_object();
- 286: 6762: ni->type = scheme_noninline_proc_type;
- 286: 6763: SCHEME_PTR_VAL(ni) = e;
- -: 6764:
- 286: 6765: return ni;
- -: 6766:}
- -: 6767:
- 10198: 6768:static int is_values_apply(Scheme_Object *e, int n, Optimize_Info *info, Scheme_Hash_Tree *except_vars, int fuel)
- -: 6769:/* Is `e` a `(values ...)` form --- or, in the case of `if`, can be be
- -: 6770: converted to one, so that we can split apart the results
- -: 6771: statically? */
- -: 6772:{
- 10198: 6773: if (SAME_TYPE(SCHEME_TYPE(e), scheme_application_type)) {
- 4215: 6774: Scheme_App_Rec *app = (Scheme_App_Rec *)e;
- 4215: 6775: if (n != app->num_args) return 0;
- 1316: 6776: return SAME_OBJ(scheme_values_proc, app->args[0]);
- 5983: 6777: } else if ((n == 1) && SAME_TYPE(SCHEME_TYPE(e), scheme_application2_type)) {
- #####: 6778: Scheme_App2_Rec *app = (Scheme_App2_Rec *)e;
- #####: 6779: return SAME_OBJ(scheme_values_proc, app->rator);
- 5983: 6780: } else if ((n == 2) && SAME_TYPE(SCHEME_TYPE(e), scheme_application3_type)) {
- 1116: 6781: Scheme_App3_Rec *app = (Scheme_App3_Rec *)e;
- 1116: 6782: return SAME_OBJ(scheme_values_proc, app->rator);
- 4867: 6783: } else if (fuel && SAME_TYPE(SCHEME_TYPE(e), scheme_branch_type)) {
- 762: 6784: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)e;
- 762: 6785: if (SAME_TYPE(SCHEME_TYPE(b->test), scheme_ir_local_type)
- 176: 6786: && !scheme_hash_tree_get(except_vars, b->test)
- 176: 6787: && !SCHEME_VAR(b->test)->mutated) {
- 352: 6788: return (is_values_apply(b->tbranch, n, info, except_vars, 0)
- 176: 6789: && is_values_apply(b->fbranch, n, info, except_vars, 0));
- -: 6790: }
- -: 6791: }
- -: 6792:
- 4691: 6793: return 0;
- -: 6794:}
- -: 6795:
- 1390: 6796:static int no_mutable_bindings(Scheme_IR_Let_Value *irlv)
- -: 6797:/* Check whether a `let` clause has any mutable bindings */
- -: 6798:{
- -: 6799: int i;
- -: 6800:
- 3948: 6801: for (i = irlv->count; i--; ) {
- 1172: 6802: if (irlv->vars[i]->mutated)
- 4: 6803: return 0;
- -: 6804: }
- -: 6805:
- 1386: 6806: return 1;
- -: 6807:}
- -: 6808:
- 1197: 6809:static void update_rhs_value(Scheme_IR_Let_Value *naya, Scheme_Object *e,
- -: 6810: Optimize_Info *info, Scheme_IR_Local *tst)
- -: 6811:/* Install an expression from a split `(values ...)` */
- -: 6812:{
- 1197: 6813: if (tst) {
- -: 6814: Scheme_Object *n;
- -: 6815:
- 21: 6816: n = equivalent_exprs(naya->value, e, NULL, NULL, 0);
- 21: 6817: if (!n) {
- -: 6818: Scheme_Branch_Rec *b;
- -: 6819:
- -: 6820: /* We're duplicating the test */
- 21: 6821: increment_use_count(tst, 0);
- -: 6822:
- 21: 6823: b = MALLOC_ONE_TAGGED(Scheme_Branch_Rec);
- 21: 6824: b->so.type = scheme_branch_type;
- 21: 6825: b->test = (Scheme_Object *)tst;
- 21: 6826: b->tbranch = naya->value;
- 21: 6827: b->fbranch = e;
- -: 6828:
- 21: 6829: naya->value = (Scheme_Object *)b;
- -: 6830: } else
- #####: 6831: naya->value = n;
- -: 6832: } else
- 1176: 6833: naya->value = e;
- 1197: 6834:}
- -: 6835:
- 381: 6836:static void unpack_values_application(Scheme_Object *e, Scheme_IR_Let_Value *naya,
- -: 6837: Optimize_Info *info, Scheme_IR_Local *branch_test)
- -: 6838:/* Install the expressions from a split `values` form into new `let` clauses */
- -: 6839:{
- 516: 6840: if (SAME_TYPE(SCHEME_TYPE(e), scheme_application_type)) {
- 135: 6841: Scheme_App_Rec *app = (Scheme_App_Rec *)e;
- -: 6842: int i;
- 860: 6843: for (i = 0; i < app->num_args; i++) {
- 725: 6844: update_rhs_value(naya, app->args[i + 1], info, branch_test);
- 725: 6845: naya = (Scheme_IR_Let_Value *)naya->body;
- -: 6846: }
- 246: 6847: } else if (SAME_TYPE(SCHEME_TYPE(e), scheme_application2_type)) {
- #####: 6848: Scheme_App2_Rec *app = (Scheme_App2_Rec *)e;
- #####: 6849: update_rhs_value(naya, app->rand, info, branch_test);
- 482: 6850: } else if (SAME_TYPE(SCHEME_TYPE(e), scheme_application3_type)) {
- 236: 6851: Scheme_App3_Rec *app = (Scheme_App3_Rec *)e;
- 236: 6852: update_rhs_value(naya, app->rand1, info, branch_test);
- 236: 6853: naya = (Scheme_IR_Let_Value *)naya->body;
- 236: 6854: update_rhs_value(naya, app->rand2, info, branch_test);
- 10: 6855: } else if (SAME_TYPE(SCHEME_TYPE(e), scheme_branch_type)) {
- 10: 6856: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)e;
- -: 6857:
- -: 6858: MZ_ASSERT(SAME_TYPE(SCHEME_TYPE(b->test), scheme_ir_local_type));
- -: 6859:
- 10: 6860: unpack_values_application(b->tbranch, naya, info, NULL);
- 10: 6861: unpack_values_application(b->fbranch, naya, info, SCHEME_VAR(b->test));
- -: 6862: }
- 381: 6863:}
- -: 6864:
- 8798: 6865:static Scheme_Object *make_clones(Scheme_IR_Let_Value *retry_start,
- -: 6866: Scheme_IR_Let_Value *pre_body,
- -: 6867: Optimize_Info *body_info)
- -: 6868:/* Clone `lambda`s for re-optimization and for a fixpoint computation of
- -: 6869: procedure properties */
- -: 6870:{
- -: 6871: Scheme_IR_Let_Value *irlv;
- -: 6872: Scheme_Object *value, *clone, *pr;
- 8798: 6873: Scheme_Object *last = NULL, *first = NULL;
- -: 6874:
- 8798: 6875: irlv = retry_start;
- -: 6876: while (1) {
- 9694: 6877: value = irlv->value;
- 9694: 6878: if (SCHEME_LAMBDAP(value)) {
- 9499: 6879: clone = optimize_clone(1, value, body_info, empty_eq_hash_tree, 0);
- 9499: 6880: if (clone) {
- 9499: 6881: pr = scheme_make_raw_pair(scheme_make_raw_pair(value, clone), NULL);
- -: 6882: } else
- #####: 6883: pr = scheme_make_raw_pair(NULL, NULL);
- 9499: 6884: if (last)
- 732: 6885: SCHEME_CDR(last) = pr;
- -: 6886: else
- 8767: 6887: first = pr;
- 9499: 6888: last = pr;
- -: 6889: }
- 9694: 6890: if (irlv == pre_body)
- 8798: 6891: break;
- 896: 6892: irlv = (Scheme_IR_Let_Value *)irlv->body;
- 896: 6893: }
- -: 6894:
- 8798: 6895: return first;
- -: 6896:}
- -: 6897:
- 43419: 6898:static int set_one_code_flags(Scheme_Object *value, int flags,
- -: 6899: Scheme_Object *first, Scheme_Object *second,
- -: 6900: int set_flags, int mask_flags, int just_tentative,
- -: 6901: int merge_local_typed)
- -: 6902:/* Set, record, or merge procedure-property flags */
- -: 6903:{
- -: 6904: Scheme_Case_Lambda *cl, *cl2, *cl3;
- -: 6905: Scheme_Lambda *lam, *lam2, *lam3;
- -: 6906: int i, count;
- -: 6907:
- 43419: 6908: if (SAME_TYPE(scheme_ir_lambda_type, SCHEME_TYPE(value))) {
- 42450: 6909: count = 1;
- 42450: 6910: cl = NULL;
- 42450: 6911: cl2 = NULL;
- 42450: 6912: cl3 = NULL;
- -: 6913: } else {
- 969: 6914: cl = (Scheme_Case_Lambda *)value;
- 969: 6915: cl2 = (Scheme_Case_Lambda *)first;
- 969: 6916: cl3 = (Scheme_Case_Lambda *)second;
- 969: 6917: count = cl->count;
- -: 6918: }
- -: 6919:
- 88248: 6920: for (i = 0; i < count; i++) {
- 44829: 6921: if (cl) {
- 2379: 6922: lam = (Scheme_Lambda *)cl->array[i];
- 2379: 6923: lam2 = (Scheme_Lambda *)cl2->array[i];
- 2379: 6924: lam3 = (Scheme_Lambda *)cl3->array[i];
- -: 6925: } else {
- 42450: 6926: lam = (Scheme_Lambda *)value;
- 42450: 6927: lam2 = (Scheme_Lambda *)first;
- 42450: 6928: lam3 = (Scheme_Lambda *)second;
- -: 6929: }
- -: 6930:
- 44829: 6931: if (merge_local_typed) {
- 9523: 6932: merge_lambda_arg_types(lam, lam2);
- 9523: 6933: merge_lambda_arg_types(lam, lam3);
- 9523: 6934: merge_lambda_arg_types(lam, lam2);
- -: 6935: }
- -: 6936:
- 44829: 6937: if (!just_tentative || (SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_RESULT_TENTATIVE)) {
- 38986: 6938: flags = (flags & SCHEME_LAMBDA_FLAGS(lam));
- 38986: 6939: SCHEME_LAMBDA_FLAGS(lam2) = set_flags | (SCHEME_LAMBDA_FLAGS(lam2) & mask_flags);
- 38986: 6940: SCHEME_LAMBDA_FLAGS(lam3) = set_flags | (SCHEME_LAMBDA_FLAGS(lam3) & mask_flags);
- -: 6941: }
- -: 6942: }
- -: 6943:
- 43419: 6944: return flags;
- -: 6945:}
- -: 6946:
- 26394: 6947:static int set_code_flags(Scheme_IR_Let_Value *retry_start,
- -: 6948: Scheme_IR_Let_Value *pre_body,
- -: 6949: Scheme_Object *clones,
- -: 6950: int set_flags, int mask_flags, int just_tentative,
- -: 6951: int merge_local_typed)
- -: 6952:/* Set, record, or merge procedure-property flags */
- -: 6953:{
- -: 6954: Scheme_IR_Let_Value *irlv;
- -: 6955: Scheme_Object *value, *first;
- 26394: 6956: int flags = LAMBDA_SINGLE_RESULT | LAMBDA_PRESERVES_MARKS;
- -: 6957:
- -: 6958: /* The first in a clone pair is the one that is consulted for
- -: 6959: references. The second one is the clone, and it's the one whose
- -: 6960: flags are updated by optimization. So consult the clone, and set
- -: 6961: flags in both. */
- -: 6962:
- 26394: 6963: irlv = retry_start;
- 55359: 6964: while (clones) {
- 28818: 6965: value = irlv->value;
- 28818: 6966: if (SCHEME_LAMBDAP(value)) {
- 28497: 6967: first = SCHEME_CAR(clones);
- -: 6968:
- 28497: 6969: if (first)
- 28497: 6970: flags = set_one_code_flags(value, flags,
- 28497: 6971: SCHEME_CAR(first), SCHEME_CDR(first),
- -: 6972: set_flags, mask_flags, just_tentative,
- -: 6973: merge_local_typed);
- -: 6974:
- 28497: 6975: clones = SCHEME_CDR(clones);
- -: 6976: }
- -: 6977:
- 28818: 6978: if (irlv == pre_body)
- 26247: 6979: break;
- 2571: 6980: irlv = (Scheme_IR_Let_Value *)irlv->body;
- -: 6981: }
- -: 6982:
- 26394: 6983: return flags;
- -: 6984:}
- -: 6985:
- 157348: 6986:static int lambda_body_size(Scheme_Object *o, int less_args)
- -: 6987:{
- -: 6988: int bsz;
- -: 6989:
- 157348: 6990: if (SAME_TYPE(SCHEME_TYPE(o), scheme_ir_lambda_type)) {
- 16873: 6991: bsz = lambda_body_size_plus_info((Scheme_Lambda *)o, 0, NULL, NULL);
- 16873: 6992: if (less_args) bsz -= ((Scheme_Lambda *)o)->num_params;
- 16873: 6993: return bsz;
- 140475: 6994: } else if (SAME_TYPE(SCHEME_TYPE(o), scheme_case_lambda_sequence_type)) {
- 358: 6995: Scheme_Case_Lambda *cl = (Scheme_Case_Lambda *)o;
- 358: 6996: int i, sz = 0;
- 1597: 6997: for (i = cl->count; i--; ) {
- 881: 6998: bsz = lambda_body_size_plus_info((Scheme_Lambda *)cl->array[i], 0, NULL, NULL);
- 881: 6999: if (less_args) {
- 762: 7000: bsz -= ((Scheme_Lambda *)cl->array[i])->num_params;
- 762: 7001: if (bsz > sz) sz = bsz;
- -: 7002: } else
- 119: 7003: sz += bsz;
- -: 7004: }
- 358: 7005: return sz;
- -: 7006: } else
- 140117: 7007: return 0;
- -: 7008:}
- -: 7009:
- 142657: 7010:static int expr_size(Scheme_Object *o)
- -: 7011:{
- 142657: 7012: return lambda_body_size(o, 0) + 1;
- -: 7013:}
- -: 7014:
- 15068: 7015:int scheme_might_invoke_call_cc(Scheme_Object *value)
- -: 7016:{
- 15068: 7017: return !scheme_is_liftable(value, empty_eq_hash_tree, 10, 0, 1);
- -: 7018:}
- -: 7019:
- -: 7020:#define ADVANCE_CLOCKS_INIT_FUEL 3
- -: 7021:
- 13507: 7022:void advance_clocks_for_optimized(Scheme_Object *o,
- -: 7023: GC_CAN_IGNORE int *_vclock,
- -: 7024: GC_CAN_IGNORE int *_aclock,
- -: 7025: GC_CAN_IGNORE int *_kclock,
- -: 7026: GC_CAN_IGNORE int *_sclock,
- -: 7027: Optimize_Info *info,
- -: 7028: int fuel)
- -: 7029:/* It's ok for this function to advance clocks *less* than
- -: 7030: accurately, but not more than accurately */
- -: 7031:{
- 13507: 7032: Scheme_Object *rator = NULL;
- 13507: 7033: int argc = 0;
- -: 7034:
- 13507: 7035: if (!fuel) return;
- -: 7036:
- 13015: 7037: switch (SCHEME_TYPE(o)) {
- -: 7038: case scheme_application_type:
- -: 7039: {
- 752: 7040: Scheme_App_Rec *app = (Scheme_App_Rec *)o;
- -: 7041: int i;
- 3604: 7042: for (i = 0; i < app->num_args; i++) {
- 2852: 7043: advance_clocks_for_optimized(app->args[i+1],
- -: 7044: _vclock, _aclock, _kclock, _sclock,
- -: 7045: info, fuel - 1);
- -: 7046: }
- 752: 7047: rator = app->args[0];
- 752: 7048: argc = app->num_args;
- -: 7049: }
- 752: 7050: break;
- -: 7051: case scheme_application2_type:
- -: 7052: {
- 1712: 7053: Scheme_App2_Rec *app = (Scheme_App2_Rec *)o;
- 1712: 7054: advance_clocks_for_optimized(app->rand,
- -: 7055: _vclock, _aclock, _kclock, _sclock,
- -: 7056: info, fuel - 1);
- 1712: 7057: rator = app->rator;
- 1712: 7058: argc = 1;
- 1712: 7059: break;
- -: 7060: }
- -: 7061: case scheme_application3_type:
- -: 7062: {
- 2229: 7063: Scheme_App3_Rec *app = (Scheme_App3_Rec *)o;
- 2229: 7064: advance_clocks_for_optimized(app->rand1,
- -: 7065: _vclock, _aclock, _kclock, _sclock,
- -: 7066: info, fuel - 1);
- 2229: 7067: advance_clocks_for_optimized(app->rand2,
- -: 7068: _vclock, _aclock, _kclock, _sclock,
- -: 7069: info, fuel - 1);
- 2229: 7070: rator = app->rator;
- 2229: 7071: argc = 2;
- -: 7072: }
- 2229: 7073: break;
- -: 7074: default:
- 8322: 7075: break;
- -: 7076: }
- -: 7077:
- 13015: 7078: if (rator)
- 4693: 7079: increment_clock_counts_for_application(_vclock, _aclock, _kclock, _sclock, rator, argc);
- -: 7080:
- 13015: 7081: if ((*_vclock > info->vclock)
- 13015: 7082: || (*_aclock > info->aclock)
- 13015: 7083: || (*_kclock > info->kclock)
- 13015: 7084: || (*_sclock > info->sclock))
- #####: 7085: scheme_signal_error("internal error: optimizer clock tracking has gone wrong");
- -: 7086:}
- -: 7087:
- 39033: 7088:static void set_application_types(Scheme_Object *o, Optimize_Info *info, int fuel)
- -: 7089:/* Peek ahead in an expression to set readily apparent type information
- -: 7090: for function calls. This information is useful for type-invariant loop
- -: 7091: arguments, for example. */
- -: 7092:{
- 39033: 7093: if (!fuel) return;
- -: 7094:
- 38353: 7095: switch (SCHEME_TYPE(o)) {
- -: 7096: case scheme_application_type:
- -: 7097: {
- 1530: 7098: Scheme_App_Rec *app = (Scheme_App_Rec *)o;
- -: 7099: int i;
- 1530: 7100: register_local_argument_types(app, NULL, NULL, info);
- 7274: 7101: for (i = 0; i < app->num_args+1; i++) {
- 5744: 7102: set_application_types(app->args[i], info, fuel - 1);
- -: 7103: }
- -: 7104: }
- 1530: 7105: break;
- -: 7106: case scheme_application2_type:
- -: 7107: {
- 6206: 7108: Scheme_App2_Rec *app = (Scheme_App2_Rec *)o;
- 6206: 7109: register_local_argument_types(NULL, app, NULL, info);
- 6206: 7110: set_application_types(app->rator, info, fuel - 1);
- 6206: 7111: set_application_types(app->rand, info, fuel - 1);
- 6206: 7112: break;
- -: 7113: }
- -: 7114: case scheme_application3_type:
- -: 7115: {
- 2959: 7116: Scheme_App3_Rec *app = (Scheme_App3_Rec *)o;
- 2959: 7117: register_local_argument_types(NULL, NULL, app, info);
- 2959: 7118: set_application_types(app->rator, info, fuel - 1);
- 2959: 7119: set_application_types(app->rand1, info, fuel - 1);
- 2959: 7120: set_application_types(app->rand2, info, fuel - 1);
- -: 7121: }
- 2959: 7122: break;
- -: 7123: case scheme_sequence_type:
- -: 7124: case scheme_begin0_sequence_type:
- -: 7125: {
- 188: 7126: Scheme_Sequence *seq = (Scheme_Sequence *)o;
- -: 7127: int i;
- -: 7128:
- 644: 7129: for (i = 0; i < seq->count; i++) {
- 456: 7130: set_application_types(seq->array[i], info, fuel - 1);
- -: 7131: }
- -: 7132: }
- 188: 7133: break;
- -: 7134: case scheme_branch_type:
- -: 7135: {
- 945: 7136: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)o;
- 945: 7137: set_application_types(b->test, info, fuel - 1);
- 945: 7138: set_application_types(b->tbranch, info, fuel - 1);
- 945: 7139: set_application_types(b->fbranch, info, fuel - 1);
- -: 7140: }
- 945: 7141: break;
- -: 7142: default:
- 26525: 7143: break;
- -: 7144: }
- -: 7145:}
- -: 7146:
- 33840: 7147:static void flip_transitive(Scheme_Hash_Table *ht, int on)
- -: 7148:/* Adjust usage flags based on recorded tentative uses */
- -: 7149:{
- -: 7150: Scheme_IR_Local *tvar;
- -: 7151: int j;
- 33840: 7152: Scheme_Object *to_remove = scheme_null;
- -: 7153:
- 329080: 7154: for (j = 0; j < ht->size; j++) {
- 295240: 7155: if (ht->vals[j]) {
- 70247: 7156: tvar = SCHEME_VAR(ht->keys[j]);
- 70247: 7157: if (on) {
- 18193: 7158: if (tvar->optimize_used) {
- -: 7159: /* use of `tvar` is no longer dependent on anohter variable */
- #####: 7160: to_remove = scheme_make_pair((Scheme_Object *)tvar,
- -: 7161: to_remove);
- -: 7162: } else
- 18193: 7163: tvar->optimize_used = 1;
- -: 7164: } else {
- -: 7165: MZ_ASSERT(tvar->optimize_used);
- 52054: 7166: tvar->optimize_used = 0;
- -: 7167: }
- -: 7168: }
- -: 7169: }
- -: 7170:
- 67680: 7171: while (!SCHEME_NULLP(to_remove)) {
- #####: 7172: scheme_hash_set(ht, SCHEME_CAR(to_remove), NULL);
- #####: 7173: to_remove = SCHEME_CDR(to_remove);
- -: 7174: }
- 33840: 7175:}
- -: 7176:
- 29097: 7177:static void start_transitive_use_record(Optimize_Info *to_info, Optimize_Info *info, Scheme_IR_Local *var)
- -: 7178:/* Start recording uses as tentative. Uses in a `lambda` as the RHS of
- -: 7179: the binding of `var` will only be used in the end of `var` itself
- -: 7180: is used. */
- -: 7181:{
- 29097: 7182: if (var->optimize_used)
- #####: 7183: return;
- -: 7184:
- 29097: 7185: info->transitive_use_var = var;
- -: 7186:
- -: 7187: /* Restore use flags, if any, saved from before: */
- 29097: 7188: if (var->optimize.transitive_uses)
- 9322: 7189: flip_transitive(var->optimize.transitive_uses, 1);
- -: 7190:}
- -: 7191:
- 337277: 7192:static void end_transitive_use_record(Optimize_Info *info)
- -: 7193:/* Stop recording uses as tentative. */
- -: 7194:{
- 337277: 7195: Scheme_IR_Local *var = info->transitive_use_var;
- -: 7196:
- 337277: 7197: if (var != info->next->transitive_use_var) {
- 29097: 7198: info->transitive_use_var = info->next->transitive_use_var;
- -: 7199:
- 29097: 7200: if (var->optimize.transitive_uses)
- 24518: 7201: flip_transitive(var->optimize.transitive_uses, 0);
- -: 7202: }
- 337277: 7203:}
- -: 7204:
- 238039: 7205:static Scheme_Object *optimize_lets(Scheme_Object *form, Optimize_Info *info, int context)
- -: 7206:/* This is the main entry point for optimizing a `let[rec]-values` form. */
- -: 7207:{
- -: 7208: Optimize_Info *body_info, *rhs_info;
- -: 7209: Optimize_Info_Sequence info_seq;
- 238039: 7210: Scheme_IR_Let_Header *head = (Scheme_IR_Let_Header *)form;
- -: 7211: Scheme_IR_Let_Value *irlv, *pre_body, *retry_start, *prev_body;
- 238039: 7212: Scheme_Object *body, *value, *ready_pairs = NULL, *rp_last = NULL, *ready_pairs_start;
- 238039: 7213: Scheme_Object *escape_body = scheme_false;
- -: 7214: Scheme_Once_Used *once_used;
- -: 7215: Scheme_Hash_Tree *merge_skip_vars;
- 238039: 7216: int i, j, is_rec, not_simply_let_star = 0, undiscourage, skip_opts = 0;
- -: 7217: int did_set_value, found_escapes;
- 238039: 7218: int remove_last_one = 0, inline_fuel;
- 238039: 7219: int pre_vclock, pre_aclock, pre_kclock, pre_sclock, increments_kclock = 0;
- 238039: 7220: int once_vclock, once_aclock, once_kclock, once_sclock, once_increments_kclock = 0;
- -: 7221:
- -: 7222: /* Special case: (let ([x M]) (if x x N)), where x is not in N,
- -: 7223: to (if M #t N), when the expression is in a test position
- -: 7224: or the result of M is a boolean?. */
- 238039: 7225: if (!(SCHEME_LET_FLAGS(head) & SCHEME_LET_RECURSIVE)
- 227134: 7226: && (head->count == 1)
- 160331: 7227: && (head->num_clauses == 1)) {
- 160319: 7228: irlv = (Scheme_IR_Let_Value *)head->body;
- 160319: 7229: if (SAME_TYPE(SCHEME_TYPE(irlv->body), scheme_branch_type)
- 67025: 7230: && (irlv->vars[0]->use_count == 2)) {
- 25947: 7231: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)irlv->body;
- 25947: 7232: if (SAME_OBJ(b->test, (Scheme_Object *)irlv->vars[0])
- 14247: 7233: && SAME_OBJ(b->tbranch, (Scheme_Object *)irlv->vars[0])) {
- -: 7234: Scheme_Object *pred;
- -: 7235:
- 5123: 7236: if (context & OPT_CONTEXT_BOOLEAN)
- -: 7237: /* In a boolean context, any expression can be moved. */
- 1708: 7238: pred = scheme_boolean_p_proc;
- -: 7239: else
- 3415: 7240: pred = expr_implies_predicate(irlv->value, info);
- -: 7241:
- 5123: 7242: if (pred && predicate_implies(pred, scheme_boolean_p_proc)) {
- -: 7243: Scheme_Branch_Rec *b3;
- -: 7244:
- 2074: 7245: b3 = MALLOC_ONE_TAGGED(Scheme_Branch_Rec);
- 2074: 7246: b3->so.type = scheme_branch_type;
- 2074: 7247: b3->test = irlv->value;
- 2074: 7248: b3->tbranch = scheme_true;
- 2074: 7249: b3->fbranch = b->fbranch;
- -: 7250:
- 2074: 7251: form = scheme_optimize_expr((Scheme_Object *)b3, info, context);
- -: 7252:
- 2074: 7253: return form;
- -: 7254: }
- -: 7255: }
- -: 7256: }
- -: 7257: }
- -: 7258:
- 235965: 7259: is_rec = (SCHEME_LET_FLAGS(head) & SCHEME_LET_RECURSIVE);
- -: 7260:
- -: 7261: /* Special case: (let ([x E]) x) => E or (values E) */
- 235965: 7262: if (!is_rec
- 225060: 7263: && (head->count == 1)
- 158257: 7264: && (head->num_clauses == 1)) {
- 158245: 7265: irlv = (Scheme_IR_Let_Value *)head->body;
- 158245: 7266: if (SAME_OBJ((Scheme_Object *)irlv->vars[0], irlv->body)) {
- 847: 7267: body = irlv->value;
- 847: 7268: body = ensure_single_value_noncm(body);
- 847: 7269: return scheme_optimize_expr(body, info, context);
- -: 7270: }
- -: 7271: }
- -: 7272:
- 235118: 7273: if (!is_rec) {
- -: 7274: int try_again;
- -: 7275: do {
- 235534: 7276: try_again = 0;
- -: 7277: /* (let ([x (let ([y M]) N)]) P) => (let ([y M]) (let ([x N]) P))
- -: 7278: or (let ([x (begin M ... N)]) P) => (begin M ... (let ([x N]) P)) */
- 235534: 7279: if (head->num_clauses) {
- 235534: 7280: irlv = (Scheme_IR_Let_Value *)head->body; /* ([x ...]) */
- 247311: 7281: if (SAME_TYPE(SCHEME_TYPE(irlv->value), scheme_ir_let_header_type)) {
- 11777: 7282: Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)irlv->value; /* (let ([y ...]) ...) */
- -: 7283:
- 11777: 7284: if (!lh->num_clauses) {
- #####: 7285: irlv->value = lh->body;
- #####: 7286: lh->body = (Scheme_Object *)head;
- -: 7287: } else {
- 11777: 7288: body = lh->body;
- 24527: 7289: for (i = lh->num_clauses - 1; i--; ) {
- 973: 7290: body = ((Scheme_IR_Let_Value *)body)->body;
- -: 7291: }
- 11777: 7292: irlv->value = ((Scheme_IR_Let_Value *)body)->body; /* N */
- 11777: 7293: ((Scheme_IR_Let_Value *)body)->body = (Scheme_Object *)head;
- -: 7294: }
- -: 7295:
- 11777: 7296: head = lh;
- 11777: 7297: form = (Scheme_Object *)head;
- 11777: 7298: is_rec = (SCHEME_LET_FLAGS(head) & SCHEME_LET_RECURSIVE);
- 11777: 7299: try_again = !is_rec;
- 223757: 7300: } else if (SAME_TYPE(SCHEME_TYPE(irlv->value), scheme_sequence_type)) {
- 1039: 7301: Scheme_Sequence *seq = (Scheme_Sequence *)irlv->value; /* (begin M ... N) */
- -: 7302:
- 1039: 7303: irlv->value = seq->array[seq->count - 1];
- 1039: 7304: seq->array[seq->count - 1] = (Scheme_Object *)head;
- -: 7305:
- 1039: 7306: return scheme_optimize_expr((Scheme_Object *)seq, info, context);
- -: 7307: }
- -: 7308: }
- 234495: 7309: } while (try_again);
- -: 7310: }
- -: 7311:
- 234079: 7312: body_info = optimize_info_add_frame(info, head->count, head->count, 0);
- 234079: 7313: rhs_info = body_info;
- -: 7314:
- 234079: 7315: merge_skip_vars = scheme_make_hash_tree(SCHEME_hashtr_eq);
- 234079: 7316: body = head->body;
- 795109: 7317: for (i = head->num_clauses; i--; ) {
- 326951: 7318: pre_body = (Scheme_IR_Let_Value *)body;
- 998853: 7319: for (j = pre_body->count; j--; ) {
- 344951: 7320: merge_skip_vars = scheme_hash_tree_set(merge_skip_vars, (Scheme_Object *)pre_body->vars[j], scheme_true);
- 344951: 7321: set_optimize_mode(pre_body->vars[j]);
- 344951: 7322: pre_body->vars[j]->optimize.lambda_depth = body_info->lambda_depth;
- 344951: 7323: pre_body->vars[j]->optimize_used = 0;
- 344951: 7324: pre_body->vars[j]->optimize_outside_binding = 0;
- 344951: 7325: if (!pre_body->vars[j]->mutated && is_rec) {
- -: 7326: /* Indicate that it's not yet ready, so it cannot be inlined: */
- -: 7327: Scheme_Object *rp;
- 12569: 7328: pre_body->vars[j]->optimize_unready = 1;
- 12569: 7329: rp = scheme_make_raw_pair((Scheme_Object *)pre_body->vars[j], NULL);
- 12569: 7330: if (rp_last)
- 1210: 7331: SCHEME_CDR(rp_last) = rp;
- -: 7332: else
- 11359: 7333: ready_pairs = rp;
- 12569: 7334: rp_last = rp;
- -: 7335: }
- -: 7336: }
- 326951: 7337: body = pre_body->body;
- -: 7338: }
- -: 7339:
- -: 7340: if (OPT_ESTIMATE_FUTURE_SIZES) {
- 234079: 7341: if (is_rec && !body_info->letrec_not_twice) {
- -: 7342: /* For each identifier bound to a procedure, register an initial
- -: 7343: size estimate, which is used to discourage early loop unrolling
- -: 7344: at the expense of later inlining. */
- 9203: 7345: body = head->body;
- 9203: 7346: pre_body = NULL;
- 28856: 7347: for (i = head->num_clauses; i--; ) {
- 10450: 7348: pre_body = (Scheme_IR_Let_Value *)body;
- -: 7349:
- 10450: 7350: if ((pre_body->count == 1)
- 10266: 7351: && SCHEME_LAMBDAP(pre_body->value)
- 9913: 7352: && !pre_body->vars[0]->mutated) {
- -: 7353: Scheme_Object *sz;
- 9909: 7354: sz = estimate_closure_size(pre_body->value);
- 9909: 7355: pre_body->vars[0]->optimize.known_val = sz;
- -: 7356: }
- -: 7357:
- 10450: 7358: body = pre_body->body;
- -: 7359: }
- 9203: 7360: rhs_info->use_psize = 1;
- -: 7361: }
- -: 7362: }
- -: 7363:
- 234079: 7364: optimize_info_seq_init(rhs_info, &info_seq);
- -: 7365:
- 234079: 7366: prev_body = NULL;
- 234079: 7367: body = head->body;
- 234079: 7368: pre_body = NULL;
- 234079: 7369: retry_start = NULL;
- 234079: 7370: ready_pairs_start = NULL;
- 234079: 7371: did_set_value = 0;
- 234079: 7372: found_escapes = 0;
- 794891: 7373: for (i = head->num_clauses; i--; ) {
- 327778: 7374: pre_body = (Scheme_IR_Let_Value *)body;
- -: 7375:
- 327778: 7376: if ((pre_body->count == 1)
- 317809: 7377: && SCHEME_LAMBDAP(pre_body->value)
- 19606: 7378: && !pre_body->vars[0]->optimize_used)
- 19604: 7379: start_transitive_use_record(body_info, rhs_info, pre_body->vars[0]);
- -: 7380:
- 327778: 7381: if (is_rec && OPT_DISCOURAGE_EARLY_INLINE && !rhs_info->letrec_not_twice
- 10456: 7382: && SCHEME_LAMBDAP(pre_body->value)) {
- 9915: 7383: inline_fuel = rhs_info->inline_fuel;
- 9915: 7384: if (inline_fuel > 2)
- 7215: 7385: rhs_info->inline_fuel = 2;
- 9915: 7386: rhs_info->letrec_not_twice++;
- 9915: 7387: undiscourage = 1;
- -: 7388: } else {
- 317863: 7389: inline_fuel = 0;
- 317863: 7390: undiscourage = 0;
- -: 7391: }
- -: 7392:
- 327778: 7393: if (!skip_opts) {
- 326951: 7394: pre_vclock = rhs_info->vclock;
- 326951: 7395: pre_aclock = rhs_info->aclock;
- 326951: 7396: pre_kclock = rhs_info->kclock;
- 326951: 7397: pre_sclock = rhs_info->sclock;
- 326951: 7398: if (!found_escapes) {
- 326917: 7399: optimize_info_seq_step(rhs_info, &info_seq);
- 326917: 7400: value = scheme_optimize_expr(pre_body->value, rhs_info,
- 326917: 7401: (((pre_body->count == 1)
- -: 7402: ? OPT_CONTEXT_SINGLED
- 326917: 7403: : 0)
- 326917: 7404: | (((pre_body->count == 1)
- 316954: 7405: && !pre_body->vars[0]->non_app_count)
- 28477: 7406: ? (pre_body->vars[0]->use_count << OPT_CONTEXT_APP_COUNT_SHIFT)
- 355394: 7407: : 0)));
- 326917: 7408: pre_body->value = value;
- 326917: 7409: if (rhs_info->escapes)
- 76: 7410: found_escapes = 1;
- -: 7411: } else {
- 34: 7412: optimize_info_seq_step(rhs_info, &info_seq);
- 34: 7413: value = scheme_false;
- 34: 7414: pre_body->value = value;
- 34: 7415: body_info->single_result = 1;
- 34: 7416: body_info->preserves_marks = 1;
- 34: 7417: body_info->escapes = 1;
- 34: 7418: body_info->size++;
- -: 7419: }
- 326951: 7420: once_vclock = rhs_info->vclock;
- 326951: 7421: once_aclock = rhs_info->aclock;
- 326951: 7422: once_kclock = rhs_info->kclock;
- 326951: 7423: once_sclock = rhs_info->sclock;
- 326951: 7424: increments_kclock = (once_kclock > pre_kclock);
- 326951: 7425: once_increments_kclock = increments_kclock;
- -: 7426: } else {
- 827: 7427: value = pre_body->value;
- 827: 7428: --skip_opts;
- 827: 7429: if (skip_opts) {
- -: 7430: /* when a `values` group is split, we've lost track of the
- -: 7431: clock values for points between the `values` arguments;
- -: 7432: we can conservatively assume the clock before the whole group
- -: 7433: for the purpose of registering once-used variables,
- -: 7434: but we can also conservatively advance the clock: */
- 458: 7435: if (!found_escapes)
- 458: 7436: advance_clocks_for_optimized(value,
- -: 7437: &pre_vclock, &pre_aclock, &pre_kclock, &pre_sclock,
- -: 7438: rhs_info,
- -: 7439: ADVANCE_CLOCKS_INIT_FUEL);
- 458: 7440: once_vclock = pre_vclock;
- 458: 7441: once_aclock = pre_aclock;
- 458: 7442: once_kclock = pre_kclock;
- 458: 7443: once_sclock = pre_sclock;
- -: 7444: } else {
- -: 7445: /* end of split group, so rhs_info clock is right */
- 369: 7446: once_vclock = rhs_info->vclock;
- 369: 7447: once_aclock = rhs_info->aclock;
- 369: 7448: once_kclock = rhs_info->kclock;
- 369: 7449: once_sclock = rhs_info->sclock;
- -: 7450: }
- 827: 7451: if (increments_kclock) {
- -: 7452: /* note that we conservatively assume that a member of a split
- -: 7453: advance the kclock, unless we can easily show otherwise */
- 347: 7454: once_increments_kclock = 1;
- -: 7455: }
- -: 7456: }
- -: 7457:
- 327778: 7458: if (undiscourage) {
- 9915: 7459: rhs_info->inline_fuel = inline_fuel;
- 9915: 7460: --rhs_info->letrec_not_twice;
- -: 7461: }
- -: 7462:
- 327778: 7463: end_transitive_use_record(rhs_info);
- -: 7464:
- 327778: 7465: if (is_rec && !not_simply_let_star) {
- -: 7466: /* Keep track of whether we can simplify to let*: */
- 11394: 7467: if (scheme_might_invoke_call_cc(value)
- 11335: 7468: || optimize_any_uses(body_info, pre_body, i+1))
- 11325: 7469: not_simply_let_star = 1;
- -: 7470: }
- -: 7471:
- -: 7472: /* Change (let-values ([(id ...) (values e ...)]) body)
- -: 7473: to (let-values ([id e] ...) body) for simple e.
- -: 7474: The is_values_apply() and related functions also handle
- -: 7475: (if id (values e1 ...) (values e2 ...)) to effectively convert to
- -: 7476: (values (if id e1 e2) ...) and then split the values call, since
- -: 7477: duplicating the id use and test is likely to pay off. */
- 327778: 7478: if ((pre_body->count != 1)
- 9969: 7479: && ((!is_rec && found_escapes)
- 9937: 7480: || (is_values_apply(value, pre_body->count, rhs_info, merge_skip_vars, 1)
- 1396: 7481: && ((!is_rec && no_mutable_bindings(pre_body))
- -: 7482: /* If the right-hand side is omittable, then there are
- -: 7483: no side effects, so mutation and recursiveness are ok */
- 10: 7484: || scheme_omittable_expr(value, pre_body->count, -1, 0, rhs_info, info))))) {
- 1424: 7485: if (!pre_body->count && !i) {
- -: 7486: /* We want to drop the clause entirely, but doing it
- -: 7487: here messes up the loop for letrec. So wait and
- -: 7488: remove it at the end. */
- 1045: 7489: remove_last_one = 1;
- -: 7490: /* If `found_escapes`, either this expression is the
- -: 7491: one that escaped, or `value` should have been simplified
- -: 7492: to `#f`. So, if it's not `#f`, we'll need to keep
- -: 7493: the expression part */
- 1045: 7494: if (!found_escapes)
- 1031: 7495: value = scheme_false;
- 1045: 7496: pre_body->value = value;
- -: 7497: } else {
- -: 7498: Scheme_IR_Let_Value *naya;
- 379: 7499: Scheme_Object *rest = pre_body->body;
- -: 7500: int j;
- -: 7501:
- 1954: 7502: for (j = pre_body->count; j--; ) {
- -: 7503: Scheme_IR_Local **new_vars;
- 1196: 7504: naya = MALLOC_ONE_TAGGED(Scheme_IR_Let_Value);
- 1196: 7505: naya->iso.so.type = scheme_ir_let_value_type;
- 1196: 7506: naya->body = rest;
- 1196: 7507: naya->count = 1;
- 1196: 7508: new_vars = MALLOC_N(Scheme_IR_Local *, 1);
- 1196: 7509: new_vars[0] = pre_body->vars[j];
- 1196: 7510: naya->vars = new_vars;
- 1196: 7511: rest = (Scheme_Object *)naya;
- -: 7512: }
- -: 7513:
- 379: 7514: naya = (Scheme_IR_Let_Value *)rest;
- 379: 7515: if (!found_escapes) {
- 361: 7516: unpack_values_application(value, naya, rhs_info, NULL);
- -: 7517: } else {
- 18: 7518: Scheme_IR_Let_Value *naya2 = naya;
- 38: 7519: for (j = 0; j < pre_body->count; j++) {
- 20: 7520: if (!j)
- 10: 7521: naya2->value = value;
- -: 7522: else
- 10: 7523: naya2->value = scheme_false;
- 20: 7524: naya2 = (Scheme_IR_Let_Value *)naya2->body;
- -: 7525: }
- -: 7526:
- 18: 7527: if (!pre_body->count && !SCHEME_FALSEP(value)) {
- -: 7528: /* Since `value` is not false, this clause must be the one
- -: 7529: that is escaping. We'll end up dropping the remaining
- -: 7530: clauses and the original body, but we need to keep the
- -: 7531: erroring expression. */
- 8: 7532: escape_body = value;
- -: 7533: }
- -: 7534: }
- -: 7535:
- 379: 7536: if (prev_body)
- 6: 7537: prev_body->body = (Scheme_Object *)naya;
- -: 7538: else
- 373: 7539: head->body = (Scheme_Object *)naya;
- 379: 7540: head->num_clauses += (pre_body->count - 1);
- 379: 7541: i += (pre_body->count - 1);
- 379: 7542: if (pre_body->count) {
- -: 7543: /* We're backing up. Since the RHSs have been optimized
- -: 7544: already, don't re-optimize. */
- 369: 7545: skip_opts = pre_body->count - 1;
- 369: 7546: pre_body = naya;
- 369: 7547: body = (Scheme_Object *)naya;
- 369: 7548: value = pre_body->value;
- -: 7549:
- 369: 7550: if (skip_opts) {
- -: 7551: /* Use "pre" clocks: */
- 369: 7552: if (!found_escapes)
- 359: 7553: advance_clocks_for_optimized(value,
- -: 7554: &pre_vclock, &pre_aclock, &pre_kclock, &pre_sclock,
- -: 7555: rhs_info,
- -: 7556: ADVANCE_CLOCKS_INIT_FUEL);
- 369: 7557: once_vclock = pre_vclock;
- 369: 7558: once_aclock = pre_aclock;
- 369: 7559: once_kclock = pre_kclock;
- 369: 7560: once_sclock = pre_sclock;
- -: 7561: }
- -: 7562: } else {
- -: 7563: /* We've dropped this clause entirely. */
- 10: 7564: i++;
- 10: 7565: if (i > 0) {
- 10: 7566: body = (Scheme_Object *)naya;
- 10: 7567: continue;
- -: 7568: } else
- #####: 7569: break;
- -: 7570: }
- -: 7571: }
- -: 7572: }
- -: 7573:
- 327768: 7574: if ((pre_body->count == 1) && !pre_body->vars[0]->mutated) {
- 317442: 7575: int indirect = 0, indirect_binding = 0;
- -: 7576:
- 638815: 7577: while (indirect < 10) {
- 321530: 7578: if (SAME_TYPE(SCHEME_TYPE(value), scheme_sequence_type)) {
- 157: 7579: Scheme_Sequence *seq = (Scheme_Sequence *)value;
- 157: 7580: value = seq->array[seq->count - 1];
- 157: 7581: indirect++;
- 321451: 7582: } else if (SAME_TYPE(SCHEME_TYPE(value), scheme_with_cont_mark_type)) {
- 235: 7583: Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)value;
- 235: 7584: value = wcm->body;
- 235: 7585: indirect++;
- 320981: 7586: } else if (SAME_TYPE(SCHEME_TYPE(value), scheme_ir_let_header_type)) {
- 3539: 7587: Scheme_IR_Let_Header *head2 = (Scheme_IR_Let_Header *)value;
- -: 7588: int i;
- -: 7589:
- 3539: 7590: if (head2->num_clauses < 10) {
- 3539: 7591: value = head2->body;
- 10822: 7592: for (i = head2->num_clauses; i--; ) {
- 3744: 7593: value = ((Scheme_IR_Let_Value *)value)->body;
- -: 7594: }
- -: 7595: }
- 3539: 7596: indirect++;
- 3539: 7597: if (head2->count)
- 3539: 7598: indirect_binding = 1;
- -: 7599: } else
- -: 7600: break;
- -: 7601: }
- -: 7602:
- 317442: 7603: if (indirect_binding) {
- -: 7604: /* only allow constants */
- 3193: 7605: if (SCHEME_TYPE(value) < _scheme_ir_values_types_)
- 3193: 7606: value = NULL;
- -: 7607: }
- -: 7608:
- 317442: 7609: if (value && SAME_TYPE(SCHEME_TYPE(value), scheme_ir_local_type)) {
- -: 7610: /* Don't optimize reference to a local that's mutable; also,
- -: 7611: double-check that the value is ready, because we might be
- -: 7612: nested in the RHS of a `letrec': */
- 62769: 7613: if (SCHEME_VAR(value)->mutated || SCHEME_VAR(value)->optimize_unready)
- 287: 7614: value = NULL;
- -: 7615: }
- -: 7616:
- 317442: 7617: if (value)
- 313962: 7618: value = extract_specialized_proc(value, value);
- -: 7619:
- 317442: 7620: if (value && (scheme_ir_propagate_ok(value, body_info))) {
- 119733: 7621: pre_body->vars[0]->optimize.known_val = value;
- 119733: 7622: did_set_value = 1;
- 197709: 7623: } else if (value && !is_rec) {
- -: 7624: int cnt, ct, involves_k_cross;
- -: 7625: Scheme_Object *pred;
- -: 7626:
- 193422: 7627: ct = scheme_expr_produces_local_type(value, &involves_k_cross);
- 193422: 7628: if (ct) {
- 5487: 7629: SCHEME_VAR(pre_body->vars[0])->val_type = ct;
- 5487: 7630: if (involves_k_cross) {
- -: 7631: /* Although this variable's uses do not necessarily cross
- -: 7632: a continuation capture, the inference of its type
- -: 7633: depends on that crossing, so we treat as having a crossing.
- -: 7634: This is an accommodation to the bytecode format and
- -: 7635: validator, which has no way to distinguish between
- -: 7636: a known type and unboxing capability for that type. */
- #####: 7637: SCHEME_VAR(pre_body->vars[0])->escapes_after_k_tick = 1;
- -: 7638: }
- -: 7639: }
- -: 7640:
- 193422: 7641: pred = expr_implies_predicate(value, rhs_info);
- -: 7642:
- 193422: 7643: if (pred)
- 45465: 7644: add_type(body_info, (Scheme_Object *)pre_body->vars[0], pred);
- -: 7645:
- 193422: 7646: if (!indirect) {
- 193228: 7647: cnt = pre_body->vars[0]->use_count;
- 193228: 7648: if (cnt == 1) {
- -: 7649: /* used only once; we may be able to shift the expression to the use
- -: 7650: site, instead of binding to a temporary */
- 72621: 7651: once_used = make_once_used(value, pre_body->vars[0],
- -: 7652: once_vclock, once_aclock, once_kclock, once_sclock,
- -: 7653: once_increments_kclock);
- 72621: 7654: pre_body->vars[0]->optimize.known_val = (Scheme_Object *)once_used;
- -: 7655: }
- -: 7656: }
- -: 7657: }
- -: 7658: }
- -: 7659:
- 327768: 7660: if (!retry_start) {
- 234404: 7661: retry_start = pre_body;
- 234404: 7662: ready_pairs_start = ready_pairs;
- -: 7663: }
- -: 7664:
- -: 7665: /* Re-optimize to inline letrec bindings? */
- 327768: 7666: if (is_rec
- 12731: 7667: && !body_info->letrec_not_twice
- 10456: 7668: && ((i < 1)
- 1253: 7669: || (!scheme_is_ir_lambda(((Scheme_IR_Let_Value *)pre_body->body)->value, 1, 1)
- 474: 7670: && !scheme_is_liftable(((Scheme_IR_Let_Value *)pre_body->body)->value, merge_skip_vars, 5, 1, 0)))) {
- 9528: 7671: Scheme_Object *prop_later = NULL;
- -: 7672:
- 9528: 7673: if (did_set_value) {
- -: 7674: /* Next RHS ends a reorderable sequence.
- -: 7675: Re-optimize from retry_start to pre_body, inclusive.
- -: 7676: For procedures, assume LAMBDA_SINGLE_RESULT and LAMBDA_PRESERVES_MARKS for all,
- -: 7677: but then assume not for all if any turn out not (i.e., approximate fix point). */
- -: 7678: int flags;
- -: 7679: Scheme_Object *clones, *cl, *cl_first;
- -: 7680:
- -: 7681: /* If this is the last binding, peek ahead in the body to
- -: 7682: check for easy type info in function calls */
- 8798: 7683: if (!i)
- 8709: 7684: set_application_types(pre_body->body, body_info, 5);
- -: 7685:
- -: 7686: /* Reset "unready" flags: */
- 9619: 7687: for (rp_last = ready_pairs_start; !SAME_OBJ(rp_last, ready_pairs); rp_last = SCHEME_CDR(rp_last)) {
- 821: 7688: SCHEME_VAR(SCHEME_CAR(rp_last))->optimize_unready = 1;
- -: 7689: }
- -: 7690: /* Set-flags loop: */
- 8798: 7691: clones = make_clones(retry_start, pre_body, rhs_info);
- 8798: 7692: (void)set_code_flags(retry_start, pre_body, clones,
- -: 7693: LAMBDA_SINGLE_RESULT | LAMBDA_PRESERVES_MARKS | LAMBDA_RESULT_TENTATIVE,
- -: 7694: 0xFFFF,
- -: 7695: 0,
- -: 7696: 0);
- -: 7697: /* Re-optimize loop: */
- 8798: 7698: irlv = retry_start;
- 8798: 7699: cl = clones;
- -: 7700: while (1) {
- 9694: 7701: value = irlv->value;
- 9694: 7702: if (cl) {
- 9606: 7703: cl_first = SCHEME_CAR(cl);
- 9606: 7704: if (!cl_first)
- #####: 7705: cl = SCHEME_CDR(cl);
- -: 7706: } else
- 88: 7707: cl_first = NULL;
- 9694: 7708: if (cl_first && SAME_OBJ(value, SCHEME_CAR(cl_first))) {
- -: 7709: /* Try optimization. */
- -: 7710: Scheme_Object *self_value;
- -: 7711: int sz;
- -: 7712: char use_psize;
- -: 7713:
- 9499: 7714: if ((irlv->count == 1)
- 9499: 7715: && !irlv->vars[0]->optimize_used)
- 9493: 7716: start_transitive_use_record(body_info, rhs_info, irlv->vars[0]);
- -: 7717:
- 9499: 7718: cl = SCHEME_CDR(cl);
- 9499: 7719: self_value = SCHEME_CDR(cl_first);
- -: 7720:
- -: 7721: /* Drop old size, and remove old inline fuel: */
- 9499: 7722: sz = lambda_body_size(value, 0);
- 9499: 7723: rhs_info->size -= (sz + 1);
- -: 7724:
- -: 7725: /* Setting letrec_not_twice prevents inlinining
- -: 7726: of letrec bindings in this RHS. There's a small
- -: 7727: chance that we miss some optimizations, but we
- -: 7728: avoid the possibility of N^2 behavior. */
- -: 7729: if (!OPT_DISCOURAGE_EARLY_INLINE)
- -: 7730: rhs_info->letrec_not_twice++;
- 9499: 7731: use_psize = rhs_info->use_psize;
- 9499: 7732: rhs_info->use_psize = info->use_psize;
- -: 7733:
- 9499: 7734: optimize_info_seq_step(rhs_info, &info_seq);
- 9499: 7735: value = scheme_optimize_expr(self_value, rhs_info,
- 9499: 7736: (((irlv->count == 1)
- -: 7737: ? OPT_CONTEXT_SINGLED
- 9499: 7738: : 0)
- 9499: 7739: | (((irlv->count == 1)
- 9499: 7740: && !irlv->vars[0]->non_app_count)
- 9190: 7741: ? (irlv->vars[0]->use_count << OPT_CONTEXT_APP_COUNT_SHIFT)
- 18689: 7742: : 0)));
- -: 7743:
- -: 7744: if (!OPT_DISCOURAGE_EARLY_INLINE)
- -: 7745: --rhs_info->letrec_not_twice;
- 9499: 7746: rhs_info->use_psize = use_psize;
- -: 7747:
- 9499: 7748: irlv->value = value;
- -: 7749:
- 9499: 7750: if (!irlv->vars[0]->mutated) {
- 9497: 7751: if (scheme_ir_propagate_ok(value, rhs_info)) {
- -: 7752: /* Register re-optimized as the value for the binding, but
- -: 7753: maybe only if it didn't grow too much: */
- -: 7754: int new_sz;
- -: 7755: if (OPT_DELAY_GROUP_PROPAGATE || OPT_LIMIT_FUNCTION_RESIZE)
- -: 7756: new_sz = lambda_body_size(value, 0);
- -: 7757: else
- 8668: 7758: new_sz = 0;
- 8668: 7759: if (new_sz <= sz) {
- 8668: 7760: irlv->vars[0]->optimize.known_val = value;
- -: 7761: }
- -: 7762: else if (!OPT_LIMIT_FUNCTION_RESIZE
- -: 7763: || (new_sz < 4 * sz))
- #####: 7764: prop_later = scheme_make_raw_pair(scheme_make_pair((Scheme_Object *)irlv->vars[0],
- -: 7765: value),
- -: 7766: prop_later);
- -: 7767: }
- -: 7768: }
- -: 7769:
- 9499: 7770: end_transitive_use_record(rhs_info);
- -: 7771: }
- 9694: 7772: if (irlv == pre_body)
- 8798: 7773: break;
- -: 7774: {
- -: 7775: /* Since letrec is really letrec*, the variables
- -: 7776: for this binding are now ready: */
- -: 7777: int i;
- 2667: 7778: for (i = irlv->count; i--; ) {
- 875: 7779: if (!irlv->vars[i]->mutated) {
- 821: 7780: SCHEME_VAR(SCHEME_CAR(ready_pairs_start))->optimize_unready = 0;
- 821: 7781: ready_pairs_start = SCHEME_CDR(ready_pairs_start);
- -: 7782: }
- -: 7783: }
- -: 7784: }
- 896: 7785: irlv = (Scheme_IR_Let_Value *)irlv->body;
- 896: 7786: }
- -: 7787: /* Check flags loop: */
- 8798: 7788: flags = set_code_flags(retry_start, pre_body, clones, 0, 0xFFFF, 0, 0);
- -: 7789: /* Reset-flags loop: */
- 8798: 7790: (void)set_code_flags(retry_start, pre_body, clones,
- -: 7791: (flags & (LAMBDA_SINGLE_RESULT | LAMBDA_PRESERVES_MARKS)),
- -: 7792: ~(LAMBDA_SINGLE_RESULT | LAMBDA_PRESERVES_MARKS | LAMBDA_RESULT_TENTATIVE),
- -: 7793: 1,
- -: 7794: 1);
- -: 7795: }
- 9528: 7796: retry_start = NULL;
- 9528: 7797: ready_pairs_start = NULL;
- 9528: 7798: did_set_value = 0;
- -: 7799:
- 19056: 7800: while (prop_later) {
- #####: 7801: value = SCHEME_CAR(prop_later);
- #####: 7802: SCHEME_VAR(SCHEME_CAR(value))->optimize.known_val = SCHEME_CDR(value);
- #####: 7803: prop_later = SCHEME_CDR(prop_later);
- -: 7804: }
- -: 7805: }
- -: 7806:
- 327768: 7807: if (is_rec) {
- -: 7808: /* Since letrec is really letrec*, the variables
- -: 7809: for this binding are now ready: */
- -: 7810: int i;
- 38119: 7811: for (i = pre_body->count; i--; ) {
- 12657: 7812: pre_body->vars[i]->optimize.init_kclock = rhs_info->kclock;
- 12657: 7813: if (!pre_body->vars[i]->mutated) {
- 12569: 7814: SCHEME_VAR(SCHEME_CAR(ready_pairs))->optimize_unready = 0;
- 12569: 7815: ready_pairs = SCHEME_CDR(ready_pairs);
- -: 7816: }
- -: 7817: }
- -: 7818: }
- -: 7819:
- 327768: 7820: if (remove_last_one) {
- 1045: 7821: head->num_clauses -= 1;
- 1045: 7822: body = (Scheme_Object *)pre_body->body;
- -: 7823:
- 1045: 7824: if (found_escapes && !SCHEME_FALSEP(pre_body->value)) {
- -: 7825: /* Since `pre_body->value` wasn't simplified to #f,
- -: 7826: keep this as the new body */
- 10: 7827: escape_body = pre_body->value;
- -: 7828: }
- -: 7829:
- 1045: 7830: if (prev_body) {
- 8: 7831: prev_body->body = body;
- 8: 7832: pre_body = prev_body;
- -: 7833: } else {
- 1037: 7834: head->body = body;
- 1037: 7835: pre_body = NULL;
- -: 7836: }
- 1045: 7837: break;
- -: 7838: }
- -: 7839:
- 326723: 7840: prev_body = pre_body;
- 326723: 7841: body = pre_body->body;
- -: 7842: }
- -: 7843:
- 234079: 7844: if (!is_rec) {
- -: 7845: /* All `let`-bound variables are now allocated: */
- 222718: 7846: body = head->body;
- 759428: 7847: for (i = head->num_clauses; i--; ) {
- 313992: 7848: pre_body = (Scheme_IR_Let_Value *)body;
- 960278: 7849: for (j = pre_body->count; j--; ) {
- 332294: 7850: pre_body->vars[j]->optimize.init_kclock = body_info->kclock;
- -: 7851: }
- 313992: 7852: body = pre_body->body;
- -: 7853: }
- -: 7854: }
- -: 7855:
- 234079: 7856: optimize_info_seq_done(body_info, &info_seq);
- -: 7857:
- 234079: 7858: if (!found_escapes) {
- 234003: 7859: body = scheme_optimize_expr(body, body_info, scheme_optimize_tail_context(context));
- -: 7860: } else {
- 76: 7861: body = ensure_noncm(escape_body);
- 76: 7862: body_info->single_result = 1;
- 76: 7863: body_info->preserves_marks = 1;
- 76: 7864: body_info->escapes = 1;
- 76: 7865: body_info->size++;
- -: 7866: }
- 234068: 7867: if (head->num_clauses)
- 233031: 7868: pre_body->body = body;
- -: 7869: else
- 1037: 7870: head->body = body;
- -: 7871:
- -: 7872: /* Propagate any use from formerly tentative uses: */
- -: 7873: while (1) {
- 247595: 7874: int changed = 0;
- 247595: 7875: body = head->body;
- 839309: 7876: for (i = head->num_clauses; i--; ) {
- 344119: 7877: pre_body = (Scheme_IR_Let_Value *)body;
- 1050161: 7878: for (j = pre_body->count; j--; ) {
- 361923: 7879: if (pre_body->vars[j]->optimize_used
- 208794: 7880: && pre_body->vars[j]->optimize.transitive_uses) {
- 14196: 7881: register_transitive_uses(pre_body->vars[j], body_info);
- 14196: 7882: changed = 1;
- 14196: 7883: pre_body->vars[j]->optimize.transitive_uses = NULL;
- -: 7884: }
- -: 7885: }
- 344119: 7886: body = pre_body->body;
- -: 7887: }
- 247595: 7888: if (!changed)
- 234068: 7889: break;
- 13527: 7890: }
- -: 7891:
- 234068: 7892: info->single_result = body_info->single_result;
- 234068: 7893: info->preserves_marks = body_info->preserves_marks;
- 234068: 7894: info->vclock = body_info->vclock;
- 234068: 7895: info->aclock = body_info->aclock;
- 234068: 7896: info->kclock = body_info->kclock;
- 234068: 7897: info->sclock = body_info->sclock;
- -: 7898:
- -: 7899: /* Clear used flags where possible, clear once-used references, etc. */
- 234068: 7900: body = head->body;
- 234068: 7901: prev_body = NULL;
- 794846: 7902: for (i = head->num_clauses; i--; ) {
- 326710: 7903: int used = 0, j;
- -: 7904:
- 326710: 7905: pre_body = (Scheme_IR_Let_Value *)body;
- -: 7906:
- 326710: 7907: if (pre_body->count == 1) {
- -: 7908: /* If the right-hand side is a function, make sure all use sites
- -: 7909: are accounted for toward type inference of arguments. */
- 318166: 7910: if (pre_body->vars[0]->optimize.known_val
- 187510: 7911: && SAME_TYPE(SCHEME_TYPE(pre_body->vars[0]->optimize.known_val), scheme_lambda_type)) {
- #####: 7912: check_lambda_arg_types_registered((Scheme_Lambda *)pre_body->vars[0]->optimize.known_val,
- #####: 7913: pre_body->vars[0]->use_count);
- -: 7914: }
- -: 7915: }
- -: 7916:
- 803754: 7917: for (j = pre_body->count; j--; ) {
- 330372: 7918: if (pre_body->vars[j]->optimize_used) {
- 180038: 7919: used = 1;
- 180038: 7920: break;
- -: 7921: }
- -: 7922: }
- -: 7923:
- -: 7924: /* once-used moved implies not optimize_used: */
- -: 7925: MZ_ASSERT(!(used
- -: 7926: && (pre_body->count == 1)
- -: 7927: && pre_body->vars[0]->optimize.known_val
- -: 7928: && SAME_TYPE(scheme_once_used_type, SCHEME_TYPE(pre_body->vars[0]->optimize.known_val))
- -: 7929: && ((Scheme_Once_Used *)pre_body->vars[0]->optimize.known_val)->moved));
- -: 7930:
- 326710: 7931: if (!used
- 146672: 7932: && (scheme_omittable_expr(pre_body->value, pre_body->count, -1, 0, info, info)
- 15674: 7933: || ((pre_body->count == 1)
- 15405: 7934: && pre_body->vars[0]->optimize.known_val
- 11752: 7935: && SAME_TYPE(scheme_once_used_type, SCHEME_TYPE(pre_body->vars[0]->optimize.known_val))
- 11727: 7936: && ((Scheme_Once_Used *)pre_body->vars[0]->optimize.known_val)->moved))) {
- -: 7937: /* Drop the binding(s) */
- 427971: 7938: for (j = pre_body->count; j--; ) {
- 142657: 7939: pre_body->vars[j]->mode = SCHEME_VAR_MODE_NONE;
- -: 7940: }
- 142657: 7941: head->num_clauses -= 1;
- 142657: 7942: head->count -= pre_body->count;
- 142657: 7943: if (prev_body)
- 8479: 7944: prev_body->body = pre_body->body;
- -: 7945: else
- 134178: 7946: head->body = pre_body->body;
- -: 7947: /* Deduct from size to aid further inlining. */
- 142657: 7948: {
- -: 7949: int sz;
- 142657: 7950: sz = expr_size(pre_body->value);
- 142657: 7951: body_info->size -= sz;
- -: 7952: }
- -: 7953: } else {
- 184053: 7954: if (!used && (pre_body->count == 1)) {
- -: 7955: /* The whole binding is not omittable, but maybe the tail is omittable: */
- 3746: 7956: Scheme_Object *v2 = pre_body->value, *inside;
- 3746: 7957: extract_tail_inside(&v2, &inside);
- 3746: 7958: if (scheme_omittable_expr(v2, pre_body->count, -1, 0, info, info)) {
- 25: 7959: replace_tail_inside(scheme_false, inside, pre_body->value);
- -: 7960: }
- -: 7961: }
- -: 7962:
- 570383: 7963: for (j = pre_body->count; j--; ) {
- -: 7964: int ct;
- -: 7965:
- 202277: 7966: pre_body->vars[j]->optimize_outside_binding = 1;
- 202277: 7967: if (pre_body->vars[j]->optimize.known_val
- 46409: 7968: && SAME_TYPE(scheme_once_used_type, SCHEME_TYPE(pre_body->vars[j]->optimize.known_val))) {
- -: 7969: /* We're keeping this clause here, so don't allow movement of the once-used
- -: 7970: value when peeking under bindings via extract_tail_inside(): */
- 30239: 7971: pre_body->vars[j]->optimize.known_val = NULL;
- -: 7972: }
- -: 7973:
- 202277: 7974: ct = pre_body->vars[j]->arg_type;
- 202277: 7975: if (ct) {
- 298: 7976: if (ALWAYS_PREFER_UNBOX_TYPE(ct)
- 298: 7977: || !pre_body->vars[j]->escapes_after_k_tick)
- 260: 7978: pre_body->vars[j]->arg_type = ct;
- -: 7979: }
- -: 7980: }
- 184053: 7981: info->size += 1;
- 184053: 7982: prev_body = pre_body;
- -: 7983: }
- 326710: 7984: body = pre_body->body;
- -: 7985: }
- -: 7986:
- 234068: 7987: optimize_info_done(body_info, NULL);
- 234068: 7988: merge_types(body_info, info, merge_skip_vars);
- -: 7989:
- 234068: 7990: if (is_rec && !not_simply_let_star) {
- -: 7991: /* We can simplify letrec to let* */
- 36: 7992: SCHEME_LET_FLAGS(head) -= SCHEME_LET_RECURSIVE;
- 36: 7993: is_rec = 0;
- 36: 7994: optimize_uses_of_mutable_imply_early_alloc((Scheme_IR_Let_Value *)head->body, head->num_clauses);
- -: 7995: }
- -: 7996:
- -: 7997: /* Optimized away all clauses? */
- 234068: 7998: if (!head->num_clauses) {
- 80552: 7999: return body;
- -: 8000: }
- -: 8001:
- 153516: 8002: if (!is_rec
- 142238: 8003: && ((SCHEME_TYPE(body) > _scheme_ir_values_types_)
- 138930: 8004: || SAME_TYPE(SCHEME_TYPE(body), scheme_ir_toplevel_type)
- 138930: 8005: || SAME_TYPE(SCHEME_TYPE(body), scheme_ir_local_type))) {
- -: 8006: /* If the body is a constant, toplevel or another local, the last binding
- -: 8007: is unused, so reduce (let ([x <expr>]) K) => (begin <expr> K).
- -: 8008: As a special case, include a second check for (let ([x E]) x) => E or (values E). */
- -: 8009: Scheme_Object *inside;
- -: 8010:
- 3895: 8011: inside = (Scheme_Object *)head;
- 3895: 8012: pre_body = (Scheme_IR_Let_Value *)head->body;
- 7790: 8013: for (i = head->num_clauses - 1; i--; ) {
- #####: 8014: inside = (Scheme_Object *)pre_body;
- #####: 8015: pre_body = (Scheme_IR_Let_Value *)pre_body->body;
- -: 8016: }
- -: 8017:
- 3895: 8018: if (pre_body->count == 1) {
- 3389: 8019: if (!SAME_OBJ((Scheme_Object *)pre_body->vars[0], body)
- 3314: 8020: && !found_escapes) {
- 3258: 8021: body = make_discarding_sequence(pre_body->value, body, info);
- -: 8022: } else {
- -: 8023: /* Special case for (let ([x E]) x) and (let ([x <error>]) #f) */
- 131: 8024: body = pre_body->value;
- 131: 8025: body = ensure_single_value_noncm(body);
- 131: 8026: if (found_escapes) {
- 56: 8027: found_escapes = 0; /* Perhaps the error is moved to the body. */
- 56: 8028: body = ensure_noncm(body);
- -: 8029: }
- -: 8030: }
- -: 8031:
- 3389: 8032: if (head->num_clauses == 1)
- 3389: 8033: return body;
- -: 8034:
- #####: 8035: (void)replace_tail_inside(body, inside, NULL);
- #####: 8036: head->count--;
- #####: 8037: head->num_clauses--;
- -: 8038: }
- -: 8039: }
- -: 8040:
- 150127: 8041: if (!is_rec) {
- -: 8042: /* One last pass to peel off unused bindings */
- 138849: 8043: Scheme_Object *prev = NULL, *rhs;
- -: 8044:
- 138849: 8045: body = head->body;
- 277929: 8046: for (i = head->num_clauses; i--; ) {
- 138862: 8047: pre_body = (Scheme_IR_Let_Value *)body;
- 138862: 8048: if ((pre_body->count == 1)
- 130699: 8049: && !pre_body->vars[0]->optimize_used) {
- -: 8050: Scheme_Sequence *seq;
- -: 8051: Scheme_Object *new_body;
- -: 8052:
- 231: 8053: pre_body->vars[0]->mode = SCHEME_VAR_MODE_NONE;
- -: 8054:
- 231: 8055: seq = scheme_malloc_sequence(2);
- 231: 8056: seq->so.type = scheme_sequence_type;
- 231: 8057: seq->count = 2;
- -: 8058:
- 231: 8059: rhs = pre_body->value;
- 231: 8060: rhs = ensure_single_value_noncm(rhs);
- 231: 8061: seq->array[0] = rhs;
- -: 8062:
- 231: 8063: head->count--;
- 231: 8064: head->num_clauses--;
- 231: 8065: head->body = pre_body->body;
- -: 8066:
- 231: 8067: new_body = (Scheme_Object *)seq;
- -: 8068:
- 231: 8069: if (head->num_clauses)
- 13: 8070: seq->array[1] = (Scheme_Object *)head;
- 218: 8071: else if (found_escapes && SCHEME_FALSEP(head->body)) {
- -: 8072: /* don't need the `#f` for the body, because some RHS escapes */
- #####: 8073: new_body = ensure_noncm(rhs);
- -: 8074: } else
- 218: 8075: seq->array[1] = head->body;
- -: 8076:
- 231: 8077: if (prev)
- 5: 8078: (void)replace_tail_inside(new_body, prev, NULL);
- -: 8079: else
- 226: 8080: form = new_body;
- 231: 8081: prev = new_body;
- -: 8082:
- 231: 8083: body = pre_body->body;
- -: 8084: } else
- -: 8085: break;
- -: 8086: }
- -: 8087:
- 138849: 8088: if (prev && SAME_TYPE(SCHEME_TYPE(prev), scheme_sequence_type))
- 226: 8089: form = optimize_sequence(form, info, context, 0);
- -: 8090: }
- -: 8091:
- 150127: 8092: return form;
- -: 8093:}
- -: 8094:
- -: 8095:/*========================================================================*/
- -: 8096:/* lambda */
- -: 8097:/*========================================================================*/
- -: 8098:
- -: 8099:static Scheme_Object *
- 73851: 8100:optimize_lambda(Scheme_Object *_lam, Optimize_Info *info, int context)
- -: 8101:{
- -: 8102: Scheme_Lambda *lam;
- -: 8103: Scheme_Object *code, *ctx;
- -: 8104: Scheme_IR_Lambda_Info *cl;
- -: 8105: int i, init_vclock, init_aclock, init_kclock, init_sclock;
- -: 8106: Scheme_Hash_Table *ht;
- 73851: 8107: int app_count = OPT_CONTEXT_APP_COUNT(context);
- -: 8108:
- 73851: 8109: lam = (Scheme_Lambda *)_lam;
- -: 8110:
- 73851: 8111: info->single_result = 1;
- 73851: 8112: info->preserves_marks = 1;
- -: 8113:
- 73851: 8114: info = optimize_info_add_frame(info, lam->num_params, lam->num_params,
- -: 8115: SCHEME_LAMBDA_FRAME);
- -: 8116:
- 73851: 8117: ht = scheme_make_hash_table(SCHEME_hash_ptr);
- 73851: 8118: info->uses = ht;
- -: 8119:
- 73851: 8120: init_vclock = info->vclock;
- 73851: 8121: init_aclock = info->aclock;
- 73851: 8122: init_kclock = info->kclock;
- 73851: 8123: init_sclock = info->sclock;
- -: 8124:
- 73851: 8125: info->vclock += 1; /* model delayed evaluation as vclock increment */
- 73851: 8126: info->kclock += 1;
- 73851: 8127: info->sclock += 1;
- -: 8128:
- -: 8129: /* For reporting warnings: */
- 73851: 8130: if (info->context && SCHEME_PAIRP(info->context))
- 47271: 8131: ctx = scheme_make_pair((Scheme_Object *)lam,
- 47271: 8132: SCHEME_CDR(info->context));
- 26580: 8133: else if (info->context)
- 20635: 8134: ctx = scheme_make_pair((Scheme_Object *)lam, info->context);
- -: 8135: else
- 5945: 8136: ctx = (Scheme_Object *)lam;
- 73851: 8137: info->context = ctx;
- -: 8138:
- 73851: 8139: cl = lam->ir_info;
- 186401: 8140: for (i = 0; i < lam->num_params; i++) {
- 112550: 8141: set_optimize_mode(cl->vars[i]);
- 112550: 8142: cl->vars[i]->optimize.lambda_depth = info->lambda_depth;
- 112550: 8143: cl->vars[i]->optimize_used = 0;
- 112550: 8144: cl->vars[i]->optimize.init_kclock = info->kclock;
- 112550: 8145: if (app_count
- 39873: 8146: && (app_count < SCHEME_USE_COUNT_INF)
- 38118: 8147: && cl->arg_types
- 26090: 8148: && cl->arg_types[i]
- 10267: 8149: && (cl->arg_type_contributors[i] == ((1 << app_count) - 1))) {
- -: 8150: /* All uses accounted for, so we can rely on type info */
- 3569: 8151: add_type(info, (Scheme_Object *)cl->vars[i], cl->arg_types[i]);
- -: 8152: }
- -: 8153: }
- -: 8154:
- 73851: 8155: code = scheme_optimize_expr(lam->body, info, 0);
- -: 8156:
- 73850: 8157: propagate_used_variables(info);
- -: 8158:
- 73850: 8159: if (info->single_result)
- 40355: 8160: SCHEME_LAMBDA_FLAGS(lam) |= LAMBDA_SINGLE_RESULT;
- 33495: 8161: else if (SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_SINGLE_RESULT)
- 5246: 8162: SCHEME_LAMBDA_FLAGS(lam) -= LAMBDA_SINGLE_RESULT;
- -: 8163:
- 73850: 8164: if (info->preserves_marks)
- 39682: 8165: SCHEME_LAMBDA_FLAGS(lam) |= LAMBDA_PRESERVES_MARKS;
- 34168: 8166: else if (SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_PRESERVES_MARKS)
- 5248: 8167: SCHEME_LAMBDA_FLAGS(lam) -= LAMBDA_PRESERVES_MARKS;
- -: 8168:
- 73850: 8169: if ((info->single_result > 0) && (info->preserves_marks > 0)
- 34445: 8170: && (SCHEME_LAMBDA_FLAGS(lam) & LAMBDA_RESULT_TENTATIVE))
- 5843: 8171: SCHEME_LAMBDA_FLAGS(lam) -= LAMBDA_RESULT_TENTATIVE;
- -: 8172:
- 73850: 8173: lam->body = code;
- -: 8174:
- -: 8175: /* Remembers positions of used vars (and unsets usage for this level) */
- 73850: 8176: cl->base_closure = info->uses;
- 73850: 8177: if (env_uses_toplevel(info))
- 35300: 8178: cl->has_tl = 1;
- -: 8179: else
- 38550: 8180: cl->has_tl = 0;
- 73850: 8181: cl->body_size = info->size;
- 73850: 8182: cl->body_psize = info->psize;
- 73850: 8183: cl->has_nonleaf = info->has_nonleaf;
- -: 8184:
- -: 8185: /* closure itself is not an effect */
- 73850: 8186: info->vclock = init_vclock;
- 73850: 8187: info->aclock = init_aclock;
- 73850: 8188: info->kclock = init_kclock;
- 73850: 8189: info->sclock = init_sclock;
- 73850: 8190: info->escapes = 0;
- -: 8191:
- 73850: 8192: info->size++;
- -: 8193:
- 147700: 8194: lam->closure_size = (cl->base_closure->count
- 73850: 8195: + (cl->has_tl ? 1 : 0));
- -: 8196:
- 73850: 8197: optimize_info_done(info, NULL);
- -: 8198:
- 73850: 8199: return (Scheme_Object *)lam;
- -: 8200:}
- -: 8201:
- 28569: 8202:static void merge_lambda_arg_types(Scheme_Lambda *lam1, Scheme_Lambda *lam2)
- -: 8203:{
- 28569: 8204: Scheme_IR_Lambda_Info *cl1 = lam1->ir_info;
- 28569: 8205: Scheme_IR_Lambda_Info *cl2 = lam2->ir_info;
- -: 8206: int i;
- -: 8207:
- 28569: 8208: if (!cl1->arg_types) {
- 980: 8209: if (cl2->arg_types) {
- 2: 8210: cl1->arg_types = cl2->arg_types;
- 2: 8211: cl1->arg_type_contributors = cl2->arg_type_contributors;
- -: 8212: }
- -: 8213: } else {
- 27589: 8214: if (cl2->arg_types) {
- 99047: 8215: for (i = lam1->num_params; i--; ) {
- 43869: 8216: if (!cl1->arg_type_contributors[i]) {
- 9216: 8217: cl1->arg_types[i] = cl2->arg_types[i];
- 9216: 8218: cl1->arg_type_contributors[i] = cl2->arg_type_contributors[i];
- 34653: 8219: } else if (cl2->arg_type_contributors[i]) {
- 34636: 8220: if (!cl2->arg_types[i])
- 22118: 8221: cl1->arg_types[i] = NULL;
- 12518: 8222: else if (predicate_implies(cl1->arg_types[i], cl2->arg_types[i]))
- 12511: 8223: cl1->arg_types[i] = cl2->arg_types[i];
- 7: 8224: else if (!predicate_implies(cl2->arg_types[i], cl1->arg_types[i])) {
- 7: 8225: cl1->arg_types[i] = NULL;
- 7: 8226: cl1->arg_type_contributors[i] |= (1 << (SCHEME_USE_COUNT_INF-1));
- -: 8227: }
- 34636: 8228: cl1->arg_type_contributors[i] |= cl2->arg_type_contributors[i];
- -: 8229: }
- -: 8230: }
- -: 8231: }
- -: 8232:
- 27589: 8233: cl2->arg_types = cl1->arg_types;
- 27589: 8234: cl2->arg_type_contributors = cl1->arg_type_contributors;
- -: 8235: }
- 28569: 8236:}
- -: 8237:
- #####: 8238:static void check_lambda_arg_types_registered(Scheme_Lambda *lam, int app_count)
- -: 8239:{
- #####: 8240: if (lam->ir_info->arg_types) {
- -: 8241: int i;
- #####: 8242: for (i = lam->num_params; i--; ) {
- #####: 8243: if (lam->ir_info->arg_types[i]) {
- #####: 8244: if ((lam->ir_info->arg_type_contributors[i] & (1 << (SCHEME_USE_COUNT_INF-1)))
- #####: 8245: || (lam->ir_info->arg_type_contributors[i] < ((1 << app_count) - 1))) {
- -: 8246: /* someone caller didn't weigh in with a type,
- -: 8247: of an anonymous caller had no type to record */
- #####: 8248: lam->ir_info->arg_types[i] = NULL;
- -: 8249: }
- -: 8250: }
- -: 8251: }
- -: 8252: }
- #####: 8253:}
- -: 8254:
- 270315: 8255:static Scheme_IR_Local *clone_variable(Scheme_IR_Local *var)
- -: 8256:{
- -: 8257: Scheme_IR_Local *var2;
- -: 8258: MZ_ASSERT(SAME_TYPE(var->so.type, scheme_ir_local_type));
- 270315: 8259: var2 = MALLOC_ONE_TAGGED(Scheme_IR_Local);
- 270315: 8260: memcpy(var2, var, sizeof(Scheme_IR_Local));
- 270315: 8261: return var2;
- -: 8262:}
- -: 8263:
- 182782: 8264:static Scheme_IR_Local **clone_variable_array(Scheme_IR_Local **vars,
- -: 8265: int sz,
- -: 8266: Scheme_Hash_Tree **_var_map)
- -: 8267:{
- -: 8268: Scheme_IR_Local **new_vars, *var;
- 182782: 8269: Scheme_Hash_Tree *var_map = *_var_map;
- -: 8270: int j;
- -: 8271:
- 182782: 8272: new_vars = MALLOC_N(Scheme_IR_Local*, sz);
- 635767: 8273: for (j = sz; j--; ) {
- 270203: 8274: var = clone_variable(vars[j]);
- 270203: 8275: var->mode = SCHEME_VAR_MODE_NONE;
- 270203: 8276: new_vars[j] = var;
- 270203: 8277: var_map = scheme_hash_tree_set(var_map, (Scheme_Object *)vars[j], (Scheme_Object *)new_vars[j]);
- -: 8278: }
- -: 8279:
- 182782: 8280: *_var_map = var_map;
- 182782: 8281: return new_vars;
- -: 8282:}
- -: 8283:
- 94077: 8284:static Scheme_Object *clone_lambda(int single_use, Scheme_Object *_lam, Optimize_Info *info, Scheme_Hash_Tree *var_map)
- -: 8285:{
- -: 8286: Scheme_Lambda *lam, *lam2;
- -: 8287: Scheme_Object *body, *var;
- -: 8288: Scheme_Hash_Table *ht;
- -: 8289: Scheme_IR_Lambda_Info *cl;
- -: 8290: Scheme_IR_Local **vars;
- -: 8291: int sz;
- -: 8292: Scheme_Object **arg_types;
- -: 8293: short *arg_type_contributors;
- -: 8294:
- 94077: 8295: lam = (Scheme_Lambda *)_lam;
- -: 8296:
- 94077: 8297: lam2 = MALLOC_ONE_TAGGED(Scheme_Lambda);
- 94077: 8298: memcpy(lam2, lam, sizeof(Scheme_Lambda));
- -: 8299:
- 94077: 8300: cl = MALLOC_ONE_RT(Scheme_IR_Lambda_Info);
- 94077: 8301: memcpy(cl, lam->ir_info, sizeof(Scheme_IR_Lambda_Info));
- 94077: 8302: lam2->ir_info = cl;
- -: 8303:
- 94077: 8304: vars = clone_variable_array(cl->vars, lam2->num_params, &var_map);
- 94077: 8305: cl->vars = vars;
- -: 8306:
- 94077: 8307: cl->is_dup |= !single_use;
- -: 8308:
- 94077: 8309: body = optimize_clone(single_use, lam->body, info, var_map, 0);
- 94077: 8310: if (!body) return NULL;
- -: 8311:
- 89641: 8312: lam2->body = body;
- -: 8313:
- 89641: 8314: if (cl->arg_types) {
- 32429: 8315: sz = lam2->num_params;
- 32429: 8316: arg_types = MALLOC_N(Scheme_Object*, sz);
- 32429: 8317: arg_type_contributors = MALLOC_N_ATOMIC(short, sz);
- 32429: 8318: memcpy(arg_types, cl->arg_types, sz * sizeof(Scheme_Object*));
- 32429: 8319: memcpy(arg_type_contributors, cl->arg_type_contributors, sz * sizeof(short));
- 32429: 8320: cl->arg_types = arg_types;
- 32429: 8321: cl->arg_type_contributors = arg_type_contributors;
- -: 8322: }
- -: 8323:
- 89641: 8324: if (cl->base_closure && var_map->count) {
- -: 8325: int i;
- 62763: 8326: ht = scheme_make_hash_table(SCHEME_hash_ptr);
- 439507: 8327: for (i = 0; i < cl->base_closure->size; i++) {
- 376744: 8328: if (cl->base_closure->vals[i]) {
- 118337: 8329: var = scheme_hash_tree_get(var_map, cl->base_closure->keys[i]);
- 203761: 8330: scheme_hash_set(ht,
- -: 8331: (var
- -: 8332: ? var
- 85424: 8333: : cl->base_closure->keys[i]),
- 118337: 8334: cl->base_closure->vals[i]);
- -: 8335: }
- -: 8336: }
- 62763: 8337: cl->base_closure = ht;
- -: 8338: }
- -: 8339:
- 89641: 8340: return (Scheme_Object *)lam2;
- -: 8341:}
- -: 8342:
- 210738: 8343:static int lambda_body_size_plus_info(Scheme_Lambda *lam, int check_assign,
- -: 8344: Optimize_Info *info, int *is_leaf)
- -: 8345:{
- -: 8346: int i;
- -: 8347: Scheme_IR_Lambda_Info *cl;
- -: 8348:
- 210738: 8349: cl = lam->ir_info;
- -: 8350:
- 210738: 8351: if (check_assign) {
- -: 8352: /* Don't try to inline if any arguments are mutated: */
- 756339: 8353: for (i = lam->num_params; i--; ) {
- 370397: 8354: if (cl->vars[i]->mutated)
- 26: 8355: return -1;
- -: 8356: }
- -: 8357: }
- -: 8358:
- 210712: 8359: if (is_leaf)
- 152461: 8360: *is_leaf = !cl->has_nonleaf;
- -: 8361:
- 210712: 8362: return cl->body_size + ((info && info->use_psize) ? cl->body_psize : 0);
- -: 8363:}
- -: 8364:
- #####: 8365:static int lambda_has_top_level(Scheme_Lambda *lam)
- -: 8366:{
- #####: 8367: return lam->ir_info->has_tl;
- -: 8368:}
- -: 8369:
- -: 8370:/*========================================================================*/
- -: 8371:/* modules */
- -: 8372:/*========================================================================*/
- -: 8373:
- 5535: 8374:static int set_code_closure_flags(Scheme_Object *clones,
- -: 8375: int set_flags, int mask_flags,
- -: 8376: int just_tentative)
- -: 8377:{
- -: 8378: Scheme_Object *clone, *orig, *first;
- 5535: 8379: int flags = LAMBDA_SINGLE_RESULT | LAMBDA_PRESERVES_MARKS;
- -: 8380:
- -: 8381: /* The first in a clone pair is the one that is consulted for
- -: 8382: references. The second one is the original, and its the one whose
- -: 8383: flags are updated by optimization. So consult the original, and set
- -: 8384: flags in both. */
- -: 8385:
- 25992: 8386: while (clones) {
- 14922: 8387: first = SCHEME_CAR(clones);
- 14922: 8388: clone = SCHEME_CAR(first);
- 14922: 8389: orig = SCHEME_CDR(first);
- -: 8390:
- 14922: 8391: flags = set_one_code_flags(orig, flags,
- -: 8392: orig, clone,
- -: 8393: set_flags, mask_flags, just_tentative,
- -: 8394: 0);
- -: 8395:
- 14922: 8396: clones = SCHEME_CDR(clones);
- -: 8397: }
- -: 8398:
- 5535: 8399: return flags;
- -: 8400:}
- -: 8401:
- 7151: 8402:static Scheme_Object *is_cross_module_inline_candidiate(Scheme_Object *e, Optimize_Info *info,
- -: 8403: int size_override)
- -: 8404:{
- 7151: 8405: if (SCHEME_LAMBDAP(e)) {
- 5222: 8406: if (size_override || (lambda_body_size(e, 1) < CROSS_MODULE_INLINE_SIZE))
- 1198: 8407: return optimize_clone(0, e, info, empty_eq_hash_tree, 0);
- -: 8408: }
- -: 8409:
- 5953: 8410: return NULL;
- -: 8411:}
- -: 8412:
- 8177: 8413:static int is_general_lambda(Scheme_Object *e, Optimize_Info *info)
- -: 8414:{
- -: 8415: /* recognize (begin <omitable>* <proc>) */
- 8177: 8416: if (SCHEME_TYPE(e) == scheme_sequence_type) {
- #####: 8417: Scheme_Sequence *seq = (Scheme_Sequence *)e;
- #####: 8418: if (seq->count > 0) {
- -: 8419: int i;
- #####: 8420: for (i = seq->count - 1; i--; ) {
- #####: 8421: if (!scheme_omittable_expr(seq->array[i], -1, 20, 0, info, NULL))
- #####: 8422: return 0;
- -: 8423: }
- -: 8424: }
- #####: 8425: e = seq->array[seq->count - 1];
- -: 8426: }
- -: 8427:
- -: 8428: /* recognize (let ([x <proc>]) x) */
- 8177: 8429: if (SCHEME_TYPE(e) == scheme_ir_let_header_type) {
- 1315: 8430: Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)e;
- 1315: 8431: if (!(SCHEME_LET_FLAGS(lh) & SCHEME_LET_RECURSIVE)
- 1314: 8432: && (lh->count == 1)
- 575: 8433: && (lh->num_clauses == 1)
- 575: 8434: && SAME_TYPE(SCHEME_TYPE(lh->body), scheme_ir_let_value_type)) {
- 575: 8435: Scheme_IR_Let_Value *lv = (Scheme_IR_Let_Value *)lh->body;
- 575: 8436: if (SCHEME_LAMBDAP(lv->value))
- 315: 8437: return SAME_OBJ(lv->body, (Scheme_Object *)lv->vars[0]);
- -: 8438: }
- -: 8439: }
- -: 8440:
- 7862: 8441: if (SCHEME_LAMBDAP(e))
- 4918: 8442: return 1;
- -: 8443:
- 2944: 8444: return 0;
- -: 8445:}
- -: 8446:
- 50: 8447:void install_definition(Scheme_Object *vec, int pos, Scheme_Object *var, Scheme_Object *rhs)
- -: 8448:{
- -: 8449: Scheme_Object *def;
- -: 8450:
- 50: 8451: var = scheme_make_pair(var, scheme_null);
- 50: 8452: def = scheme_make_vector(2, NULL);
- 50: 8453: SCHEME_VEC_ELS(def)[0] = var;
- 50: 8454: SCHEME_VEC_ELS(def)[1] = rhs;
- 50: 8455: def->type = scheme_define_values_type;
- -: 8456:
- 50: 8457: SCHEME_VEC_ELS(vec)[pos] = def;
- 50: 8458:}
- -: 8459:
- 1092: 8460:int split_define_values(Scheme_Object *e, int n, Scheme_Object *vars, Scheme_Object *vec, int offset)
- -: 8461:{
- 1729: 8462: if (SAME_TYPE(SCHEME_TYPE(e), scheme_ir_let_header_type)) {
- -: 8463: /* This is a tedious case to recognize the pattern
- -: 8464: (let ([x rhs] ...) (values x ...))
- -: 8465: which might be the result of expansion that involved a local
- -: 8466: macro to define the `x's */
- 653: 8467: Scheme_IR_Let_Header *lh = (Scheme_IR_Let_Header *)e;
- 653: 8468: if ((lh->count == n) && (lh->num_clauses == n)
- 16: 8469: && !(SCHEME_LET_FLAGS(lh) & SCHEME_LET_RECURSIVE)) {
- 16: 8470: Scheme_Object *body = lh->body;
- -: 8471: int i;
- 68: 8472: for (i = 0; i < n; i++) {
- 104: 8473: if (SAME_TYPE(SCHEME_TYPE(body), scheme_ir_let_value_type)) {
- 52: 8474: Scheme_IR_Let_Value *lv = (Scheme_IR_Let_Value *)body;
- 52: 8475: if (lv->count == 1) {
- 52: 8476: if (!scheme_omittable_expr(lv->value, 1, 5, 0, NULL, NULL))
- #####: 8477: return 0;
- 52: 8478: body = lv->body;
- -: 8479: } else
- #####: 8480: return 0;
- -: 8481: } else
- #####: 8482: return 0;
- -: 8483: }
- 16: 8484: if ((n == 2) && SAME_TYPE(SCHEME_TYPE(body), scheme_application3_type)) {
- 4: 8485: Scheme_App3_Rec *app = (Scheme_App3_Rec *)body;
- 4: 8486: Scheme_IR_Let_Value *lv = (Scheme_IR_Let_Value *)lh->body;
- 4: 8487: if (SAME_OBJ(app->rator, scheme_values_proc)
- 4: 8488: && SAME_OBJ(app->rand1, (Scheme_Object *)lv->vars[0])
- 4: 8489: && SAME_OBJ(app->rand2, (Scheme_Object *)((Scheme_IR_Let_Value *)lv->body)->vars[0])) {
- 4: 8490: if (vars) {
- 2: 8491: install_definition(vec, offset, SCHEME_CAR(vars), lv->value);
- 2: 8492: vars = SCHEME_CDR(vars);
- 2: 8493: lv = (Scheme_IR_Let_Value *)lv->body;
- 2: 8494: install_definition(vec, offset+1, SCHEME_CAR(vars), lv->value);
- -: 8495: }
- 4: 8496: return 1;
- -: 8497: }
- 12: 8498: } else if (SAME_TYPE(SCHEME_TYPE(body), scheme_application_type)
- 12: 8499: && ((Scheme_App_Rec *)body)->num_args == n) {
- 12: 8500: Scheme_App_Rec *app = (Scheme_App_Rec *)body;
- 12: 8501: Scheme_IR_Let_Value *lv = (Scheme_IR_Let_Value *)lh->body;
- 12: 8502: if (SAME_OBJ(app->args[0], scheme_values_proc)) {
- 56: 8503: for (i = 0; i < n; i++) {
- 44: 8504: if (!SAME_TYPE(SCHEME_TYPE(app->args[i+1]), scheme_ir_local_type)
- 44: 8505: || !SAME_OBJ((Scheme_Object *)lv->vars[0], app->args[i+1]))
- #####: 8506: return 0;
- 44: 8507: lv = (Scheme_IR_Let_Value *)lv->body;
- -: 8508: }
- 12: 8509: if (vars) {
- 6: 8510: body = lh->body;
- 28: 8511: for (i = 0; i < n; i++) {
- 22: 8512: Scheme_IR_Let_Value *lv2 = (Scheme_IR_Let_Value *)body;
- 22: 8513: install_definition(vec, offset+i, SCHEME_CAR(vars), lv2->value);
- 22: 8514: vars = SCHEME_CDR(vars);
- 22: 8515: body = lv2->body;
- -: 8516: }
- -: 8517: }
- 12: 8518: return 1;
- -: 8519: }
- -: 8520: }
- -: 8521: }
- 439: 8522: } else if ((n == 2) && SAME_TYPE(SCHEME_TYPE(e), scheme_application3_type)) {
- 4: 8523: Scheme_App3_Rec *app = (Scheme_App3_Rec *)e;
- 4: 8524: if (SAME_OBJ(app->rator, scheme_values_proc)
- 4: 8525: && scheme_omittable_expr(app->rand1, 1, 5, 0, NULL, NULL)
- 4: 8526: && scheme_omittable_expr(app->rand2, 1, 5, 0, NULL, NULL)) {
- 4: 8527: if (vars) {
- 2: 8528: install_definition(vec, offset, SCHEME_CAR(vars), app->rand1);
- 2: 8529: vars = SCHEME_CDR(vars);
- 2: 8530: install_definition(vec, offset+1, SCHEME_CAR(vars), app->rand2);
- -: 8531: }
- 4: 8532: return 1;
- -: 8533: }
- 435: 8534: } else if (SAME_TYPE(SCHEME_TYPE(e), scheme_application_type)
- 344: 8535: && ((Scheme_App_Rec *)e)->num_args == n) {
- 37: 8536: Scheme_App_Rec *app = (Scheme_App_Rec *)e;
- 37: 8537: if (SAME_OBJ(app->args[0], scheme_values_proc)) {
- -: 8538: int i;
- 52: 8539: for (i = 0; i < n; i++) {
- 40: 8540: if (!scheme_omittable_expr(app->args[i+1], 1, 5, 0, NULL, NULL))
- #####: 8541: return 0;
- -: 8542: }
- 12: 8543: if (vars) {
- 26: 8544: for (i = 0; i < n; i++) {
- 20: 8545: install_definition(vec, offset+i, SCHEME_CAR(vars), app->args[i+1]);
- 20: 8546: vars = SCHEME_CDR(vars);
- -: 8547: }
- -: 8548: }
- 12: 8549: return 1;
- -: 8550: }
- -: 8551: }
- -: 8552:
- 1060: 8553: return 0;
- -: 8554:}
- -: 8555:
- 2011: 8556:static Scheme_Hash_Table *set_as_fixed(Scheme_Hash_Table *fixed_table, Optimize_Info *info, int pos)
- -: 8557:{
- 2011: 8558: if (!fixed_table) {
- 397: 8559: fixed_table = scheme_make_hash_table(SCHEME_hash_ptr);
- 397: 8560: if (!info->top_level_consts) {
- -: 8561: Scheme_Hash_Table *consts;
- 181: 8562: consts = scheme_make_hash_table(SCHEME_hash_ptr);
- 181: 8563: info->top_level_consts = consts;
- -: 8564: }
- 397: 8565: scheme_hash_set(info->top_level_consts, scheme_false, (Scheme_Object *)fixed_table);
- -: 8566: }
- -: 8567:
- 2011: 8568: scheme_hash_set(fixed_table, scheme_make_integer(pos), scheme_true);
- -: 8569:
- 2011: 8570: return fixed_table;
- -: 8571:}
- -: 8572:
- -: 8573:static Scheme_Object *
- 3869: 8574:module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
- -: 8575:{
- 3869: 8576: Scheme_Module *m = (Scheme_Module *)data;
- -: 8577: Scheme_Object *e, *vars, *old_context;
- 3869: 8578: int start_simultaneous = 0, i_m, cnt;
- 3869: 8579: Scheme_Object *cl_first = NULL, *cl_last = NULL;
- 3869: 8580: Scheme_Hash_Table *consts = NULL, *fixed_table = NULL, *re_consts = NULL;
- 3869: 8581: Scheme_Hash_Table *originals = NULL;
- 3869: 8582: int cont, next_pos_ready = -1, inline_fuel, is_proc_def;
- -: 8583: Comp_Prefix *prev_cp;
- -: 8584: Optimize_Info *limited_info;
- -: 8585: Optimize_Info_Sequence info_seq;
- -: 8586:
- 3869: 8587: if (!m->comp_prefix) {
- -: 8588: /* already resolved */
- 1187: 8589: return (Scheme_Object *)m;
- -: 8590: }
- -: 8591:
- 2682: 8592: if (m->phaseless) {
- 5: 8593: scheme_log(info->logger,
- -: 8594: SCHEME_LOG_DEBUG,
- -: 8595: 0,
- -: 8596: "compilation of cross-phase persistent module: %D",
- -: 8597: m->modname);
- -: 8598: }
- -: 8599:
- 2682: 8600: old_context = info->context;
- 2682: 8601: info->context = (Scheme_Object *)m;
- -: 8602:
- 2682: 8603: optimize_info_seq_init(info, &info_seq);
- -: 8604:
- 2682: 8605: prev_cp = info->cp;
- 2682: 8606: info->cp = m->comp_prefix;
- -: 8607:
- -: 8608: /* Use `limited_info` for optimization decisions that need to be
- -: 8609: rediscovered by the validator. The validator knows shape
- -: 8610: information for imported variables, and it knows about structure
- -: 8611: bindings for later forms. */
- 2682: 8612: limited_info = MALLOC_ONE_RT(Optimize_Info);
- -: 8613:#ifdef MZTAG_REQUIRED
- -: 8614: limited_info->type = scheme_rt_optimize_info;
- -: 8615:#endif
- 2682: 8616: limited_info->cp = info->cp;
- -: 8617:
- 2682: 8618: cnt = SCHEME_VEC_SIZE(m->bodies[0]);
- -: 8619:
- -: 8620: /* First, flatten `(define-values (x ...) (values e ...))'
- -: 8621: to `(define (x) e) ...' when possible. */
- -: 8622: {
- 2682: 8623: int inc = 0;
- 12525: 8624: for (i_m = 0; i_m < cnt; i_m++) {
- 9843: 8625: e = SCHEME_VEC_ELS(m->bodies[0])[i_m];
- 9843: 8626: if (SAME_TYPE(SCHEME_TYPE(e), scheme_define_values_type)) {
- -: 8627: int n;
- 8143: 8628: vars = SCHEME_VEC_ELS(e)[0];
- 8143: 8629: n = scheme_list_length(vars);
- 8143: 8630: if (n > 1) {
- 1072: 8631: e = SCHEME_VEC_ELS(e)[1];
- 1072: 8632: if (split_define_values(e, n, NULL, NULL, 0))
- 16: 8633: inc += (n - 1);
- -: 8634: }
- -: 8635: }
- -: 8636: }
- -: 8637:
- 2682: 8638: if (inc > 0) {
- -: 8639: Scheme_Object *new_vec;
- 16: 8640: int j = 0;
- 16: 8641: new_vec = scheme_make_vector(cnt+inc, NULL);
- 132: 8642: for (i_m = 0; i_m < cnt; i_m++) {
- 116: 8643: e = SCHEME_VEC_ELS(m->bodies[0])[i_m];
- 232: 8644: if (SAME_TYPE(SCHEME_TYPE(e), scheme_define_values_type)) {
- -: 8645: int n;
- 116: 8646: vars = SCHEME_VEC_ELS(e)[0];
- 116: 8647: n = scheme_list_length(vars);
- 116: 8648: if (n > 1) {
- 20: 8649: if (split_define_values(SCHEME_VEC_ELS(e)[1], n, vars, new_vec, j)) {
- 16: 8650: j += n;
- -: 8651: } else
- 4: 8652: SCHEME_VEC_ELS(new_vec)[j++] = e;
- -: 8653: } else
- 96: 8654: SCHEME_VEC_ELS(new_vec)[j++] = e;
- -: 8655: } else
- #####: 8656: SCHEME_VEC_ELS(new_vec)[j++] = e;
- -: 8657: }
- 16: 8658: cnt += inc;
- 16: 8659: m->bodies[0] = new_vec;
- -: 8660: }
- -: 8661: }
- -: 8662:
- -: 8663: if (OPT_ESTIMATE_FUTURE_SIZES) {
- 2682: 8664: if (info->enforce_const) {
- -: 8665: /* For each identifier bound to a procedure, register an initial
- -: 8666: size estimate, which is used to discourage early loop unrolling
- -: 8667: at the expense of later inlining. */
- 12559: 8668: for (i_m = 0; i_m < cnt; i_m++) {
- 9877: 8669: e = SCHEME_VEC_ELS(m->bodies[0])[i_m];
- 9877: 8670: if (SAME_TYPE(SCHEME_TYPE(e), scheme_define_values_type)) {
- -: 8671: int n;
- -: 8672:
- 8177: 8673: vars = SCHEME_VEC_ELS(e)[0];
- 8177: 8674: e = SCHEME_VEC_ELS(e)[1];
- -: 8675:
- 8177: 8676: n = scheme_list_length(vars);
- 8177: 8677: if ((n == 1) && SCHEME_LAMBDAP(e)) {
- -: 8678: Scheme_Toplevel *tl;
- -: 8679:
- 4918: 8680: tl = (Scheme_Toplevel *)SCHEME_CAR(vars);
- -: 8681:
- 4918: 8682: if (!(SCHEME_TOPLEVEL_FLAGS(tl) & SCHEME_TOPLEVEL_MUTATED)) {
- -: 8683: int pos;
- 4918: 8684: if (!consts)
- 1007: 8685: consts = scheme_make_hash_table(SCHEME_hash_ptr);
- 4918: 8686: pos = tl->position;
- 9836: 8687: scheme_hash_set(consts,
- 4918: 8688: scheme_make_integer(pos),
- -: 8689: estimate_closure_size(e));
- -: 8690: }
- -: 8691: }
- -: 8692: }
- -: 8693: }
- -: 8694:
- 2682: 8695: if (consts) {
- 1007: 8696: info->top_level_consts = consts;
- 1007: 8697: consts = NULL;
- -: 8698: }
- -: 8699: }
- -: 8700: }
- -: 8701:
- 12559: 8702: for (i_m = 0; i_m < cnt; i_m++) {
- -: 8703: /* Optimize this expression: */
- 9877: 8704: e = SCHEME_VEC_ELS(m->bodies[0])[i_m];
- -: 8705:
- 9877: 8706: is_proc_def = 0;
- 9877: 8707: if (OPT_DISCOURAGE_EARLY_INLINE && info->enforce_const) {
- 9877: 8708: if (SAME_TYPE(SCHEME_TYPE(e), scheme_define_values_type)) {
- -: 8709: Scheme_Object *e2;
- 8177: 8710: e2 = SCHEME_VEC_ELS(e)[1];
- 8177: 8711: if (is_general_lambda(e2, info))
- 5047: 8712: is_proc_def = 1;
- -: 8713: }
- -: 8714: }
- -: 8715:
- 9877: 8716: if (is_proc_def && OPT_DISCOURAGE_EARLY_INLINE) {
- 5047: 8717: info->use_psize = 1;
- 5047: 8718: inline_fuel = info->inline_fuel;
- 5047: 8719: if (inline_fuel > 2)
- 5047: 8720: info->inline_fuel = 2;
- -: 8721: } else
- 4830: 8722: inline_fuel = 0;
- 9877: 8723: optimize_info_seq_step(info, &info_seq);
- 9877: 8724: e = scheme_optimize_expr(e, info, 0);
- 9877: 8725: if (is_proc_def && OPT_DISCOURAGE_EARLY_INLINE) {
- 5047: 8726: info->use_psize = 0;
- 5047: 8727: info->inline_fuel = inline_fuel;
- -: 8728: }
- 9877: 8729: SCHEME_VEC_ELS(m->bodies[0])[i_m] = e;
- -: 8730:
- 9877: 8731: if (info->enforce_const) {
- -: 8732: /* If this expression/definition can't have any side effect
- -: 8733: (including raising an exception), then continue the group of
- -: 8734: simultaneous definitions: */
- 18054: 8735: if (SAME_TYPE(SCHEME_TYPE(e), scheme_define_values_type)) {
- 8177: 8736: int n, cnst = 0, sproc = 0, sprop = 0, has_guard = 0;
- 8177: 8737: Scheme_Object *sstruct = NULL, *parent_identity = NULL;
- -: 8738: Simple_Stuct_Type_Info stinfo;
- -: 8739:
- 8177: 8740: vars = SCHEME_VEC_ELS(e)[0];
- 8177: 8741: e = SCHEME_VEC_ELS(e)[1];
- -: 8742:
- 8177: 8743: n = scheme_list_length(vars);
- 8177: 8744: cont = scheme_omittable_expr(e, n, -1,
- -: 8745: /* ignore APPN_FLAG_OMITTABLE, because the
- -: 8746: validator won't be able to reconstruct it
- -: 8747: in general; also, don't recognize struct-type
- -: 8748: functions, since they weren't recognized
- -: 8749: as immediate calls */
- -: 8750: (OMITTABLE_IGNORE_APPN_OMIT
- -: 8751: | OMITTABLE_IGNORE_MAKE_STRUCT_TYPE),
- -: 8752: /* similarly, use `limited_info` instead of `info'
- -: 8753: here, because the decision
- -: 8754: of omittable should not depend on
- -: 8755: information that's only available at
- -: 8756: optimization time: */
- -: 8757: limited_info,
- -: 8758: info);
- -: 8759:
- 8177: 8760: if (n == 1) {
- 7121: 8761: if (scheme_ir_propagate_ok(e, info))
- 5403: 8762: cnst = 1;
- 1718: 8763: else if (scheme_is_statically_proc(e, info, OMITTABLE_IGNORE_APPN_OMIT)) {
- 286: 8764: cnst = 1;
- 286: 8765: sproc = 1;
- -: 8766: }
- 1056: 8767: } else if (scheme_is_simple_make_struct_type(e, n, 0, NULL,
- -: 8768: &stinfo, &parent_identity,
- -: 8769: info->top_level_consts,
- 1056: 8770: info->cp->inline_variants,
- -: 8771: NULL, NULL, 0, NULL, NULL,
- -: 8772: &sstruct,
- -: 8773: 5)) {
- 532: 8774: sstruct = scheme_make_pair(sstruct, parent_identity);
- 532: 8775: cnst = 1;
- 524: 8776: } else if (scheme_is_simple_make_struct_type_property(e, n, 0,
- -: 8777: &has_guard,
- -: 8778: info->top_level_consts,
- 524: 8779: info->cp->inline_variants,
- -: 8780: NULL, NULL, 0, NULL, NULL,
- -: 8781: 5)) {
- 79: 8782: sprop = 1;
- 79: 8783: cnst = 1;
- -: 8784: } else
- 445: 8785: sstruct = NULL;
- -: 8786:
- 8177: 8787: if ((sstruct || sprop) && !cont) {
- -: 8788: /* Since the `make-struct-type` or `make-struct-tye-property` form is immediate
- -: 8789: enough that the validator can see it, re-check whether we can continue
- -: 8790: a group of simultaneously defined variables. */
- 611: 8791: cont = scheme_omittable_expr(e, n, 5, OMITTABLE_IGNORE_APPN_OMIT, limited_info, NULL);
- -: 8792: }
- -: 8793:
- 8177: 8794: if (cnst) {
- -: 8795: Scheme_Toplevel *tl;
- -: 8796: int i;
- 14946: 8797: for (i = 0; i < n; i++) {
- 8646: 8798: tl = (Scheme_Toplevel *)SCHEME_CAR(vars);
- 8646: 8799: vars = SCHEME_CDR(vars);
- -: 8800:
- 8646: 8801: if (!(SCHEME_TOPLEVEL_FLAGS(tl) & SCHEME_TOPLEVEL_MUTATED)) {
- -: 8802: Scheme_Object *e2;
- -: 8803:
- 8572: 8804: if (sstruct) {
- 2720: 8805: e2 = scheme_make_struct_proc_shape(scheme_get_struct_proc_shape(i, &stinfo),
- -: 8806: sstruct);
- 5852: 8807: } else if (sprop) {
- 237: 8808: e2 = scheme_make_struct_property_proc_shape(scheme_get_struct_property_proc_shape(i, has_guard));
- 5615: 8809: } else if (sproc) {
- 286: 8810: e2 = scheme_make_noninline_proc(e);
- 5329: 8811: } else if (SCHEME_LAMBDAP(e)) {
- 4974: 8812: e2 = optimize_clone(1, e, info, empty_eq_hash_tree, 0);
- 9948: 8813: if (e2) {
- -: 8814: Scheme_Object *pr;
- 4974: 8815: pr = scheme_make_raw_pair(scheme_make_raw_pair(e2, e), NULL);
- 4974: 8816: if (cl_last)
- 3585: 8817: SCHEME_CDR(cl_last) = pr;
- -: 8818: else
- 1389: 8819: cl_first = pr;
- 4974: 8820: cl_last = pr;
- -: 8821: } else
- #####: 8822: e2 = scheme_make_noninline_proc(e);
- -: 8823: } else {
- 355: 8824: e2 = e;
- -: 8825: }
- -: 8826:
- 8572: 8827: if (e2) {
- -: 8828: int pos;
- 8572: 8829: pos = tl->position;
- -: 8830:
- 8572: 8831: consts = info->top_level_consts;
- 8572: 8832: if (!consts) {
- 157: 8833: consts = scheme_make_hash_table(SCHEME_hash_ptr);
- 157: 8834: info->top_level_consts = consts;
- -: 8835: }
- 8572: 8836: scheme_hash_set(consts, scheme_make_integer(pos), e2);
- -: 8837:
- 8572: 8838: if (sstruct || sprop) {
- -: 8839: /* include in `limited_info` */
- 2957: 8840: Scheme_Hash_Table *limited_consts = limited_info->top_level_consts;
- 2957: 8841: if (!limited_consts) {
- 207: 8842: limited_consts = scheme_make_hash_table(SCHEME_hash_ptr);
- 207: 8843: limited_info->top_level_consts = limited_consts;
- -: 8844: }
- 2957: 8845: scheme_hash_set(limited_consts, scheme_make_integer(pos), e2);
- -: 8846: }
- -: 8847:
- 8572: 8848: if (sstruct || (SCHEME_TYPE(e2) > _scheme_ir_values_types_)) {
- -: 8849: /* No use re-optimizing */
- -: 8850: } else {
- 4990: 8851: if (!re_consts)
- 1392: 8852: re_consts = scheme_make_hash_table(SCHEME_hash_ptr);
- 4990: 8853: scheme_hash_set(re_consts, scheme_make_integer(i_m),
- 4990: 8854: scheme_make_integer(pos));
- -: 8855: }
- -: 8856: } else {
- -: 8857: /* At least mark it as fixed */
- #####: 8858: fixed_table = set_as_fixed(fixed_table, info, tl->position);
- -: 8859: }
- -: 8860: }
- -: 8861: }
- -: 8862: } else {
- -: 8863: /* The binding is not inlinable/propagatable, but unless it's
- -: 8864: set!ed, it is constant after evaluating the definition. We
- -: 8865: map the top-level position to indicate constantness --- immediately
- -: 8866: if `cont`, and later if not. */
- -: 8867: Scheme_Object *l, *a;
- -: 8868: int pos;
- -: 8869:
- 4846: 8870: for (l = vars; !SCHEME_NULLP(l); l = SCHEME_CDR(l)) {
- 2969: 8871: a = SCHEME_CAR(l);
- -: 8872:
- -: 8873: /* Test for set!: */
- 2969: 8874: if (!(SCHEME_TOPLEVEL_FLAGS(a) & SCHEME_TOPLEVEL_MUTATED)) {
- 2952: 8875: pos = SCHEME_TOPLEVEL_POS(a);
- -: 8876:
- 2952: 8877: if (cont)
- 459: 8878: fixed_table = set_as_fixed(fixed_table, info, pos);
- -: 8879: else
- 2493: 8880: next_pos_ready = pos;
- -: 8881: }
- -: 8882: }
- -: 8883: }
- -: 8884: } else {
- 1700: 8885: cont = scheme_omittable_expr(e, -1, -1, 0, NULL, NULL);
- -: 8886: }
- 9877: 8887: if (i_m + 1 == cnt)
- 2562: 8888: cont = 0;
- -: 8889: } else
- #####: 8890: cont = 1;
- -: 8891:
- 9877: 8892: if (!cont) {
- 4588: 8893: Scheme_Object *prop_later = NULL;
- -: 8894: /* If we have new constants, re-optimize to inline: */
- 4588: 8895: if (consts) {
- -: 8896: int flags;
- -: 8897:
- -: 8898: /* Same as in letrec: assume LAMBDA_SINGLE_RESULT and
- -: 8899: LAMBDA_PRESERVES_MARKS for all, but then assume not for all
- -: 8900: if any turn out not (i.e., approximate fix point). */
- 1845: 8901: (void)set_code_closure_flags(cl_first,
- -: 8902: LAMBDA_SINGLE_RESULT | LAMBDA_PRESERVES_MARKS | LAMBDA_RESULT_TENTATIVE,
- -: 8903: 0xFFFF,
- -: 8904: 0);
- -: 8905:
- -: 8906: while (1) {
- -: 8907: /* Re-optimize this expression. */
- -: 8908: int old_sz, new_sz;
- -: 8909:
- 7110: 8910: e = SCHEME_VEC_ELS(m->bodies[0])[start_simultaneous];
- -: 8911:
- -: 8912: if (OPT_DELAY_GROUP_PROPAGATE || OPT_LIMIT_FUNCTION_RESIZE) {
- -: 8913: if (SAME_TYPE(SCHEME_TYPE(e), scheme_define_values_type)) {
- -: 8914: Scheme_Object *sub_e;
- -: 8915: sub_e = SCHEME_VEC_ELS(e)[1];
- -: 8916: old_sz = lambda_body_size(sub_e, 0);
- -: 8917: } else
- -: 8918: old_sz = 0;
- -: 8919: } else
- 7110: 8920: old_sz = 0;
- -: 8921:
- 7110: 8922: optimize_info_seq_step(info, &info_seq);
- 7110: 8923: e = scheme_optimize_expr(e, info, 0);
- 7110: 8924: SCHEME_VEC_ELS(m->bodies[0])[start_simultaneous] = e;
- -: 8925:
- 7110: 8926: if (re_consts) {
- -: 8927: /* Install optimized closures into constant table ---
- -: 8928: unless, maybe, they grow too much: */
- -: 8929: Scheme_Object *rpos;
- 6293: 8930: rpos = scheme_hash_get(re_consts, scheme_make_integer(start_simultaneous));
- 6293: 8931: if (rpos) {
- -: 8932: Scheme_Object *old_e;
- -: 8933:
- 4990: 8934: e = SCHEME_VEC_ELS(e)[1];
- -: 8935:
- 4990: 8936: old_e = scheme_hash_get(info->top_level_consts, rpos);
- 4990: 8937: if (old_e && SCHEME_LAMBDAP(old_e) && OPT_PRE_OPTIMIZE_FOR_CROSS_MODULE(1)) {
- 4974: 8938: if (!originals)
- 1025: 8939: originals = scheme_make_hash_table(SCHEME_hash_ptr);
- 4974: 8940: scheme_hash_set(originals, scheme_make_integer(start_simultaneous), old_e);
- -: 8941: }
- -: 8942:
- 4990: 8943: if (!scheme_ir_propagate_ok(e, info)
- 520: 8944: && scheme_is_statically_proc(e, info, 0)) {
- -: 8945: /* If we previously installed a procedure for inlining,
- -: 8946: don't replace that with a worse approximation. */
- 520: 8947: if (SCHEME_LAMBDAP(old_e))
- 520: 8948: e = NULL;
- -: 8949: else
- #####: 8950: e = scheme_make_noninline_proc(e);
- -: 8951: }
- -: 8952:
- 4990: 8953: if (e) {
- -: 8954: if (OPT_DELAY_GROUP_PROPAGATE || OPT_LIMIT_FUNCTION_RESIZE)
- -: 8955: new_sz = lambda_body_size(e, 0);
- -: 8956: else
- 4470: 8957: new_sz = 0;
- -: 8958:
- -: 8959: if (!old_sz
- -: 8960: || (new_sz <= old_sz)
- -: 8961: || (!OPT_DELAY_GROUP_PROPAGATE && !OPT_LIMIT_FUNCTION_RESIZE))
- 4470: 8962: scheme_hash_set(info->top_level_consts, rpos, e);
- -: 8963: else if (!OPT_LIMIT_FUNCTION_RESIZE
- -: 8964: || (new_sz < 4 * old_sz))
- -: 8965: prop_later = scheme_make_raw_pair(scheme_make_pair(rpos, e), prop_later);
- -: 8966: }
- -: 8967: }
- -: 8968: }
- -: 8969:
- 7110: 8970: if (start_simultaneous == i_m)
- 1845: 8971: break;
- 5265: 8972: start_simultaneous++;
- 5265: 8973: }
- -: 8974:
- 1845: 8975: flags = set_code_closure_flags(cl_first, 0, 0xFFFF, 0);
- 1845: 8976: (void)set_code_closure_flags(cl_first,
- -: 8977: (flags & (LAMBDA_SINGLE_RESULT | LAMBDA_PRESERVES_MARKS)),
- -: 8978: ~(LAMBDA_SINGLE_RESULT | LAMBDA_PRESERVES_MARKS | LAMBDA_RESULT_TENTATIVE),
- -: 8979: 1);
- -: 8980: }
- -: 8981:
- 4588: 8982: cl_last = cl_first = NULL;
- 4588: 8983: consts = NULL;
- 4588: 8984: re_consts = NULL;
- 4588: 8985: start_simultaneous = i_m + 1;
- -: 8986:
- 9176: 8987: while (prop_later) {
- #####: 8988: e = SCHEME_CAR(prop_later);
- #####: 8989: scheme_hash_set(info->top_level_consts, SCHEME_CAR(e), SCHEME_CDR(e));
- #####: 8990: prop_later = SCHEME_CDR(prop_later);
- -: 8991: }
- -: 8992: }
- -: 8993:
- 9877: 8994: if (next_pos_ready > -1) {
- 1552: 8995: fixed_table = set_as_fixed(fixed_table, info, next_pos_ready);
- 1552: 8996: next_pos_ready = -1;
- -: 8997: }
- -: 8998: }
- -: 8999:
- -: 9000: /* For functions that are potentially inlineable, perhaps
- -: 9001: before optimization, insert inline_variant records: */
- 2682: 9002: if (info->enforce_const) {
- 12559: 9003: for (i_m = 0; i_m < cnt; i_m++) {
- -: 9004: /* Optimize this expression: */
- 9877: 9005: e = SCHEME_VEC_ELS(m->bodies[0])[i_m];
- 9877: 9006: if (SAME_TYPE(SCHEME_TYPE(e), scheme_define_values_type)) {
- -: 9007: int size_override;
- 8177: 9008: size_override = SCHEME_IMMUTABLEP(e);
- 8177: 9009: vars = SCHEME_VEC_ELS(e)[0];
- 8177: 9010: if (SCHEME_PAIRP(vars) && SCHEME_NULLP(SCHEME_CDR(vars))) {
- -: 9011: Scheme_Object *sub_e, *alt_e;
- 7121: 9012: sub_e = SCHEME_VEC_ELS(e)[1];
- 7121: 9013: alt_e = is_cross_module_inline_candidiate(sub_e, info, 0);
- 7121: 9014: if (!alt_e && originals && OPT_PRE_OPTIMIZE_FOR_CROSS_MODULE(size_override)) {
- 30: 9015: alt_e = scheme_hash_get(originals, scheme_make_integer(i_m));
- 30: 9016: if (SAME_OBJ(alt_e, sub_e) && !size_override)
- #####: 9017: alt_e = NULL;
- 30: 9018: else if (alt_e)
- 30: 9019: alt_e = is_cross_module_inline_candidiate(alt_e, info, size_override);
- -: 9020: }
- 7121: 9021: if (alt_e) {
- -: 9022: Scheme_Object *iv;
- 1194: 9023: iv = scheme_make_vector(3, scheme_false);
- 1194: 9024: iv->type = scheme_inline_variant_type;
- 1194: 9025: SCHEME_VEC_ELS(iv)[0] = sub_e;
- 1194: 9026: SCHEME_VEC_ELS(iv)[1] = alt_e;
- 1194: 9027: SCHEME_VEC_ELS(e)[1] = iv;
- -: 9028: }
- -: 9029: }
- -: 9030: }
- -: 9031: }
- -: 9032: }
- -: 9033:
- -: 9034: /* Check one more time for expressions that we can omit: */
- -: 9035: {
- 2682: 9036: int can_omit = 0;
- 12559: 9037: for (i_m = 0; i_m < cnt; i_m++) {
- -: 9038: /* Optimize this expression: */
- 9877: 9039: e = SCHEME_VEC_ELS(m->bodies[0])[i_m];
- 9877: 9040: if (scheme_omittable_expr(e, -1, -1, 0, info, NULL)) {
- #####: 9041: can_omit++;
- -: 9042: }
- -: 9043: }
- 2682: 9044: if (can_omit) {
- -: 9045: Scheme_Object *vec;
- #####: 9046: int j = 0;
- #####: 9047: vec = scheme_make_vector(cnt - can_omit, NULL);
- #####: 9048: for (i_m = 0; i_m < cnt; i_m++) {
- -: 9049: /* Optimize this expression: */
- #####: 9050: e = SCHEME_VEC_ELS(m->bodies[0])[i_m];
- #####: 9051: if (!scheme_omittable_expr(e, -1, -1, 0, info, NULL)) {
- #####: 9052: SCHEME_VEC_ELS(vec)[j++] = e;
- -: 9053: }
- -: 9054: }
- #####: 9055: m->bodies[0] = vec;
- -: 9056: }
- 2682: 9057: cnt -= can_omit;
- -: 9058: }
- -: 9059:
- 2682: 9060: info->context = old_context;
- 2682: 9061: info->cp = prev_cp;
- -: 9062:
- -: 9063: /* Exp-time body was optimized during compilation */
- -: 9064:
- -: 9065: {
- -: 9066: /* optimize submodules */
- -: 9067: int k;
- -: 9068: Scheme_Object *p;
- 8046: 9069: for (k = 0; k < 2; k++) {
- 5364: 9070: p = (k ? m->post_submodules : m->pre_submodules);
- 5364: 9071: if (p) {
- 3483: 9072: while (!SCHEME_NULLP(p)) {
- 1187: 9073: optimize_info_seq_step(info, &info_seq);
- 1187: 9074: scheme_optimize_expr(SCHEME_CAR(p), info, 0);
- 1187: 9075: p = SCHEME_CDR(p);
- -: 9076: }
- -: 9077: }
- -: 9078: }
- -: 9079: }
- -: 9080:
- 2682: 9081: optimize_info_seq_done(info, &info_seq);
- -: 9082:
- 2682: 9083: info->escapes = 0;
- -: 9084:
- 2682: 9085: return data;
- -: 9086:}
- -: 9087:
- -: 9088:static Scheme_Object *
- 49: 9089:top_level_require_optimize(Scheme_Object *data, Optimize_Info *info, int context)
- -: 9090:{
- 49: 9091: return data;
- -: 9092:}
- -: 9093:
- -: 9094:/*========================================================================*/
- -: 9095:/* expressions */
- -: 9096:/*========================================================================*/
- -: 9097:
- #####: 9098:static Scheme_Object *optimize_k(void)
- -: 9099:{
- #####: 9100: Scheme_Thread *p = scheme_current_thread;
- #####: 9101: Scheme_Object *expr = (Scheme_Object *)p->ku.k.p1;
- #####: 9102: Optimize_Info *info = (Optimize_Info *)p->ku.k.p2;
- #####: 9103: int context = p->ku.k.i1;
- -: 9104:
- #####: 9105: p->ku.k.p1 = NULL;
- #####: 9106: p->ku.k.p2 = NULL;
- -: 9107:
- #####: 9108: return scheme_optimize_expr(expr, info, context);
- -: 9109:}
- -: 9110:
- 4231544: 9111:Scheme_Object *scheme_optimize_expr(Scheme_Object *expr, Optimize_Info *info, int context)
- -: 9112:{
- 4231544: 9113: Scheme_Type type = SCHEME_TYPE(expr);
- -: 9114:
- -: 9115:#ifdef DO_STACK_CHECK
- -: 9116:# include "mzstkchk.h"
- -: 9117: {
- #####: 9118: Scheme_Thread *p = scheme_current_thread;
- -: 9119:
- #####: 9120: p->ku.k.p1 = (void *)expr;
- #####: 9121: p->ku.k.p2 = (void *)info;
- #####: 9122: p->ku.k.i1 = context;
- -: 9123:
- #####: 9124: return scheme_handle_stack_overflow(optimize_k);
- -: 9125: }
- -: 9126:#endif
- -: 9127:
- 4231544: 9128: info->preserves_marks = 1;
- 4231544: 9129: info->single_result = 1;
- 4231544: 9130: info->escapes = 0;
- -: 9131:
- 4231544: 9132: switch (type) {
- -: 9133: case scheme_ir_local_type:
- -: 9134: {
- -: 9135: Scheme_Object *val;
- -: 9136:
- 1238842: 9137: info->size += 1;
- -: 9138:
- 1238842: 9139: if (SCHEME_VAR(expr)->mutated) {
- 3853: 9140: info->vclock += 1;
- 3853: 9141: register_use(SCHEME_VAR(expr), info);
- 3853: 9142: return expr;
- -: 9143: }
- -: 9144:
- 1234989: 9145: val = optimize_info_propagate_local(expr);
- 1234989: 9146: if (val) {
- 180164: 9147: info->size -= 1;
- 180164: 9148: return scheme_optimize_expr(val, info, context);
- -: 9149: }
- -: 9150:
- 1054825: 9151: val = collapse_local(expr, info, context);
- 1054825: 9152: if (val)
- 1481: 9153: return val;
- -: 9154:
- 1053344: 9155: if (!(context & OPT_CONTEXT_NO_SINGLE)) {
- 1053344: 9156: val = SCHEME_VAR(expr)->optimize.known_val;
- -: 9157:
- 1053344: 9158: if (val && SAME_TYPE(SCHEME_TYPE(val), scheme_once_used_type)) {
- 80997: 9159: Scheme_Once_Used *o = (Scheme_Once_Used *)val;
- -: 9160:
- -: 9161: MZ_ASSERT(!o->moved);
- -: 9162: MZ_ASSERT(!SCHEME_VAR(expr)->optimize_outside_binding);
- -: 9163:
- -: 9164: /* In case this variable was tentatively used before: */
- 80997: 9165: SCHEME_VAR(expr)->optimize_used = 0;
- -: 9166:
- 80997: 9167: if (((o->vclock == info->vclock)
- 15168: 9168: && ((o->aclock == info->aclock)
- 163: 9169: || !o->spans_k)
- 15091: 9170: && ((context & OPT_CONTEXT_SINGLED)
- 36: 9171: || single_valued_noncm_expression(o->expr, 5)))
- 197724: 9172: || movable_expression(o->expr, info,
- 65908: 9173: o->var->optimize.lambda_depth != info->lambda_depth,
- 65908: 9174: o->kclock != info->kclock,
- 65908: 9175: o->sclock != info->sclock,
- -: 9176: 0, 5)) {
- 37002: 9177: int save_fuel = info->inline_fuel, save_no_types = info->no_types;
- -: 9178: int save_vclock, save_aclock, save_kclock, save_sclock;
- 37002: 9179: info->size -= 1;
- 37002: 9180: info->inline_fuel = 0; /* no more inlining; o->expr was already optimized */
- 37002: 9181: info->no_types = 1; /* cannot used inferred types, in case `val' inferred them */
- 37002: 9182: save_vclock = info->vclock; /* allowed to move => no change to clocks */
- 37002: 9183: save_aclock = info->aclock;
- 37002: 9184: save_kclock = info->kclock;
- 37002: 9185: save_sclock = info->sclock;
- -: 9186:
- 37002: 9187: o->moved = 1;
- -: 9188:
- 37002: 9189: val = scheme_optimize_expr(o->expr, info, context);
- -: 9190:
- 37002: 9191: if (info->maybe_values_argument) {
- -: 9192: /* Although `val` could be counted as taking 0 time, we advance
- -: 9193: the clock conservatively to be consistent with `values`
- -: 9194: splitting. */
- 3668: 9195: advance_clocks_for_optimized(val,
- -: 9196: &save_vclock, &save_aclock, &save_kclock, &save_sclock,
- -: 9197: info,
- -: 9198: ADVANCE_CLOCKS_INIT_FUEL);
- -: 9199: }
- -: 9200:
- 37002: 9201: info->inline_fuel = save_fuel;
- 37002: 9202: info->no_types = save_no_types;
- 37002: 9203: info->vclock = save_vclock;
- 37002: 9204: info->aclock = save_aclock;
- 37002: 9205: info->kclock = save_kclock;
- 37002: 9206: info->sclock = save_sclock;
- 37002: 9207: return val;
- -: 9208: }
- -: 9209: }
- -: 9210: }
- -: 9211:
- -: 9212: /* If everything fails, mark it as used. */
- 1016342: 9213: if (OPT_CONTEXT_TYPE(context))
- 722: 9214: SCHEME_VAR(expr)->arg_type = OPT_CONTEXT_TYPE(context);
- 1016342: 9215: if (info->kclock > SCHEME_VAR(expr)->optimize.init_kclock)
- 539988: 9216: SCHEME_VAR(expr)->escapes_after_k_tick = 1;
- 1016342: 9217: register_use(SCHEME_VAR(expr), info);
- 1016342: 9218: return expr;
- -: 9219: }
- -: 9220: case scheme_application_type:
- 157486: 9221: return optimize_application(expr, info, context);
- -: 9222: case scheme_application2_type:
- 534493: 9223: return optimize_application2(expr, info, context);
- -: 9224: case scheme_application3_type:
- 293662: 9225: return optimize_application3(expr, info, context);
- -: 9226: case scheme_sequence_type:
- -: 9227: case scheme_splice_sequence_type:
- 30988: 9228: return optimize_sequence(expr, info, context, 1);
- -: 9229: case scheme_branch_type:
- 245190: 9230: return optimize_branch(expr, info, context);
- -: 9231: case scheme_with_cont_mark_type:
- 3345: 9232: return optimize_wcm(expr, info, context);
- -: 9233: case scheme_ir_lambda_type:
- 73877: 9234: if (context & OPT_CONTEXT_BOOLEAN)
- 26: 9235: return scheme_true;
- -: 9236: else
- 73851: 9237: return optimize_lambda(expr, info, context);
- -: 9238: case scheme_ir_let_header_type:
- 186491: 9239: return optimize_lets(expr, info, context);
- -: 9240: case scheme_ir_toplevel_type:
- 214827: 9241: info->size += 1;
- 214827: 9242: if (info->top_level_consts) {
- -: 9243: int pos;
- -: 9244: Scheme_Object *c;
- -: 9245:
- -: 9246: while (1) {
- 95852: 9247: pos = SCHEME_TOPLEVEL_POS(expr);
- 95852: 9248: c = scheme_hash_get(info->top_level_consts, scheme_make_integer(pos));
- 95852: 9249: c = no_potential_size(c);
- 95852: 9250: if (c && SAME_TYPE(SCHEME_TYPE(c), scheme_ir_toplevel_type))
- 25: 9251: expr = c;
- -: 9252: else
- -: 9253: break;
- 25: 9254: }
- -: 9255:
- 95827: 9256: if (c) {
- 23175: 9257: if (context & OPT_CONTEXT_BOOLEAN)
- 20: 9258: return (SCHEME_FALSEP(c) ? scheme_false : scheme_true);
- -: 9259:
- 23155: 9260: if (scheme_ir_duplicate_ok(c, 0))
- 361: 9261: return c;
- -: 9262:
- -: 9263: /* We can't inline, but mark the top level as a constant,
- -: 9264: so we can direct-jump and avoid null checks in JITed code: */
- 22794: 9265: expr = scheme_toplevel_to_flagged_toplevel(expr, SCHEME_TOPLEVEL_CONST);
- -: 9266: } else {
- -: 9267: /* false is mapped to a table of non-constant ready values: */
- 72652: 9268: c = scheme_hash_get(info->top_level_consts, scheme_false);
- 72652: 9269: if (c) {
- 50015: 9270: c = scheme_hash_get((Scheme_Hash_Table *)c, scheme_make_integer(pos));
- -: 9271:
- 50015: 9272: if (c) {
- -: 9273: /* We can't inline, but mark the top level as ready and fixed,
- -: 9274: so we can avoid null checks in JITed code, etc: */
- 7129: 9275: expr = scheme_toplevel_to_flagged_toplevel(expr, SCHEME_TOPLEVEL_FIXED);
- -: 9276: }
- -: 9277: }
- 72652: 9278: if (!c)
- 65523: 9279: info->vclock += 1;
- -: 9280: }
- -: 9281: } else {
- 119000: 9282: info->vclock += 1;
- -: 9283: }
- 214446: 9284: optimize_info_used_top(info);
- 214446: 9285: return expr;
- -: 9286: case scheme_ir_quote_syntax_type:
- 75984: 9287: if (context & OPT_CONTEXT_BOOLEAN)
- #####: 9288: return scheme_true;
- -: 9289: else {
- 75984: 9290: info->size += 1;
- 75984: 9291: optimize_info_used_top(info);
- -: 9292: }
- 75984: 9293: return expr;
- -: 9294: case scheme_variable_type:
- -: 9295: case scheme_module_variable_type:
- #####: 9296: scheme_signal_error("got top-level in wrong place");
- #####: 9297: return 0;
- -: 9298: case scheme_define_values_type:
- 15830: 9299: return define_values_optimize(expr, info, context);
- -: 9300: case scheme_varref_form_type:
- 1049: 9301: return ref_optimize(expr, info, context);
- -: 9302: case scheme_set_bang_type:
- 2793: 9303: return set_optimize(expr, info, context);
- -: 9304: case scheme_define_syntaxes_type:
- 7: 9305: return define_syntaxes_optimize(expr, info, context);
- -: 9306: case scheme_begin_for_syntax_type:
- #####: 9307: return begin_for_syntax_optimize(expr, info, context);
- -: 9308: case scheme_case_lambda_sequence_type:
- 2026: 9309: if (context & OPT_CONTEXT_BOOLEAN)
- #####: 9310: return scheme_true;
- -: 9311: else
- 2026: 9312: return case_lambda_optimize(expr, info, context);
- -: 9313: case scheme_begin0_sequence_type:
- 370: 9314: return begin0_optimize(expr, info, context);
- -: 9315: case scheme_apply_values_type:
- 726: 9316: return apply_values_optimize(expr, info, context);
- -: 9317: case scheme_with_immed_mark_type:
- 267: 9318: return with_immed_mark_optimize(expr, info, context);
- -: 9319: case scheme_require_form_type:
- 49: 9320: return top_level_require_optimize(expr, info, context);
- -: 9321: case scheme_module_type:
- 3869: 9322: return module_optimize(expr, info, context);
- -: 9323: default:
- 1149373: 9324: info->size += 1;
- 1149373: 9325: if ((context & OPT_CONTEXT_BOOLEAN)
- 46310: 9326: && (SCHEME_TYPE(expr) > _scheme_ir_values_types_)
- 46310: 9327: && SCHEME_TRUEP(expr))
- 17000: 9328: return scheme_true;
- -: 9329: else
- 1132373: 9330: return expr;
- -: 9331: }
- -: 9332:}
- -: 9333:
- 178588: 9334:static void increment_use_count(Scheme_IR_Local *var, int as_rator)
- -: 9335:{
- 178588: 9336: if (var->use_count < SCHEME_USE_COUNT_INF)
- 98224: 9337: var->use_count++;
- 178588: 9338: if (!as_rator && (var->non_app_count < SCHEME_USE_COUNT_INF))
- 80412: 9339: var->non_app_count++;
- -: 9340:
- 178588: 9341: if (var->optimize.known_val
- 30943: 9342: && SAME_TYPE(SCHEME_TYPE(var->optimize.known_val), scheme_once_used_type))
- 5346: 9343: var->optimize.known_val = NULL;
- 178588: 9344:}
- -: 9345:
- 2251610: 9346:Scheme_Object *optimize_clone(int single_use, Scheme_Object *expr, Optimize_Info *info, Scheme_Hash_Tree *var_map, int as_rator)
- -: 9347:/* If single_use is 1, then the old copy will be dropped --- so it's ok to "duplicate"
- -: 9348: any constant, and local-variable use counts should not be incremented. */
- -: 9349:{
- -: 9350: int t;
- -: 9351:
- 2251610: 9352: t = SCHEME_TYPE(expr);
- -: 9353:
- 2251610: 9354: switch(t) {
- -: 9355: case scheme_ir_local_type:
- -: 9356: {
- -: 9357: Scheme_Object *v;
- 689965: 9358: v = scheme_hash_tree_get(var_map, expr);
- 689965: 9359: if (v)
- 562944: 9360: return v;
- 127021: 9361: else if (!single_use)
- 71766: 9362: increment_use_count(SCHEME_VAR(expr), as_rator);
- 127021: 9363: return expr;
- -: 9364: }
- -: 9365: case scheme_application2_type:
- -: 9366: {
- 309887: 9367: Scheme_App2_Rec *app = (Scheme_App2_Rec *)expr, *app2;
- -: 9368:
- 309887: 9369: app2 = MALLOC_ONE_TAGGED(Scheme_App2_Rec);
- 309887: 9370: app2->iso.so.type = scheme_application2_type;
- -: 9371:
- 309887: 9372: expr = optimize_clone(single_use, app->rator, info, var_map, 1);
- 309887: 9373: if (!expr) return NULL;
- 309879: 9374: app2->rator = expr;
- -: 9375:
- 309879: 9376: expr = optimize_clone(single_use, app->rand, info, var_map, 0);
- 309879: 9377: if (!expr) return NULL;
- 309617: 9378: app2->rand = expr;
- -: 9379:
- 309617: 9380: SCHEME_APPN_FLAGS(app2) |= (SCHEME_APPN_FLAGS(app) & APPN_FLAG_MASK);
- 309617: 9381: if (single_use)
- 116478: 9382: SCHEME_APPN_FLAGS(app2) |= (SCHEME_APPN_FLAGS(app) & APPN_POSITION_MASK);
- -: 9383:
- 309617: 9384: return (Scheme_Object *)app2;
- -: 9385: }
- -: 9386: case scheme_application_type:
- -: 9387: {
- 77325: 9388: Scheme_App_Rec *app = (Scheme_App_Rec *)expr, *app2;
- -: 9389: int i;
- -: 9390:
- 77325: 9391: app2 = scheme_malloc_application(app->num_args + 1);
- -: 9392:
- 472734: 9393: for (i = app->num_args + 1; i--; ) {
- 321450: 9394: expr = optimize_clone(single_use, app->args[i], info, var_map, !i);
- 321450: 9395: if (!expr) return NULL;
- 318084: 9396: app2->args[i] = expr;
- -: 9397: }
- -: 9398:
- 73959: 9399: SCHEME_APPN_FLAGS(app2) |= (SCHEME_APPN_FLAGS(app) & APPN_FLAG_MASK);
- 73959: 9400: if (single_use)
- 29086: 9401: SCHEME_APPN_FLAGS(app2) |= (SCHEME_APPN_FLAGS(app) & APPN_POSITION_MASK);
- -: 9402:
- 73959: 9403: return (Scheme_Object *)app2;
- -: 9404: }
- -: 9405: case scheme_application3_type:
- -: 9406: {
- 161123: 9407: Scheme_App3_Rec *app = (Scheme_App3_Rec *)expr, *app2;
- -: 9408:
- 161123: 9409: app2 = MALLOC_ONE_TAGGED(Scheme_App3_Rec);
- 161123: 9410: app2->iso.so.type = scheme_application3_type;
- -: 9411:
- 161123: 9412: expr = optimize_clone(single_use, app->rator, info, var_map, 1);
- 161123: 9413: if (!expr) return NULL;
- 161123: 9414: app2->rator = expr;
- -: 9415:
- 161123: 9416: expr = optimize_clone(single_use, app->rand1, info, var_map, 0);
- 161123: 9417: if (!expr) return NULL;
- 159951: 9418: app2->rand1 = expr;
- -: 9419:
- 159951: 9420: expr = optimize_clone(single_use, app->rand2, info, var_map, 0);
- 159951: 9421: if (!expr) return NULL;
- 158139: 9422: app2->rand2 = expr;
- -: 9423:
- 158139: 9424: SCHEME_APPN_FLAGS(app2) |= (SCHEME_APPN_FLAGS(app) & APPN_FLAG_MASK);
- 158139: 9425: if (single_use)
- 56091: 9426: SCHEME_APPN_FLAGS(app2) |= (SCHEME_APPN_FLAGS(app) & APPN_POSITION_MASK);
- -: 9427:
- 158139: 9428: return (Scheme_Object *)app2;
- -: 9429: }
- -: 9430: case scheme_ir_let_header_type:
- -: 9431: {
- 75826: 9432: Scheme_IR_Let_Header *head = (Scheme_IR_Let_Header *)expr, *head2;
- -: 9433: Scheme_Object *body;
- 75826: 9434: Scheme_IR_Let_Value *lv, *lv2, *prev = NULL;
- -: 9435: Scheme_IR_Local **vars;
- -: 9436: int i;
- -: 9437:
- 75826: 9438: head2 = MALLOC_ONE_TAGGED(Scheme_IR_Let_Header);
- 75826: 9439: head2->iso.so.type = scheme_ir_let_header_type;
- 75826: 9440: head2->count = head->count;
- 75826: 9441: head2->num_clauses = head->num_clauses;
- 75826: 9442: SCHEME_LET_FLAGS(head2) = SCHEME_LET_FLAGS(head);
- -: 9443:
- -: 9444: /* Build let-value change: */
- 75826: 9445: body = head->body;
- 240357: 9446: for (i = head->num_clauses; i--; ) {
- 88705: 9447: lv = (Scheme_IR_Let_Value *)body;
- -: 9448:
- 88705: 9449: vars = clone_variable_array(lv->vars, lv->count, &var_map);
- -: 9450:
- 88705: 9451: lv2 = MALLOC_ONE_TAGGED(Scheme_IR_Let_Value);
- 88705: 9452: SCHEME_IRLV_FLAGS(lv2) |= (SCHEME_IRLV_FLAGS(lv) & 0x1);
- 88705: 9453: lv2->iso.so.type = scheme_ir_let_value_type;
- 88705: 9454: lv2->count = lv->count;
- 88705: 9455: lv2->vars = vars;
- 88705: 9456: lv2->value = lv->value;
- -: 9457:
- 88705: 9458: if (prev)
- 12879: 9459: prev->body = (Scheme_Object *)lv2;
- -: 9460: else
- 75826: 9461: head2->body = (Scheme_Object *)lv2;
- 88705: 9462: prev = lv2;
- -: 9463:
- 88705: 9464: body = lv->body;
- -: 9465: }
- 75826: 9466: if (prev)
- 75826: 9467: prev->body = body;
- -: 9468: else
- #####: 9469: head2->body = body;
- -: 9470:
- 75826: 9471: body = head2->body;
- 239325: 9472: for (i = head->num_clauses; i--; ) {
- 88475: 9473: lv2 = (Scheme_IR_Let_Value *)body;
- -: 9474:
- 88475: 9475: expr = optimize_clone(single_use, lv2->value, info, var_map, 0);
- 88475: 9476: if (!expr) return NULL;
- 87673: 9477: lv2->value = expr;
- -: 9478:
- 87673: 9479: body = lv2->body;
- -: 9480: }
- -: 9481:
- 75024: 9482: expr = optimize_clone(single_use, body, info, var_map, 0);
- 75024: 9483: if (!expr) return NULL;
- -: 9484:
- 70298: 9485: if (prev)
- 70298: 9486: prev->body = expr;
- -: 9487: else
- #####: 9488: head2->body = expr;
- -: 9489:
- 70298: 9490: return (Scheme_Object *)head2;
- -: 9491: }
- -: 9492: case scheme_sequence_type:
- -: 9493: case scheme_begin0_sequence_type:
- -: 9494: case scheme_splice_sequence_type:
- -: 9495: {
- 20028: 9496: Scheme_Sequence *seq = (Scheme_Sequence *)expr, *seq2;
- -: 9497: int i;
- -: 9498:
- 20028: 9499: seq2 = scheme_malloc_sequence(seq->count);
- 20028: 9500: seq2->so.type = seq->so.type;
- 20028: 9501: seq2->count = seq->count;
- -: 9502:
- 87056: 9503: for (i = seq->count; i--; ) {
- 48516: 9504: expr = optimize_clone(single_use, seq->array[i], info, var_map, 0);
- 48516: 9505: if (!expr) return NULL;
- 47000: 9506: seq2->array[i] = expr;
- -: 9507: }
- -: 9508:
- 18512: 9509: return (Scheme_Object *)seq2;
- -: 9510: }
- -: 9511: case scheme_branch_type:
- -: 9512: {
- 145958: 9513: Scheme_Branch_Rec *b = (Scheme_Branch_Rec *)expr, *b2;
- -: 9514:
- 145958: 9515: b2 = MALLOC_ONE_TAGGED(Scheme_Branch_Rec);
- 145958: 9516: b2->so.type = scheme_branch_type;
- -: 9517:
- 145958: 9518: expr = optimize_clone(single_use, b->test, info, var_map, 0);
- 145958: 9519: if (!expr) return NULL;
- 145102: 9520: b2->test = expr;
- -: 9521:
- 145102: 9522: expr = optimize_clone(single_use, b->tbranch, info, var_map, 0);
- 145102: 9523: if (!expr) return NULL;
- 143862: 9524: b2->tbranch = expr;
- -: 9525:
- 143862: 9526: expr = optimize_clone(single_use, b->fbranch, info, var_map, 0);
- 143862: 9527: if (!expr) return NULL;
- 142820: 9528: b2->fbranch = expr;
- -: 9529:
- 142820: 9530: return (Scheme_Object *)b2;
- -: 9531: }
- -: 9532: case scheme_with_cont_mark_type:
- -: 9533: {
- 1578: 9534: Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)expr, *wcm2;
- -: 9535:
- 1578: 9536: wcm2 = MALLOC_ONE_TAGGED(Scheme_With_Continuation_Mark);
- 1578: 9537: wcm2->so.type = scheme_with_cont_mark_type;
- -: 9538:
- 1578: 9539: expr = optimize_clone(single_use, wcm->key, info, var_map, 0);
- 1578: 9540: if (!expr) return NULL;
- 1578: 9541: wcm2->key = expr;
- -: 9542:
- 1578: 9543: expr = optimize_clone(single_use, wcm->val, info, var_map, 0);
- 1578: 9544: if (!expr) return NULL;
- 1486: 9545: wcm2->val = expr;
- -: 9546:
- 1486: 9547: expr = optimize_clone(single_use, wcm->body, info, var_map, 0);
- 1486: 9548: if (!expr) return NULL;
- 1422: 9549: wcm2->body = expr;
- -: 9550:
- 1422: 9551: return (Scheme_Object *)wcm2;
- -: 9552: }
- -: 9553: case scheme_ir_lambda_type:
- 94077: 9554: return clone_lambda(single_use, expr, info, var_map);
- -: 9555: case scheme_ir_toplevel_type:
- -: 9556: case scheme_ir_quote_syntax_type:
- 88007: 9557: return expr;
- -: 9558: case scheme_define_values_type:
- -: 9559: case scheme_define_syntaxes_type:
- -: 9560: case scheme_begin_for_syntax_type:
- -: 9561: case scheme_boxenv_type:
- #####: 9562: return NULL;
- -: 9563: case scheme_require_form_type:
- #####: 9564: return NULL;
- -: 9565: case scheme_varref_form_type:
- 150: 9566: return ref_clone(single_use, expr, info, var_map);
- -: 9567: case scheme_set_bang_type:
- 1696: 9568: return set_clone(single_use, expr, info, var_map);
- -: 9569: case scheme_apply_values_type:
- 340: 9570: return apply_values_clone(single_use, expr, info, var_map);
- -: 9571: case scheme_with_immed_mark_type:
- 112: 9572: return with_immed_mark_clone(single_use, expr, info, var_map);
- -: 9573: case scheme_case_lambda_sequence_type:
- 764: 9574: return case_lambda_clone(single_use, expr, info, var_map);
- -: 9575: case scheme_module_type:
- #####: 9576: return NULL;
- -: 9577: default:
- 584774: 9578: if (t > _scheme_ir_values_types_) {
- 584774: 9579: if (single_use || scheme_ir_duplicate_ok(expr, 0))
- 580788: 9580: return expr;
- -: 9581: }
- -: 9582: }
- -: 9583:
- 3986: 9584: return NULL;
- -: 9585:}
- -: 9586:
- -: 9587:/*========================================================================*/
- -: 9588:/* compile-time env for optimization */
- -: 9589:/*========================================================================*/
- -: 9590:
- 1312722: 9591:Optimize_Info *scheme_optimize_info_create(Comp_Prefix *cp, Scheme_Env *env, Scheme_Object *insp, int get_logger)
- -: 9592:{
- -: 9593: Optimize_Info *info;
- -: 9594:
- 1312722: 9595: info = MALLOC_ONE_RT(Optimize_Info);
- -: 9596:#ifdef MZTAG_REQUIRED
- -: 9597: info->type = scheme_rt_optimize_info;
- -: 9598:#endif
- 1312722: 9599: info->inline_fuel = INITIAL_INLINING_FUEL;
- 1312722: 9600: info->flatten_fuel = INITIAL_FLATTENING_FUEL;
- 1312722: 9601: info->cp = cp;
- 1312722: 9602: info->env = env;
- 1312722: 9603: info->insp = insp;
- -: 9604:
- 1312722: 9605: if (get_logger) {
- -: 9606: Scheme_Logger *logger;
- 29632: 9607: logger = (Scheme_Logger *)scheme_get_param(scheme_current_config(), MZCONFIG_LOGGER);
- 29632: 9608: logger = scheme_make_logger(logger, scheme_intern_symbol("optimizer"));
- 29632: 9609: info->logger = logger;
- -: 9610: }
- -: 9611:
- 1312722: 9612: return info;
- -: 9613:}
- -: 9614:
- 1458446: 9615:static void optimize_info_seq_init(Optimize_Info *info, Optimize_Info_Sequence *info_seq)
- -: 9616:{
- 1458446: 9617: info_seq->init_flatten_fuel = info->flatten_fuel;
- 1458446: 9618: info_seq->min_flatten_fuel = info->flatten_fuel;
- 1458446: 9619:}
- -: 9620:
- 2594801: 9621:static void optimize_info_seq_step(Optimize_Info *info, Optimize_Info_Sequence *info_seq)
- -: 9622:{
- 2594801: 9623: if (info->flatten_fuel < info_seq->min_flatten_fuel)
- 498: 9624: info_seq->min_flatten_fuel = info->flatten_fuel;
- 2594801: 9625: info->flatten_fuel = info_seq->init_flatten_fuel;
- 2594801: 9626:}
- -: 9627:
- 1460625: 9628:static void optimize_info_seq_done(Optimize_Info *info, Optimize_Info_Sequence *info_seq)
- -: 9629:{
- 1460625: 9630: if (info->flatten_fuel > info_seq->min_flatten_fuel)
- 458: 9631: info->flatten_fuel = info_seq->min_flatten_fuel;
- 1460625: 9632:}
- -: 9633:
- 9343: 9634:void scheme_optimize_info_enforce_const(Optimize_Info *oi, int enforce_const)
- -: 9635:{
- 9343: 9636: oi->enforce_const = enforce_const;
- 9343: 9637:}
- -: 9638:
- 2930: 9639:void scheme_optimize_info_set_context(Optimize_Info *oi, Scheme_Object *ctx)
- -: 9640:{
- 2930: 9641: oi->context = ctx;
- 2930: 9642:}
- -: 9643:
- 20: 9644:void scheme_optimize_info_never_inline(Optimize_Info *oi)
- -: 9645:{
- 20: 9646: oi->inline_fuel = -1;
- 20: 9647:}
- -: 9648:
- 73850: 9649:static void propagate_used_variables(Optimize_Info *info)
- -: 9650:{
- -: 9651: Scheme_Hash_Table *ht;
- -: 9652: Scheme_IR_Local *tvar;
- -: 9653: int j;
- -: 9654:
- 73850: 9655: if (info->next->uses) {
- 47931: 9656: ht = info->uses;
- 430707: 9657: for (j = 0; j < ht->size; j++) {
- 382776: 9658: if (ht->vals[j]) {
- 127329: 9659: tvar = SCHEME_VAR(ht->keys[j]);
- 127329: 9660: if (tvar->optimize.lambda_depth < info->next->lambda_depth)
- 41663: 9661: scheme_hash_set(info->next->uses, (Scheme_Object *)tvar, scheme_true);
- -: 9662: }
- -: 9663: }
- -: 9664: }
- 73850: 9665:}
- -: 9666:
- 73850: 9667:static int env_uses_toplevel(Optimize_Info *frame)
- -: 9668:{
- -: 9669: int used;
- -: 9670:
- 73850: 9671: used = frame->used_toplevel;
- -: 9672:
- 73850: 9673: if (used) {
- -: 9674: /* Propagate use to an enclosing lambda, if any: */
- 35300: 9675: frame = frame->next;
- 290094: 9676: while (frame) {
- 238606: 9677: if (frame->flags & SCHEME_LAMBDA_FRAME) {
- 19112: 9678: frame->used_toplevel = 1;
- 19112: 9679: break;
- -: 9680: }
- 219494: 9681: frame = frame->next;
- -: 9682: }
- -: 9683: }
- -: 9684:
- 73850: 9685: return used;
- -: 9686:}
- -: 9687:
- 307602: 9688:static void optimize_info_used_top(Optimize_Info *info)
- -: 9689:{
- 2863609: 9690: while (info) {
- 2454005: 9691: if (info->flags & SCHEME_LAMBDA_FRAME) {
- 205600: 9692: info->used_toplevel = 1;
- 205600: 9693: break;
- -: 9694: }
- 2248405: 9695: info = info->next;
- -: 9696: }
- 307602: 9697:}
- -: 9698:
- 72621: 9699:static Scheme_Once_Used *make_once_used(Scheme_Object *val, Scheme_IR_Local *var,
- -: 9700: int vclock, int aclock, int kclock, int sclock, int spans_k)
- -: 9701:{
- -: 9702: Scheme_Once_Used *o;
- -: 9703:
- 72621: 9704: o = MALLOC_ONE_TAGGED(Scheme_Once_Used);
- 72621: 9705: o->so.type = scheme_once_used_type;
- -: 9706:
- 72621: 9707: o->expr = val;
- 72621: 9708: o->var = var;
- 72621: 9709: o->vclock = vclock;
- 72621: 9710: o->aclock = aclock;
- 72621: 9711: o->kclock = kclock;
- 72621: 9712: o->sclock = sclock;
- 72621: 9713: o->spans_k = spans_k;
- -: 9714:
- 72621: 9715: return o;
- -: 9716:}
- -: 9717:
- 11335: 9718:static int optimize_any_uses(Optimize_Info *info, Scheme_IR_Let_Value *at_irlv, int n)
- -: 9719:{
- -: 9720: int i, j;
- 11335: 9721: Scheme_IR_Let_Value *irlv = at_irlv;
- -: 9722:
- 23056: 9723: while (n--) {
- 23692: 9724: for (i = irlv->count; i--; ) {
- 11654: 9725: if (irlv->vars[i]->optimize_used)
- 10: 9726: return 1;
- 23684: 9727: for (j = at_irlv->count; j--; ) {
- 11652: 9728: if (at_irlv->vars[j]->optimize.transitive_uses) {
- 11537: 9729: if (scheme_hash_get(at_irlv->vars[j]->optimize.transitive_uses,
- 11537: 9730: (Scheme_Object *)irlv->vars[i]))
- 11256: 9731: return 1;
- -: 9732: }
- -: 9733: }
- -: 9734: }
- 386: 9735: irlv = (Scheme_IR_Let_Value *)irlv->body;
- -: 9736: }
- -: 9737:
- 69: 9738: return 0;
- -: 9739:}
- -: 9740:
- 36: 9741:static void optimize_uses_of_mutable_imply_early_alloc(Scheme_IR_Let_Value *at_irlv, int n)
- -: 9742:{
- -: 9743: int i, j;
- 36: 9744: Scheme_IR_Let_Value *irlv = at_irlv;
- -: 9745:
- -: 9746: /* We we're reinterpreting a `letrec` as `let*`, and when it realy
- -: 9747: must be `let*` instead of `let`, and when a mutable variable is
- -: 9748: involved, then we need to tell the `resolve` pass that the
- -: 9749: mutable varaiable's value must be boxed immediately, instead of
- -: 9750: delaying to the body of the `let*`. */
- -: 9751:
- 101: 9752: while (n--) {
- 87: 9753: for (i = irlv->count; i--; ) {
- 29: 9754: if (irlv->vars[i]->mutated) {
- #####: 9755: int used = 0;
- #####: 9756: if (irlv->vars[i]->optimize_used)
- #####: 9757: used = 1;
- -: 9758: else {
- #####: 9759: for (j = at_irlv->count; j--; ) {
- #####: 9760: if (at_irlv->vars[j]->optimize.transitive_uses) {
- #####: 9761: if (scheme_hash_get(at_irlv->vars[j]->optimize.transitive_uses,
- #####: 9762: (Scheme_Object *)irlv->vars[i]))
- #####: 9763: used = 1;
- -: 9764: }
- -: 9765: }
- -: 9766: }
- #####: 9767: if (used)
- #####: 9768: irlv->vars[i]->must_allocate_immediately = 1;
- -: 9769: }
- -: 9770: }
- 29: 9771: irlv = (Scheme_IR_Let_Value *)irlv->body;
- -: 9772: }
- 36: 9773:}
- -: 9774:
- 1054414: 9775:static void register_use(Scheme_IR_Local *var, Optimize_Info *info)
- -: 9776:{
- -: 9777: MZ_ASSERT(SCHEME_VAR(var)->mode == SCHEME_VAR_MODE_OPTIMIZE);
- -: 9778: MZ_ASSERT(SCHEME_VAR(var)->use_count);
- -: 9779:
- 1054414: 9780: if (var->optimize.lambda_depth < info->lambda_depth)
- 222578: 9781: scheme_hash_set(info->uses, (Scheme_Object *)var, scheme_true);
- -: 9782:
- 1054414: 9783: if (!var->optimize_used) {
- 342577: 9784: var->optimize_used = 1;
- -: 9785:
- 342577: 9786: if (info->transitive_use_var
- 404070: 9787: && (var->optimize.lambda_depth
- 202035: 9788: <= info->transitive_use_var->optimize.lambda_depth)) {
- 34811: 9789: Scheme_Hash_Table *ht = info->transitive_use_var->optimize.transitive_uses;
- -: 9790:
- 34811: 9791: if (!ht) {
- 15196: 9792: ht = scheme_make_hash_table(SCHEME_hash_ptr);
- 15196: 9793: info->transitive_use_var->optimize.transitive_uses = ht;
- -: 9794: }
- 34811: 9795: scheme_hash_set(ht, (Scheme_Object *)var, scheme_true);
- -: 9796: }
- -: 9797: }
- 1054414: 9798:}
- -: 9799:
- 14196: 9800:static void register_transitive_uses(Scheme_IR_Local *var, Optimize_Info *info)
- -: 9801:{
- -: 9802: Scheme_Hash_Table *ht;
- -: 9803: Scheme_IR_Local *tvar;
- -: 9804: int j;
- -: 9805:
- 14196: 9806: ht = var->optimize.transitive_uses;
- -: 9807:
- 139468: 9808: for (j = 0; j < ht->size; j++) {
- 125272: 9809: if (ht->vals[j]) {
- 31729: 9810: tvar = SCHEME_VAR(ht->keys[j]);
- 31729: 9811: register_use(tvar, info);
- -: 9812: }
- -: 9813: }
- 14196: 9814:}
- -: 9815:
- 112117: 9816:static Scheme_Object *optimize_info_lookup(Scheme_Object *var)
- -: 9817:{
- -: 9818: MZ_ASSERT(SCHEME_VAR(var)->mode == SCHEME_VAR_MODE_OPTIMIZE);
- -: 9819: MZ_ASSERT(SCHEME_VAR(var)->use_count);
- -: 9820:
- 112117: 9821: return SCHEME_VAR(var)->optimize.known_val;
- -: 9822:}
- -: 9823:
- 1234989: 9824:static Scheme_Object *optimize_info_propagate_local(Scheme_Object *var)
- -: 9825:{
- 1234989: 9826: Scheme_Object *last, *val = var;
- -: 9827:
- 1234989: 9828: last = val; /* Avoid compiler warning */
- -: 9829:
- 3838050: 9830: while (val && SAME_TYPE(SCHEME_TYPE(val), scheme_ir_local_type)) {
- -: 9831: MZ_ASSERT(SCHEME_VAR(val)->mode == SCHEME_VAR_MODE_OPTIMIZE);
- -: 9832: MZ_ASSERT(SCHEME_VAR(val)->use_count);
- 1368072: 9833: last = val;
- 1368072: 9834: val = SCHEME_VAR(val)->optimize.known_val;
- -: 9835: }
- -: 9836:
- 1234989: 9837: if (!val
- 200819: 9838: || SCHEME_WILL_BE_LAMBDAP(val)
- 185157: 9839: || SCHEME_LAMBDAP(val)
- 139271: 9840: || SAME_TYPE(SCHEME_TYPE(val), scheme_once_used_type)) {
- 1187908: 9841: if (SAME_OBJ(last, var))
- 1054825: 9842: return NULL;
- -: 9843:
- 133083: 9844: if (SCHEME_VAR(var)->use_count != 1)
- 106801: 9845: increment_use_count(SCHEME_VAR(last), 0);
- -: 9846:
- 133083: 9847: return last;
- -: 9848: }
- -: 9849:
- 47081: 9850: return val;
- -: 9851:}
- -: 9852:
- 2158619: 9853:Scheme_Object *optimize_get_predicate(Optimize_Info *info, Scheme_Object *var, int ignore_no_types)
- -: 9854:{
- -: 9855: Scheme_Object *pred;
- -: 9856:
- 2158619: 9857: if (info->no_types && !ignore_no_types) return NULL;
- -: 9858:
- 48238963: 9859: while (info) {
- 44747160: 9860: if (info->types) {
- 10396388: 9861: pred = scheme_hash_tree_get(info->types, var);
- 10396388: 9862: if (pred)
- 557771: 9863: return pred;
- -: 9864: }
- 44189389: 9865: info = info->next;
- -: 9866: }
- -: 9867:
- 1467016: 9868: return NULL;
- -: 9869:}
- -: 9870:
- 1283083: 9871:static Optimize_Info *optimize_info_add_frame(Optimize_Info *info, int orig, int current, int flags)
- -: 9872:{
- -: 9873: Optimize_Info *naya;
- -: 9874:
- 1283083: 9875: naya = scheme_optimize_info_create(info->cp, info->env, info->insp, 0);
- 1283083: 9876: naya->flags = (short)flags;
- 1283083: 9877: naya->next = info;
- 1283083: 9878: naya->original_frame = orig;
- 1283083: 9879: naya->new_frame = current;
- 1283083: 9880: naya->inline_fuel = info->inline_fuel;
- 1283083: 9881: naya->flatten_fuel = info->flatten_fuel;
- 1283083: 9882: naya->letrec_not_twice = info->letrec_not_twice;
- 1283083: 9883: naya->enforce_const = info->enforce_const;
- 1283083: 9884: naya->top_level_consts = info->top_level_consts;
- 1283083: 9885: naya->context = info->context;
- 1283083: 9886: naya->vclock = info->vclock;
- 1283083: 9887: naya->aclock = info->aclock;
- 1283083: 9888: naya->kclock = info->kclock;
- 1283083: 9889: naya->sclock = info->sclock;
- 1283083: 9890: naya->escapes = info->escapes;
- 1283083: 9891: naya->init_kclock = info->kclock;
- 1283083: 9892: naya->maybe_values_argument = info->maybe_values_argument;
- 1283083: 9893: naya->use_psize = info->use_psize;
- 1283083: 9894: naya->logger = info->logger;
- 1283083: 9895: naya->no_types = info->no_types;
- 1283083: 9896: naya->lambda_depth = info->lambda_depth + ((flags & SCHEME_LAMBDA_FRAME) ? 1 : 0);
- 1283083: 9897: naya->uses = info->uses;
- 1283083: 9898: naya->transitive_use_var = info->transitive_use_var;
- -: 9899:
- 1283083: 9900: return naya;
- -: 9901:}
- -: 9902:
- 822858: 9903:static void optimize_info_done(Optimize_Info *info, Optimize_Info *parent)
- -: 9904:{
- 822858: 9905: if (!parent) parent = info->next;
- -: 9906:
- 822858: 9907: parent->size += info->size;
- 822858: 9908: parent->vclock = info->vclock;
- 822858: 9909: parent->aclock = info->aclock;
- 822858: 9910: parent->kclock = info->kclock;
- 822858: 9911: parent->sclock = info->sclock;
- 822858: 9912: parent->escapes = info->escapes;
- 822858: 9913: parent->psize += info->psize;
- 822858: 9914: parent->flatten_fuel = info->flatten_fuel;
- 822858: 9915: if (info->has_nonleaf)
- 565604: 9916: parent->has_nonleaf = 1;
- 822858: 9917:}
- -: 9918:
- -: 9919:/*========================================================================*/
- -: 9920:/* precise GC traversers */
- -: 9921:/*========================================================================*/
- -: 9922:
- -: 9923:#ifdef MZ_PRECISE_GC
- -: 9924:
- -: 9925:START_XFORM_SKIP;
- -: 9926:
- -: 9927:#include "mzmark_optimize.inc"
- -: 9928:
- -: 9929:static void register_traversers(void)
- -: 9930:{
- -: 9931: GC_REG_TRAV(scheme_once_used_type, mark_once_used);
- -: 9932: GC_REG_TRAV(scheme_rt_optimize_info, mark_optimize_info);
- -: 9933:}
- -: 9934:
- -: 9935:END_XFORM_SKIP;
- -: 9936:
- -: 9937:#endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement