From 79ada3b16ee5cd905a4a04d329a7cdf447147b0a Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sun, 14 Oct 2012 12:43:14 -0400 Subject: [PATCH] fix JIT bug in struct pred/get/set corner case When thie JIT guesses that an identifier is bound to a structure predicate, getter, setter, etc., but that guess turns out to be wrong, and the call is in a tail position, then preserve tail-call behavior. (Changes include some setup to inline structure constructors.) --- collects/tests/racket/optimize.rktl | 24 +++++ src/racket/src/jit.c | 2 +- src/racket/src/jit.h | 28 ++++-- src/racket/src/jitcall.c | 7 ++ src/racket/src/jitcommon.c | 51 +++++++---- src/racket/src/jitinline.c | 130 +++++++++++++++++++++------- src/racket/src/schpriv.h | 2 + src/racket/src/struct.c | 4 +- 8 files changed, 189 insertions(+), 59 deletions(-) diff --git a/collects/tests/racket/optimize.rktl b/collects/tests/racket/optimize.rktl index 2d3bb4e332..692d4fc145 100644 --- a/collects/tests/racket/optimize.rktl +++ b/collects/tests/racket/optimize.rktl @@ -2196,4 +2196,28 @@ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(module check-tail-call-by-jit-for-struct-predicate racket/base + (provide go) + + (struct s (x)) + + (define f #f) + (set! f (lambda (v) + (if (zero? v) + (let ([vec (make-vector 6)]) + (vector-set-performance-stats! vec (current-thread)) + (vector-ref vec 3)) + (s? (sub1 v))))) + + (void (f 5)) ; JIT decides that `s?' is a struct predicate + (set! s? f) ; break the JIT's optimistic assumption + + (define (go) + (define size (f 500000)) ; make sure that this still leads to a tail loop + (size . < . 80000))) + +(test #t (dynamic-require ''check-tail-call-by-jit-for-struct-predicate 'go)) + +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (report-errs) diff --git a/src/racket/src/jit.c b/src/racket/src/jit.c index 2988a01f24..5afd8cfdd7 100644 --- a/src/racket/src/jit.c +++ b/src/racket/src/jit.c @@ -621,7 +621,7 @@ int scheme_is_simple(Scheme_Object *obj, int depth, int just_markless, mz_jit_st break; case scheme_application_type: - if (scheme_inlined_nary_prim(((Scheme_App_Rec *)obj)->args[0], obj) + if (scheme_inlined_nary_prim(((Scheme_App_Rec *)obj)->args[0], obj, jitter) && !SAME_OBJ(((Scheme_App_Rec *)obj)->args[0], scheme_values_func)) return 1; if (just_markless) { diff --git a/src/racket/src/jit.h b/src/racket/src/jit.h index 929631ca67..9dc08d468f 100644 --- a/src/racket/src/jit.h +++ b/src/racket/src/jit.h @@ -250,13 +250,13 @@ struct scheme_jit_common_record { void *on_demand_jit_arity_code, *in_progress_on_demand_jit_arity_code; void *get_stack_pointer_code; void *stack_cache_pop_code; - void *struct_pred_code, *struct_pred_multi_code; + void *struct_pred_code, *struct_pred_tail_code, *struct_pred_multi_code; void *struct_pred_branch_code; - void *struct_get_code, *struct_get_multi_code; - void *struct_set_code, *struct_set_multi_code; - void *struct_prop_get_code, *struct_prop_get_multi_code; - void *struct_prop_get_defl_code, *struct_prop_get_defl_multi_code; - void *struct_prop_pred_code, *struct_prop_pred_multi_code; + void *struct_get_code, *struct_get_tail_code, *struct_get_multi_code; + void *struct_set_code, *struct_set_tail_code, *struct_set_multi_code; + void *struct_prop_get_code, *struct_prop_get_tail_code, *struct_prop_get_multi_code; + void *struct_prop_get_defl_code, *struct_prop_get_defl_tail_code, *struct_prop_get_defl_multi_code; + void *struct_prop_pred_code, *struct_prop_pred_tail_code, *struct_prop_pred_multi_code; void *struct_proc_extract_code; void *bad_app_vals_target; void *app_values_slow_code, *app_values_multi_slow_code, *app_values_tail_slow_code; @@ -1170,7 +1170,7 @@ int scheme_mz_try_runstack_pop(mz_jit_state *jitter, int n); int scheme_inlined_unary_prim(Scheme_Object *o, Scheme_Object *_app, mz_jit_state *jitter); int scheme_inlined_binary_prim(Scheme_Object *o, Scheme_Object *_app, mz_jit_state *jitter); -int scheme_inlined_nary_prim(Scheme_Object *o, Scheme_Object *_app); +int scheme_inlined_nary_prim(Scheme_Object *o, Scheme_Object *_app, mz_jit_state *jitter); int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, int is_tail, int multi_ok, Branch_Info *for_branch, int branch_short, int need_sync, int result_ignored); int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, int is_tail, int multi_ok, @@ -1232,6 +1232,7 @@ int scheme_generate_tail_call(mz_jit_state *jitter, int num_rands, int direct_na int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direct_native, int need_set_rs, int multi_ok, int nontail_self, int pop_and_jump, int is_inlined, int unboxed_args); int scheme_generate_finish_tail_call(mz_jit_state *jitter, int direct_native); +int scheme_generate_finish_tail_apply(mz_jit_state *jitter); void scheme_jit_register_sub_func(mz_jit_state *jitter, void *code, Scheme_Object *protocol); void scheme_jit_register_helper_func(mz_jit_state *jitter, void *code); #ifdef MZ_USE_FUTURES @@ -1383,3 +1384,16 @@ Scheme_Object *scheme_jit_continuation_apply_install(Apply_LWC_Args *args); #define CMP_EVENP 4 /* odd? */ #define CMP_ODDP -4 + +/**********************************************************************/ + +#define INLINE_STRUCT_PROC_PRED 1 +#define INLINE_STRUCT_PROC_GET 2 +#define INLINE_STRUCT_PROC_SET 3 +#define INLINE_STRUCT_PROC_PROP_GET 4 +#define INLINE_STRUCT_PROC_PROP_GET_W_DEFAULT 5 +#define INLINE_STRUCT_PROC_PROP_PRED 6 +#define INLINE_STRUCT_PROC_CONSTR 7 + + + diff --git a/src/racket/src/jitcall.c b/src/racket/src/jitcall.c index 9a5e207c82..e89e2695a1 100644 --- a/src/racket/src/jitcall.c +++ b/src/racket/src/jitcall.c @@ -515,6 +515,13 @@ int scheme_generate_tail_call(mz_jit_state *jitter, int num_rands, int direct_na return 1; } +int scheme_generate_finish_tail_apply(mz_jit_state *jitter) +{ + GC_CAN_IGNORE jit_insn *refr; + (void)mz_finish_lwe(_scheme_tail_apply_from_native, refr); + return 1; +} + int scheme_generate_finish_tail_call(mz_jit_state *jitter, int direct_native) { mz_prepare(3); diff --git a/src/racket/src/jitcommon.c b/src/racket/src/jitcommon.c index c73a4fb736..0c45cf76e6 100644 --- a/src/racket/src/jitcommon.c +++ b/src/racket/src/jitcommon.c @@ -1356,7 +1356,7 @@ static int common3(mz_jit_state *jitter, void *_data) } static int gen_struct_slow(mz_jit_state *jitter, int kind, int ok_proc, - int for_branch, int multi_ok, + int for_branch, int is_tail, int multi_ok, GC_CAN_IGNORE jit_insn **_bref5, GC_CAN_IGNORE jit_insn **_bref6) { @@ -1376,7 +1376,10 @@ static int gen_struct_slow(mz_jit_state *jitter, int kind, int ok_proc, jit_pusharg_p(JIT_RUNSTACK); jit_pusharg_i(JIT_V1); jit_pusharg_p(JIT_R0); - if (multi_ok) { + if (is_tail) { + scheme_generate_finish_tail_apply(jitter); + CHECK_LIMIT(); + } else if (multi_ok) { (void)mz_finish_lwe(ts__scheme_apply_multi_from_native, refrts); } else { (void)mz_finish_lwe(ts__scheme_apply_from_native, refrts); @@ -1560,25 +1563,28 @@ static int common4(mz_jit_state *jitter, void *_data) __END_TINY_JUMPS__(1); } - /* *** struct_{pred,get,set}[_branch]_code *** */ + /* *** struct_{pred,get,set}[_branch,_multi,_tail]_code *** */ /* R0 is (potential) struct proc, R1 is (potential) struct. */ /* In branch mode, V1 is target address for false branch. */ /* In set mode, V1 is value to install. */ - for (ii = 0; ii < 2; ii++) { - for (i = 0; i < 4; i++) { + for (ii = 0; ii < 3; ii++) { /* single, multi, or tail */ + for (i = 0; i < 4; i++) { /* pred, pred_branch, get, or set */ void *code; int kind, for_branch; GC_CAN_IGNORE jit_insn *ref, *ref2, *ref3, *refslow, *refslow2, *bref1, *bref2, *refretry; GC_CAN_IGNORE jit_insn *bref3, *bref4, *bref5, *bref6, *bref8, *ref9; if ((ii == 1) && (i == 1)) continue; /* no multi variant of pred branch */ + if ((ii == 2) && (i == 1)) continue; /* no tail variant of pred branch */ code = jit_get_ip().ptr; if (!i) { kind = 1; for_branch = 0; - if (ii == 1) + if (ii == 2) + sjc.struct_pred_tail_code = jit_get_ip().ptr; + else if (ii == 1) sjc.struct_pred_multi_code = jit_get_ip().ptr; else sjc.struct_pred_code = jit_get_ip().ptr; @@ -1591,14 +1597,18 @@ static int common4(mz_jit_state *jitter, void *_data) } else if (i == 2) { kind = 2; for_branch = 0; - if (ii == 1) + if (ii == 2) + sjc.struct_get_tail_code = jit_get_ip().ptr; + else if (ii == 1) sjc.struct_get_multi_code = jit_get_ip().ptr; else sjc.struct_get_code = jit_get_ip().ptr; } else { kind = 3; for_branch = 0; - if (ii == 1) + if (ii == 2) + sjc.struct_set_tail_code = jit_get_ip().ptr; + else if (ii == 1) sjc.struct_set_multi_code = jit_get_ip().ptr; else sjc.struct_set_code = jit_get_ip().ptr; @@ -1615,13 +1625,13 @@ static int common4(mz_jit_state *jitter, void *_data) /* Slow path: non-struct proc. */ refslow = _jit.x.pc; - gen_struct_slow(jitter, kind, 0, for_branch, ii == 1, &bref5, &bref6); + gen_struct_slow(jitter, kind, 0, for_branch, ii == 2, ii == 1, &bref5, &bref6); CHECK_LIMIT(); if ((kind == 2) || (kind == 3)) { /* Slow path: argument type is bad for a getter/setter. */ refslow2 = _jit.x.pc; - gen_struct_slow(jitter, kind, 1, 0, 0, NULL, NULL); + gen_struct_slow(jitter, kind, 1, 0, 0, 0, NULL, NULL); CHECK_LIMIT(); } else refslow2 = refslow; @@ -1773,28 +1783,34 @@ static int common4b(mz_jit_state *jitter, void *_data) { int i, ii; - /* *** struct_prop_{pred,get[_defl]}_[multi_]code *** */ + /* *** struct_prop_{pred,get[_defl]}_[multi_,tail_]code *** */ /* R0 is (potential) struct-prop proc, R1 is (potential) struct. If defl_, V1 is second argument for default value. */ for (i = 0; i < 3; i++) { - for (ii = 0; ii < 2; ii++) { + for (ii = 0; ii < 3; ii++) { /* single, multi, or tail */ void *code; GC_CAN_IGNORE jit_insn *ref, *ref2, *ref3, *refno, *refslow, *refloop, *refrts; code = jit_get_ip().ptr; if (i == 0) { - if (ii == 1) + if (ii == 2) + sjc.struct_prop_get_tail_code = code; + else if (ii == 1) sjc.struct_prop_get_multi_code = code; else sjc.struct_prop_get_code = code; } else if (i == 1) { - if (ii == 1) + if (ii == 2) + sjc.struct_prop_get_defl_tail_code = code; + else if (ii == 1) sjc.struct_prop_get_defl_multi_code = code; else sjc.struct_prop_get_defl_code = code; } else if (i == 2) { - if (ii == 1) + if (ii == 2) + sjc.struct_prop_pred_tail_code = code; + else if (ii == 1) sjc.struct_prop_pred_multi_code = code; else sjc.struct_prop_pred_code = code; @@ -1826,7 +1842,10 @@ static int common4b(mz_jit_state *jitter, void *_data) jit_pusharg_p(JIT_RUNSTACK); jit_pusharg_i(JIT_V1); jit_pusharg_p(JIT_R0); - if (ii == 1) { + if (ii == 2) { + scheme_generate_finish_tail_apply(jitter); + CHECK_LIMIT(); + } else if (ii == 1) { (void)mz_finish_lwe(ts__scheme_apply_multi_from_native, refrts); } else { (void)mz_finish_lwe(ts__scheme_apply_from_native, refrts); diff --git a/src/racket/src/jitinline.c b/src/racket/src/jitinline.c index c14af07bec..07e580cd4b 100644 --- a/src/racket/src/jitinline.c +++ b/src/racket/src/jitinline.c @@ -121,22 +121,32 @@ static int generate_two_args(Scheme_Object *rand1, Scheme_Object *rand2, mz_jit_ static int check_val_struct_prim(Scheme_Object *p, int arity) { if (p && SCHEME_PRIMP(p)) { - if (arity == 1) { - int t = (((Scheme_Primitive_Proc *)p)->pp.flags & SCHEME_PRIM_OTHER_TYPE_MASK); + int t = (((Scheme_Primitive_Proc *)p)->pp.flags & SCHEME_PRIM_OTHER_TYPE_MASK); + if (t == SCHEME_PRIM_STRUCT_TYPE_CONSTR) { +#if 0 + /* not yet ready... */ + Scheme_Struct_Type *t; + t = (Scheme_Struct_Type *)SCHEME_PRIM_CLOSURE_ELS(p)[0]; + if ((arity == t->num_islots) + && scheme_is_simple_struct_type(t)) { + return INLINE_STRUCT_PROC_CONSTR; + } +#endif + return 0; + } else if (arity == 1) { if (t == SCHEME_PRIM_STRUCT_TYPE_PRED) - return 1; + return INLINE_STRUCT_PROC_PRED; if (t == SCHEME_PRIM_STRUCT_TYPE_INDEXED_GETTER) - return 2; + return INLINE_STRUCT_PROC_GET; else if (t == SCHEME_PRIM_TYPE_STRUCT_PROP_GETTER) - return 4; + return INLINE_STRUCT_PROC_PROP_GET; else if (t == SCHEME_PRIM_STRUCT_TYPE_STRUCT_PROP_PRED) - return 6; + return INLINE_STRUCT_PROC_PROP_PRED; } else if (arity == 2) { - int t = (((Scheme_Primitive_Proc *)p)->pp.flags & SCHEME_PRIM_OTHER_TYPE_MASK); if (t == SCHEME_PRIM_STRUCT_TYPE_INDEXED_SETTER) - return 3; + return INLINE_STRUCT_PROC_SET; else if (t == SCHEME_PRIM_TYPE_STRUCT_PROP_GETTER) - return 5; + return INLINE_STRUCT_PROC_PROP_GET_W_DEFAULT; } } return 0; @@ -178,12 +188,15 @@ int scheme_inlined_binary_prim(Scheme_Object *o, Scheme_Object *_app, mz_jit_sta || inlineable_struct_prim(o, jitter, 2, 2)); } -int scheme_inlined_nary_prim(Scheme_Object *o, Scheme_Object *_app) +int scheme_inlined_nary_prim(Scheme_Object *o, Scheme_Object *_app, mz_jit_state *jitter) { - return (SCHEME_PRIMP(o) - && (SCHEME_PRIM_PROC_FLAGS(o) & SCHEME_PRIM_IS_NARY_INLINED) - && (((Scheme_App_Rec *)_app)->num_args >= ((Scheme_Primitive_Proc *)o)->mina) - && (((Scheme_App_Rec *)_app)->num_args <= ((Scheme_Primitive_Proc *)o)->mu.maxa)); + int n = ((Scheme_App_Rec *)_app)->num_args; + + return ((SCHEME_PRIMP(o) + && (SCHEME_PRIM_PROC_FLAGS(o) & SCHEME_PRIM_IS_NARY_INLINED) + && (n >= ((Scheme_Primitive_Proc *)o)->mina) + && (n <= ((Scheme_Primitive_Proc *)o)->mu.maxa)) + || inlineable_struct_prim(o, jitter, n, n)); } static int generate_inlined_constant_test(mz_jit_state *jitter, Scheme_App2_Rec *app, @@ -345,7 +358,7 @@ static int generate_inlined_type_test(mz_jit_state *jitter, Scheme_App2_Rec *app static int generate_inlined_struct_op(int kind, mz_jit_state *jitter, Scheme_Object *rator, Scheme_Object *rand, Scheme_Object *rand2, Branch_Info *for_branch, int branch_short, - int multi_ok) + int is_tail, int multi_ok) /* de-sync'd ok; for branch, sync'd before */ { LOG_IT(("inlined struct op\n")); @@ -382,42 +395,62 @@ static int generate_inlined_struct_op(int kind, mz_jit_state *jitter, scheme_branch_for_true(jitter, for_branch); __END_SHORT_JUMPS__(for_branch->branch_short); CHECK_LIMIT(); - } else if (kind == 1) { - if (multi_ok) { + } else if (kind == INLINE_STRUCT_PROC_PRED) { + if (is_tail) { + (void)jit_calli(sjc.struct_pred_tail_code); + } else if (multi_ok) { (void)jit_calli(sjc.struct_pred_multi_code); } else { (void)jit_calli(sjc.struct_pred_code); } - } else if (kind == 2) { - if (multi_ok) { + } else if (kind == INLINE_STRUCT_PROC_GET) { + if (is_tail) { + (void)jit_calli(sjc.struct_get_tail_code); + } else if (multi_ok) { (void)jit_calli(sjc.struct_get_multi_code); } else { (void)jit_calli(sjc.struct_get_code); } - } else if (kind == 3) { - if (multi_ok) { + } else if (kind == INLINE_STRUCT_PROC_SET) { + if (is_tail) { + (void)jit_calli(sjc.struct_set_tail_code); + } else if (multi_ok) { (void)jit_calli(sjc.struct_set_multi_code); } else { (void)jit_calli(sjc.struct_set_code); } - } else if (kind == 4) { - if (multi_ok) { + } else if (kind == INLINE_STRUCT_PROC_PROP_GET) { + if (is_tail) { + (void)jit_calli(sjc.struct_prop_get_tail_code); + } else if (multi_ok) { (void)jit_calli(sjc.struct_prop_get_multi_code); } else { (void)jit_calli(sjc.struct_prop_get_code); } - } else if (kind == 5) { - if (multi_ok) { + } else if (kind == INLINE_STRUCT_PROC_PROP_GET_W_DEFAULT) { + if (is_tail) { + (void)jit_calli(sjc.struct_prop_get_defl_tail_code); + } else if (multi_ok) { (void)jit_calli(sjc.struct_prop_get_defl_multi_code); } else { (void)jit_calli(sjc.struct_prop_get_defl_code); } - } else if (kind == 6) { - if (multi_ok) { + } else if (kind == INLINE_STRUCT_PROC_PROP_PRED) { + if (is_tail) { + (void)jit_calli(sjc.struct_prop_pred_tail_code); + } else if (multi_ok) { (void)jit_calli(sjc.struct_prop_pred_multi_code); } else { (void)jit_calli(sjc.struct_prop_pred_code); } + } else if (kind == INLINE_STRUCT_PROC_CONSTR) { + return 0; +#if 0 + if (!rand2) + (void)jit_calli(sjc.struct_constr_unary_code); + else + (void)jit_calli(sjc.struct_constr_binary_code); +#endif } else { scheme_signal_error("internal error: unknown struct-op mode"); } @@ -425,6 +458,23 @@ static int generate_inlined_struct_op(int kind, mz_jit_state *jitter, return 1; } +static int generate_inlined_nary_struct_op(int kind, mz_jit_state *jitter, + Scheme_Object *rator, Scheme_App_Rec *app, + Branch_Info *for_branch, int branch_short, + int multi_ok) +/* de-sync'd ok; for branch, sync'd before */ +{ +#if 1 + scheme_signal_error("shouldn't get here, yet"); /* REMOVEME */ +#else + /* generate code to evaluate the arguments */ + scheme_generate_app(app, NULL, app->num_args, jitter, 0, 0, 2); + CHECK_LIMIT(); + mz_rs_sync(); +#endif + return 0; +} + static int is_cXr_prim(const char *name) { int i; @@ -503,12 +553,16 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in { int k; k = inlineable_struct_prim(rator, jitter, 1, 1); - if (k == 1) { - generate_inlined_struct_op(1, jitter, rator, app->rand, NULL, for_branch, branch_short, multi_ok); + if (k == INLINE_STRUCT_PROC_PRED) { + generate_inlined_struct_op(1, jitter, rator, app->rand, NULL, for_branch, branch_short, is_tail, multi_ok); scheme_direct_call_count++; return 1; - } else if (((k == 2) || (k == 4) || (k == 6)) && !for_branch) { - generate_inlined_struct_op(k, jitter, rator, app->rand, NULL, for_branch, branch_short, multi_ok); + } else if (((k == INLINE_STRUCT_PROC_GET) + || (k == INLINE_STRUCT_PROC_PROP_GET) + || (k == INLINE_STRUCT_PROC_PROP_PRED) + || (k == INLINE_STRUCT_PROC_CONSTR)) + && !for_branch) { + generate_inlined_struct_op(k, jitter, rator, app->rand, NULL, for_branch, branch_short, is_tail, multi_ok); scheme_direct_call_count++; return 1; } @@ -1730,7 +1784,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i int k; k = inlineable_struct_prim(rator, jitter, 2, 2); if (k) { - generate_inlined_struct_op(k, jitter, rator, app->rand1, app->rand2, for_branch, branch_short, multi_ok); + generate_inlined_struct_op(k, jitter, rator, app->rand1, app->rand2, for_branch, branch_short, is_tail, multi_ok); scheme_direct_call_count++; return 1; } @@ -2790,7 +2844,17 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int /* de-sync's; for branch, sync'd before */ { Scheme_Object *rator = app->args[0]; - + + if (!for_branch) { + int k; + k = inlineable_struct_prim(rator, jitter, app->num_args, app->num_args); + if (k) { + generate_inlined_nary_struct_op(k, jitter, rator, app, for_branch, branch_short, multi_ok); + scheme_direct_call_count++; + return 1; + } + } + if (!SCHEME_PRIMP(rator)) return 0; diff --git a/src/racket/src/schpriv.h b/src/racket/src/schpriv.h index 9e5a1e27af..d838ab5b8d 100644 --- a/src/racket/src/schpriv.h +++ b/src/racket/src/schpriv.h @@ -819,6 +819,8 @@ Scheme_Object *scheme_extract_struct_procedure(Scheme_Object *obj, int num_rands Scheme_Object *scheme_proc_struct_name_source(Scheme_Object *a); Scheme_Object *scheme_object_name(Scheme_Object *a); +int scheme_is_simple_struct_type(Scheme_Struct_Type *stype); + Scheme_Object *scheme_is_writable_struct(Scheme_Object *s); Scheme_Object *scheme_print_attribute_ref(Scheme_Object *s); diff --git a/src/racket/src/struct.c b/src/racket/src/struct.c index fa8820983c..b4b58d91c2 100644 --- a/src/racket/src/struct.c +++ b/src/racket/src/struct.c @@ -2265,7 +2265,7 @@ make_simple_struct_instance(int argc, Scheme_Object **args, Scheme_Object *prim) return (Scheme_Object *)inst; } -static int is_simple_struct_type(Scheme_Struct_Type *stype) +int scheme_is_simple_struct_type(Scheme_Struct_Type *stype) { int p; @@ -3771,7 +3771,7 @@ make_struct_proc(Scheme_Struct_Type *struct_type, if (proc_type == SCHEME_CONSTR) { int simple; - simple = is_simple_struct_type(struct_type); + simple = scheme_is_simple_struct_type(struct_type); a[0] = (Scheme_Object *)struct_type; p = scheme_make_folding_prim_closure((simple ? make_simple_struct_instance