From 624c2fabc9a2c160a989beae3e65da6583df71b1 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 16 Feb 2016 15:49:02 -0500 Subject: [PATCH 1/2] some fixes to very-linear mode, and a small amount of cleanup --- src/ast.c | 23 +++++++++-------------- src/julia-syntax.scm | 21 +++++++++++++++++---- src/toplevel.c | 10 +++++----- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/ast.c b/src/ast.c index 06521a25c010f..225f3d62fc24b 100644 --- a/src/ast.c +++ b/src/ast.c @@ -835,31 +835,27 @@ static int jl_parse_deperror(fl_context_t *fl_ctx, int err) } // returns either an expression or a thunk -JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr) +jl_value_t *jl_call_scm_on_ast(char *funcname, jl_value_t *expr) { jl_ast_context_t *ctx = jl_ast_ctx_enter(); fl_context_t *fl_ctx = &ctx->fl; JL_AST_PRESERVE_PUSH(ctx, roots, old_roots); value_t arg = julia_to_scm(fl_ctx, expr); - value_t e = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "jl-expand-to-thunk")), arg); + value_t e = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, funcname)), arg); jl_value_t *result = scm_to_julia(fl_ctx, e, 0); JL_AST_PRESERVE_POP(ctx, old_roots); jl_ast_ctx_leave(ctx); return result; } +JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr) +{ + return jl_call_scm_on_ast("jl-expand-to-thunk", expr); +} + JL_DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr) { - jl_ast_context_t *ctx = jl_ast_ctx_enter(); - fl_context_t *fl_ctx = &ctx->fl; - JL_AST_PRESERVE_PUSH(ctx, roots, old_roots); - value_t arg = julia_to_scm(fl_ctx, expr); - value_t e = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "jl-macroexpand")), arg); - jl_value_t *result; - result = scm_to_julia(fl_ctx, e, 0); - JL_AST_PRESERVE_POP(ctx, old_roots); - jl_ast_ctx_leave(ctx); - return result; + return jl_call_scm_on_ast("jl-macroexpand", expr); } ssize_t jl_max_jlgensym_in(jl_value_t *v) @@ -1140,8 +1136,7 @@ jl_value_t *jl_preresolve_globals(jl_value_t *expr, jl_lambda_info_t *lam) jl_value_t *me = jl_exprarg(e,1); if (jl_is_topnode(me) || (jl_is_symbol(me) && jl_binding_resolved_p(lam->module,(jl_sym_t*)me))) { - jl_value_t *m = jl_static_eval(me, NULL, lam->module, - lam, 0, 0); + jl_value_t *m = jl_static_eval(me, NULL, lam->module, lam, 0, 0); if (m && jl_is_module(m)) return jl_module_globalref((jl_module_t*)m, (jl_sym_t*)s); } diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index f2704dafc3a25..e61f601aad7c8 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2897,14 +2897,27 @@ f(x) = yt(x) (let* ((arg (car lst)) (aval (compile arg break-labels #t #f))) (loop (cdr lst) - (cons (if (and temps? (pair? (cdr lst)) + (cons (if (and temps? (not (simple-atom? arg)) (not (jlgensym? arg)) - (not (simple-atom? aval)) (not (jlgensym? aval))) + (not (simple-atom? aval)) (not (jlgensym? aval)) + (not (and (pair? arg) + (memq (car arg) '(& quote inert top copyast)))) + (not (and (symbol? arg) + (or (null? (cdr lst)) + (null? vals))))) (let ((tmp (make-jlgensym))) (emit `(= ,tmp ,aval)) tmp) aval) vals)))))))) + (define (compile-cond ex break-labels) + (let ((cnd (compile ex break-labels #t #f))) + (if (and *very-linear-mode* + (not (or (simple-atom? cnd) (jlgensym? cnd) (symbol? cnd)))) + (let ((tmp (make-jlgensym))) + (emit `(= ,tmp ,cnd)) + tmp) + cnd))) ;; the interpreter loop. `break-labels` keeps track of the labels to jump to ;; for all currently closing break-blocks. ;; `value` means we are in a context where a value is required; a meaningful @@ -2952,7 +2965,7 @@ f(x) = yt(x) (compile (cadr e) break-labels #t #t) '(null)) ((if) - (let ((test `(gotoifnot ,(compile (cadr e) break-labels #t #f) _)) + (let ((test `(gotoifnot ,(compile-cond (cadr e) break-labels) _)) (end-jump `(goto _)) (val (if (and value (not tail)) (new-mutable-var) #f))) (emit test) @@ -2973,7 +2986,7 @@ f(x) = yt(x) ((_while) (let* ((endl (make-label)) (topl (make&mark-label)) - (test (compile (cadr e) break-labels #t #f))) + (test (compile-cond (cadr e) break-labels))) (emit `(gotoifnot ,test ,endl)) (compile (caddr e) break-labels #f #f) (emit `(goto ,topl)) diff --git a/src/toplevel.c b/src/toplevel.c index d2153f3635374..b45696874a015 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -710,7 +710,7 @@ jl_value_t *jl_first_argument_datatype(jl_value_t *argtypes) return (jl_value_t*)first_arg_datatype(argtypes, 0); } -static jl_lambda_info_t *expr_to_lambda(jl_lambda_info_t *f) +static jl_lambda_info_t *expr_to_lambda(jl_expr_t *f) { // this occurs when there is a closure being added to an out-of-scope function // the user should only do this at the toplevel @@ -729,10 +729,10 @@ static jl_lambda_info_t *expr_to_lambda(jl_lambda_info_t *f) jl_svecset(tvar_syms, i, jl_arrayref(tvar_syms_arr, i)); } // wrap in a LambdaInfo - f = jl_new_lambda_info((jl_value_t*)f, tvar_syms, jl_emptysvec, jl_current_module); - jl_preresolve_globals(f->ast, f); + jl_lambda_info_t *li = jl_new_lambda_info((jl_value_t*)f, tvar_syms, jl_emptysvec, jl_current_module); + jl_preresolve_globals(li->ast, li); JL_GC_POP(); - return f; + return li; } JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_lambda_info_t *f, jl_value_t *isstaged) @@ -745,7 +745,7 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_lambda_info_t *f, jl_valu JL_GC_PUSH1(&f); if (!jl_is_lambda_info(f)) - f = expr_to_lambda(f); + f = expr_to_lambda((jl_expr_t*)f); assert(jl_is_lambda_info(f)); assert(jl_is_tuple_type(argtypes)); From 2fba5260604de58d3615c876cf70532c804bd033 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 23 Feb 2016 13:40:46 -0500 Subject: [PATCH 2/2] limit exponent on number of calls made by `_methods` for unions --- base/reflection.jl | 6 +++++- src/gf.c | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/base/reflection.jl b/base/reflection.jl index 6cb18c4e027ad..b24a2c7acbca1 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -188,11 +188,15 @@ function _methods(f::ANY,t::ANY,lim) end function _methods_by_ftype(t::ANY, lim) tp = t.parameters + nu = 1 for ti in tp if isa(ti, Union) - return _methods(Any[tp...], length(tp), lim, []) + nu *= length(ti.types) end end + if 1 < nu <= 64 + return _methods(Any[tp...], length(tp), lim, []) + end return ccall(:jl_matching_methods, Any, (Any,Int32), t, lim) end function _methods(t::Array,i,lim::Integer,matching::Array{Any,1}) diff --git a/src/gf.c b/src/gf.c index 1ab65c9f22ecb..6d11e627a0861 100644 --- a/src/gf.c +++ b/src/gf.c @@ -2236,6 +2236,8 @@ static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type, JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_value_t *types, int lim) { assert(jl_nparams(types) > 0); + if (jl_tparam0(types) == jl_bottom_type) + return (jl_value_t*)jl_alloc_cell_1d(0); assert(jl_is_datatype(jl_tparam0(types))); jl_methtable_t *mt = ((jl_datatype_t*)jl_tparam0(types))->name->mt; if (mt == NULL)