From a516304f6b3d7469399dc5402fe68397460be41a Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 29 Dec 2015 07:01:57 -0600 Subject: [PATCH] fix specialization over a nested `lambda` --- .../tests/racket/optimize.rktl | 21 +++++++++++++ racket/src/racket/src/jit.c | 30 +++++++++++++------ racket/src/racket/src/jit.h | 2 +- racket/src/racket/src/jitcall.c | 2 +- racket/src/racket/src/jitinline.c | 4 +-- racket/src/racket/src/jitstate.c | 13 ++++---- 6 files changed, 52 insertions(+), 20 deletions(-) diff --git a/pkgs/racket-test-core/tests/racket/optimize.rktl b/pkgs/racket-test-core/tests/racket/optimize.rktl index 4a67138c57..1aa59ed2a5 100644 --- a/pkgs/racket-test-core/tests/racket/optimize.rktl +++ b/pkgs/racket-test-core/tests/racket/optimize.rktl @@ -5064,6 +5064,27 @@ (dup rep)))) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Check specialization with a capturing lambda: + +(let () + (define (f x) + (procedure-specialize + (lambda (y) + (lambda () (+ x y))))) + (set! f f) + (test 11 ((f 10) 1))) + + +(let () + (define (f x) + (set! x (add1 x)) + (procedure-specialize + (lambda (y) + (lambda () (+ x y))))) + (set! f f) + (test 12 ((f 10) 1))) + +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/racket/src/racket/src/jit.c b/racket/src/racket/src/jit.c index 82f68277da..52b8c9704d 100644 --- a/racket/src/racket/src/jit.c +++ b/racket/src/racket/src/jit.c @@ -1275,7 +1275,7 @@ static int generate_closure(Scheme_Closure_Data *data, jit_movi_l(JIT_R1, init_word); jit_str_l(JIT_R0, JIT_R1); } - scheme_mz_load_retained(jitter, JIT_R1, code, 0); + scheme_mz_load_retained(jitter, JIT_R1, code); jit_stxi_p((intptr_t)&((Scheme_Native_Closure *)0x0)->code, JIT_R0, JIT_R1); return 1; @@ -1285,7 +1285,7 @@ static int generate_closure(Scheme_Closure_Data *data, JIT_UPDATE_THREAD_RSPTR_IF_NEEDED(); mz_prepare(1); - scheme_mz_load_retained(jitter, JIT_R0, code, 0); + scheme_mz_load_retained(jitter, JIT_R0, code); jit_pusharg_p(JIT_R0); { GC_CAN_IGNORE jit_insn *refr USED_ONLY_FOR_FUTURES; @@ -1302,13 +1302,25 @@ static int generate_closure_fill(Scheme_Closure_Data *data, /* Fill in closure */ int j, size, pos; mzshort *map; + Scheme_Object *v; size = data->closure_size; map = data->closure_map; jit_addi_p(JIT_R2, JIT_R0, &((Scheme_Native_Closure *)0x0)->vals); for (j = 0; j < size; j++) { CHECK_LIMIT(); - pos = mz_remap(map[j]); - jit_ldxi_p(JIT_R1, JIT_RUNSTACK, WORDS_TO_BYTES(pos)); + + if (SCHEME_NATIVE_CLOSURE_DATA_FLAGS(jitter->nc->code) & NATIVE_SPECIALIZED) + v = extract_closure_local(map[j], jitter, 1); + else + v = NULL; + + if (v) { + /* capture value directly within specialized */ + scheme_mz_load_retained(jitter, JIT_R1, v); + } else { + pos = mz_remap(map[j]); + jit_ldxi_p(JIT_R1, JIT_RUNSTACK, WORDS_TO_BYTES(pos)); + } jit_stxi_p(WORDS_TO_BYTES(j), JIT_R2, JIT_R1); } return 1; @@ -1435,7 +1447,7 @@ static int generate_case_closure(Scheme_Object *obj, mz_jit_state *jitter, int t JIT_UPDATE_THREAD_RSPTR_IF_NEEDED(); mz_prepare(1); - scheme_mz_load_retained(jitter, JIT_R0, ndata, 0); + scheme_mz_load_retained(jitter, JIT_R0, ndata); jit_pusharg_p(JIT_R0); { GC_CAN_IGNORE jit_insn *refr USED_ONLY_FOR_FUTURES; @@ -2056,7 +2068,7 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w Scheme_Object *b; mz_rs_sync_fail_branch(); b = scheme_extract_global(obj, jitter->nc, 0); - scheme_mz_load_retained(jitter, JIT_R2, b, 1); + scheme_mz_load_retained(jitter, JIT_R2, b); } else { /* Load global array: */ pos = mz_remap(SCHEME_TOPLEVEL_DEPTH(obj)); @@ -2175,7 +2187,7 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w pos = mz_remap(SCHEME_LOCAL_POS(obj)); if (!result_ignored) { if (specialized) - scheme_mz_load_retained(jitter, JIT_R0, specialized, 1); + scheme_mz_load_retained(jitter, JIT_R0, specialized); else mz_rs_ldxi(JIT_R0, pos); jit_ldr_p(target, JIT_R0); @@ -2879,7 +2891,7 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w if (ab) { pos = mz_remap(lv->position); if (specialized) - scheme_mz_load_retained(jitter, JIT_R2, specialized, 1); + scheme_mz_load_retained(jitter, JIT_R2, specialized); else mz_rs_ldxi(JIT_R2, pos); jit_str_p(JIT_R2, JIT_R0); @@ -3357,7 +3369,7 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w } } - scheme_mz_load_retained(jitter, target, obj, 0); + scheme_mz_load_retained(jitter, target, obj); END_JIT_DATA(19); return 1; diff --git a/racket/src/racket/src/jit.h b/racket/src/racket/src/jit.h index 70ccaf1ea1..5d097e6011 100644 --- a/racket/src/racket/src/jit.h +++ b/racket/src/racket/src/jit.h @@ -1366,7 +1366,7 @@ int scheme_stack_safety(mz_jit_state *jitter, int cnt, int offset); #ifdef USE_FLONUM_UNBOXING int scheme_mz_flostack_pos(mz_jit_state *jitter, int i); #endif -void scheme_mz_load_retained(mz_jit_state *jitter, int rs, void *o, int non_obj); +void scheme_mz_load_retained(mz_jit_state *jitter, int rs, void *o); void scheme_mz_runstack_skipped(mz_jit_state *jitter, int n); void scheme_mz_runstack_unskipped(mz_jit_state *jitter, int n); diff --git a/racket/src/racket/src/jitcall.c b/racket/src/racket/src/jitcall.c index d44ec7513e..fc2d056fa2 100644 --- a/racket/src/racket/src/jitcall.c +++ b/racket/src/racket/src/jitcall.c @@ -479,7 +479,7 @@ int scheme_generate_tail_call(mz_jit_state *jitter, int num_rands, int direct_na if (direct_native && direct_to_code) { __END_SHORT_JUMPS__(num_rands < 100); /* load closure pointer into R0: */ - scheme_mz_load_retained(jitter, JIT_R0, direct_to_code, 0); + scheme_mz_load_retained(jitter, JIT_R0, direct_to_code); /* jump directly: */ (void)jit_jmpi(direct_to_code->code->u.tail_code); /* no slow path in this mode */ diff --git a/racket/src/racket/src/jitinline.c b/racket/src/racket/src/jitinline.c index 32743f1cf9..efea7983fd 100644 --- a/racket/src/racket/src/jitinline.c +++ b/racket/src/racket/src/jitinline.c @@ -2561,7 +2561,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i && !SCHEME_FALSEP(a1) && !SCHEME_VOIDP(a1) && !SAME_OBJ(a1, scheme_true)) { - scheme_mz_load_retained(jitter, JIT_R1, a1, 0); + scheme_mz_load_retained(jitter, JIT_R1, a1); ref = jit_bner_p(jit_forward(), JIT_R0, JIT_R1); /* In case true is a fall-through, note that the test didn't disturb R0: */ @@ -3848,7 +3848,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i ref = jit_bnei_p(jit_forward(), JIT_R0, scheme_undefined); __END_TINY_JUMPS__(1); - scheme_mz_load_retained(jitter, JIT_R1, app->rand2, 0); + scheme_mz_load_retained(jitter, JIT_R1, app->rand2); if (IS_NAMED_PRIM(rator, "check-not-unsafe-undefined")) (void)jit_calli(sjc.call_check_not_defined_code); else diff --git a/racket/src/racket/src/jitstate.c b/racket/src/racket/src/jitstate.c index 09e7a14fed..029c07628c 100644 --- a/racket/src/racket/src/jitstate.c +++ b/racket/src/racket/src/jitstate.c @@ -70,15 +70,14 @@ int scheme_mz_retain_it(mz_jit_state *jitter, void *v) return jitter->retained; } -void scheme_mz_load_retained(mz_jit_state *jitter, int rs, void *obj, int non_obj) +void scheme_mz_load_retained(mz_jit_state *jitter, int rs, void *obj) /* obj is a pointer, but not necesarily tagged (in CGC) */ { - if (non_obj - || (!SCHEME_INTP((Scheme_Object *)obj) - && !SAME_OBJ((Scheme_Object *)obj, scheme_true) - && !SAME_OBJ((Scheme_Object *)obj, scheme_false) - && !SAME_OBJ((Scheme_Object *)obj, scheme_void) - && !SAME_OBJ((Scheme_Object *)obj, scheme_null))) { + if (!SCHEME_INTP((Scheme_Object *)obj) + && !SAME_OBJ((Scheme_Object *)obj, scheme_true) + && !SAME_OBJ((Scheme_Object *)obj, scheme_false) + && !SAME_OBJ((Scheme_Object *)obj, scheme_void) + && !SAME_OBJ((Scheme_Object *)obj, scheme_null)) { #ifdef JIT_PRECISE_GC int retptr; void *p;