From 716cf46d490422dcf42c14a21c904ad8db7793ab Mon Sep 17 00:00:00 2001 From: N5N3 <2642243996@qq.com> Date: Sat, 5 Oct 2024 05:34:27 +0800 Subject: [PATCH] typeintersect: allocation tuning for large `UnionAll` (#54745) This PR tries to reduce the allocation caused by `save_env` by skipping `alloc_env` and truncating env size when possible. (cherry picked from commit 99cc59c7b59a3facf4be3ac0d72218f79db0593d) --- src/subtype.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index b12a8ec88e2b7..59cba8a895653 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2412,24 +2412,47 @@ static jl_value_t *intersect_aside(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, if (obviously_egal(x, y)) return x; + jl_varbinding_t *vars = NULL; + jl_varbinding_t *bbprev = NULL; + jl_varbinding_t *xb = jl_is_typevar(x) ? lookup(e, (jl_tvar_t *)x) : NULL; + jl_varbinding_t *yb = jl_is_typevar(y) ? lookup(e, (jl_tvar_t *)y) : NULL; + int simple_x = !jl_has_free_typevars(!jl_is_typevar(x) ? x : xb ? xb->ub : ((jl_tvar_t *)x)->ub); + int simple_y = !jl_has_free_typevars(!jl_is_typevar(y) ? y : yb ? yb->ub : ((jl_tvar_t *)y)->ub); + if (simple_x && simple_y && !(xb && yb)) { + vars = e->vars; + e->vars = xb ? xb : yb; + if (e->vars != NULL) { + bbprev = e->vars->prev; + e->vars->prev = NULL; + } + } jl_saved_unionstate_t oldRunions; push_unionstate(&oldRunions, &e->Runions); int savedepth = e->invdepth; e->invdepth = depth; jl_value_t *res = intersect_all(x, y, e); e->invdepth = savedepth; pop_unionstate(&e->Runions, &oldRunions); + if (bbprev) e->vars->prev = bbprev; + if (vars) e->vars = vars; return res; } static jl_value_t *intersect_union(jl_value_t *x, jl_uniontype_t *u, jl_stenv_t *e, int8_t R, int param) { - if (param == 2 || (!jl_has_free_typevars(x) && !jl_has_free_typevars((jl_value_t*)u))) { + int no_free = !jl_has_free_typevars(x) && !jl_has_free_typevars((jl_value_t*)u); + if (param == 2 || no_free) { jl_value_t *a=NULL, *b=NULL; JL_GC_PUSH2(&a, &b); + jl_varbinding_t *vars = NULL; + if (no_free) { + vars = e->vars; + e->vars = NULL; + } jl_saved_unionstate_t oldRunions; push_unionstate(&oldRunions, &e->Runions); a = R ? intersect_all(x, u->a, e) : intersect_all(u->a, x, e); b = R ? intersect_all(x, u->b, e) : intersect_all(u->b, x, e); pop_unionstate(&e->Runions, &oldRunions); + if (vars) e->vars = vars; jl_value_t *i = simple_join(a,b); JL_GC_POP(); return i; @@ -4127,9 +4150,13 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) save_env(e, &se, 1); int niter = 0, total_iter = 0; is[0] = intersect(x, y, e, 0); // root - if (is[0] != jl_bottom_type) + if (is[0] == jl_bottom_type) { + restore_env(e, &se, 1); + } + else if (!e->emptiness_only && has_next_union_state(e, 1)) { niter = merge_env(e, &me, &se, niter); - restore_env(e, &se, 1); + restore_env(e, &se, 1); + } while (next_union_state(e, 1)) { if (e->emptiness_only && is[0] != jl_bottom_type) break; @@ -4137,9 +4164,16 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) e->Runions.more = 0; is[1] = intersect(x, y, e, 0); - if (is[1] != jl_bottom_type) + if (is[1] == jl_bottom_type) { + restore_env(e, &se, 1); + } + else if (niter > 0 || (!e->emptiness_only && has_next_union_state(e, 1))) { niter = merge_env(e, &me, &se, niter); - restore_env(e, &se, 1); + restore_env(e, &se, 1); + } + else { + assert(is[0] == jl_bottom_type); + } if (is[0] == jl_bottom_type) is[0] = is[1]; else if (is[1] != jl_bottom_type) {