1
Fork 0

rustc: Add fast paths for vars and param folds. 3x typechecking speedup.

This commit is contained in:
Patrick Walton 2011-06-09 11:20:47 -07:00
parent 73ae684536
commit a4663d2845
2 changed files with 70 additions and 61 deletions

View file

@ -1260,8 +1260,7 @@ fn simplify_type(&@crate_ctxt ccx, &ty::t typ) -> ty::t {
case (_) { ret typ; } case (_) { ret typ; }
} }
} }
auto f = bind simplifier(ccx, _); ret ty::fold_ty(ccx.tcx, ty::fm_general(bind simplifier(ccx, _)), typ);
ret ty::fold_ty(ccx.tcx, f, typ);
} }
// Computes the size of the data part of a non-dynamically-sized tag. // Computes the size of the data part of a non-dynamically-sized tag.

View file

@ -697,10 +697,22 @@ fn walk_ty(&ctxt cx, ty_walk walker, t ty) {
walker(ty); walker(ty);
} }
type ty_fold = fn(t) -> t; tag fold_mode {
fm_var(fn(int)->t);
fm_param(fn(uint)->t);
fm_general(fn(t)->t);
}
fn fold_ty(&ctxt cx, ty_fold fld, t ty_0) -> t { fn fold_ty(&ctxt cx, fold_mode fld, t ty_0) -> t {
auto ty = ty_0; auto ty = ty_0;
// Fast paths.
alt (fld) {
case (fm_var(_)) { if (!type_contains_vars(cx, ty)) { ret ty; } }
case (fm_param(_)) { if (!type_contains_params(cx, ty)) { ret ty; } }
case (fm_general(_)) { /* no fast path */ }
}
alt (struct(cx, ty)) { alt (struct(cx, ty)) {
case (ty_nil) { /* no-op */ } case (ty_nil) { /* no-op */ }
case (ty_bot) { /* no-op */ } case (ty_bot) { /* no-op */ }
@ -788,11 +800,25 @@ fn fold_ty(&ctxt cx, ty_fold fld, t ty_0) -> t {
} }
ty = copy_cname(cx, mk_obj(cx, new_methods), ty); ty = copy_cname(cx, mk_obj(cx, new_methods), ty);
} }
case (ty_var(_)) { /* no-op */ } case (ty_var(?id)) {
case (ty_param(_)) { /* no-op */ } alt (fld) {
case (fm_var(?folder)) { ty = folder(id); }
case (_) { /* no-op */ }
}
}
case (ty_param(?id)) {
alt (fld) {
case (fm_param(?folder)) { ty = folder(id); }
case (_) { /* no-op */ }
}
}
} }
ret fld(ty); // If this is a general type fold, then we need to run it now.
alt (fld) {
case (fm_general(?folder)) { ret folder(ty); }
case (_) { ret ty; }
}
} }
// Type utilities // Type utilities
@ -2101,29 +2127,23 @@ mod unify {
fn resolve_all_vars(&ty_ctxt tcx, &@var_bindings vb, t typ) -> t { fn resolve_all_vars(&ty_ctxt tcx, &@var_bindings vb, t typ) -> t {
if (!type_contains_vars(tcx, typ)) { ret typ; } if (!type_contains_vars(tcx, typ)) { ret typ; }
fn folder(ty_ctxt tcx, @var_bindings vb, t typ) -> t { fn folder(ty_ctxt tcx, @var_bindings vb, int vid) -> t {
alt (struct(tcx, typ)) { // It's possible that we haven't even created the var set.
case (ty_var(?vid)) { // Handle this case gracefully.
// It's possible that we haven't even created the var set. if ((vid as uint) >= ufind::set_count(vb.sets)) {
// Handle this case gracefully. ret ty::mk_var(tcx, vid);
if ((vid as uint) >= ufind::set_count(vb.sets)) { }
ret typ;
}
auto root_id = ufind::find(vb.sets, vid as uint); auto root_id = ufind::find(vb.sets, vid as uint);
alt (smallintmap::find[t](vb.types, root_id)) { alt (smallintmap::find[t](vb.types, root_id)) {
case (some[t](?typ2)) { case (some[t](?typ2)) {
ret fold_ty(tcx, bind folder(tcx, vb, _), typ2); ret fold_ty(tcx, fm_var(bind folder(tcx, vb, _)), typ2);
}
case (none[t]) { ret typ; }
}
} }
case (none[t]) { ret ty::mk_var(tcx, vid); }
case (_) { ret typ; }
} }
} }
ret fold_ty(tcx, bind folder(tcx, vb, _), typ); ret fold_ty(tcx, fm_var(bind folder(tcx, vb, _)), typ);
} }
// If the given type is a variable, returns the structure of that type. // If the given type is a variable, returns the structure of that type.
@ -2542,32 +2562,29 @@ mod unify {
fn fixup_vars(ty_ctxt tcx, @var_bindings vb, t typ) -> fixup_result { fn fixup_vars(ty_ctxt tcx, @var_bindings vb, t typ) -> fixup_result {
fn subst_vars(ty_ctxt tcx, @var_bindings vb, fn subst_vars(ty_ctxt tcx, @var_bindings vb,
@mutable option::t[int] unresolved, t typ) -> t { @mutable option::t[int] unresolved, int vid) -> t {
alt (struct(tcx, typ)) { if ((vid as uint) >= ufind::set_count(vb.sets)) {
case (ty::ty_var(?vid)) { *unresolved = some[int](vid);
if ((vid as uint) >= ufind::set_count(vb.sets)) { ret ty::mk_var(tcx, vid);
*unresolved = some[int](vid); }
ret typ;
}
auto root_id = ufind::find(vb.sets, vid as uint); auto root_id = ufind::find(vb.sets, vid as uint);
alt (smallintmap::find[t](vb.types, root_id)) { alt (smallintmap::find[t](vb.types, root_id)) {
case (none[t]) { case (none[t]) {
*unresolved = some[int](vid); *unresolved = some[int](vid);
ret typ; ret ty::mk_var(tcx, vid);
} }
case (some[t](?rt)) { case (some[t](?rt)) {
ret fold_ty(tcx, ret fold_ty(tcx,
bind subst_vars(tcx, vb, unresolved, _), rt); fm_var(bind subst_vars(tcx, vb, unresolved, _)), rt);
}
}
} }
case (_) { ret typ; }
} }
} }
auto unresolved = @mutable none[int]; auto unresolved = @mutable none[int];
auto rty = fold_ty(tcx, bind subst_vars(tcx, vb, unresolved, _), typ); auto rty = fold_ty(tcx,
fm_var(bind subst_vars(tcx, vb, unresolved, _)),
typ);
auto ur = *unresolved; auto ur = *unresolved;
alt (ur) { alt (ur) {
@ -2641,8 +2658,7 @@ fn type_err_to_str(&ty::type_err err) -> str {
// Converts type parameters in a type to type variables and returns the // Converts type parameters in a type to type variables and returns the
// resulting type along with a list of type variable IDs. // resulting type along with a list of type variable IDs.
fn bind_params_in_type(&ctxt cx, fn()->int next_ty_var, t typ, fn bind_params_in_type(&ctxt cx, fn()->int next_ty_var, t typ,
uint ty_param_count) uint ty_param_count) -> tup(vec[int], t) {
-> tup(vec[int], t) {
let vec[int] param_var_ids = []; let vec[int] param_var_ids = [];
auto i = 0u; auto i = 0u;
while (i < ty_param_count) { while (i < ty_param_count) {
@ -2650,16 +2666,13 @@ fn bind_params_in_type(&ctxt cx, fn()->int next_ty_var, t typ,
i += 1u; i += 1u;
} }
fn binder(ctxt cx, vec[int] param_var_ids, fn()->int next_ty_var, t typ) fn binder(ctxt cx, vec[int] param_var_ids, fn()->int next_ty_var,
-> t { uint index) -> t {
alt (struct(cx, typ)) { ret mk_var(cx, param_var_ids.(index));
case (ty_param(?index)) { ret mk_var(cx, param_var_ids.(index)); }
case (_) { ret typ; }
}
} }
auto f = bind binder(cx, param_var_ids, next_ty_var, _); auto new_typ = fold_ty(cx,
auto new_typ = fold_ty(cx, f, typ); fm_param(bind binder(cx, param_var_ids, next_ty_var, _)), typ);
ret tup(param_var_ids, new_typ); ret tup(param_var_ids, new_typ);
} }
@ -2668,14 +2681,11 @@ fn bind_params_in_type(&ctxt cx, fn()->int next_ty_var, t typ,
fn substitute_type_params(&ctxt cx, vec[ty::t] substs, t typ) -> t { fn substitute_type_params(&ctxt cx, vec[ty::t] substs, t typ) -> t {
if (!type_contains_params(cx, typ)) { ret typ; } if (!type_contains_params(cx, typ)) { ret typ; }
fn substituter(ctxt cx, vec[ty::t] substs, t typ) -> t { fn substituter(ctxt cx, vec[ty::t] substs, uint idx) -> t {
alt (struct(cx, typ)) { ret substs.(idx);
case (ty_param(?idx)) { ret substs.(idx); }
case (_) { ret typ; }
}
} }
ret fold_ty(cx, bind substituter(cx, substs, _), typ); ret fold_ty(cx, fm_param(bind substituter(cx, substs, _)), typ);
} }
fn def_has_ty_params(&ast::def def) -> bool { fn def_has_ty_params(&ast::def def) -> bool {