Skip to content

Commit 92ae2f8

Browse files
JeffBezansonmbauman
authored andcommittedJun 5, 2015
another attempt to address post-JuliaLang#10380 problems (JuliaLang#10875)
- add a linearly-searched part of the type cache for more difficult types - assign UIDs earlier so they can't change after cache insertion
1 parent ca76d47 commit 92ae2f8

File tree

4 files changed

+118
-48
lines changed

4 files changed

+118
-48
lines changed
 

‎src/alloc.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,8 @@ jl_typename_t *jl_new_typename(jl_sym_t *name)
498498
tn->name = name;
499499
tn->module = jl_current_module;
500500
tn->primary = NULL;
501-
tn->cache = (jl_value_t*)jl_emptysvec;
501+
tn->cache = jl_emptysvec;
502+
tn->linearcache = jl_emptysvec;
502503
tn->names = NULL;
503504
tn->uid = jl_assign_type_uid();
504505
return tn;

‎src/jltypes.c

+112-45
Original file line numberDiff line numberDiff line change
@@ -1720,6 +1720,35 @@ DLLEXPORT jl_value_t *jl_tupletype_fill(size_t n, jl_value_t *v)
17201720
return p;
17211721
}
17221722

1723+
static int contains_unions(jl_value_t *type)
1724+
{
1725+
if (jl_is_uniontype(type)) return 1;
1726+
if (jl_is_typector(type)) return contains_unions(((jl_typector_t*)type)->body);
1727+
if (!jl_is_datatype(type)) return 0;
1728+
int i;
1729+
for(i=0; i < jl_nparams(type); i++) {
1730+
if (contains_unions(jl_tparam(type,i)))
1731+
return 1;
1732+
}
1733+
return 0;
1734+
}
1735+
1736+
// this function determines whether a type is simple enough to form
1737+
// a total order based on UIDs and object_id.
1738+
static int is_typekey_ordered(jl_value_t **key, size_t n)
1739+
{
1740+
size_t i;
1741+
for(i=0; i < n; i++) {
1742+
jl_value_t *k = key[i];
1743+
if (jl_is_type(k) &&
1744+
!(jl_is_datatype(k) && (((jl_datatype_t*)k)->uid ||
1745+
k == ((jl_datatype_t*)k)->name->primary ||
1746+
(!jl_has_typevars_(k,1) && !contains_unions(k)))))
1747+
return 0;
1748+
}
1749+
return 1;
1750+
}
1751+
17231752
// ordered comparison of types
17241753
static int typekey_compare(jl_datatype_t *tt, jl_value_t **key, size_t n)
17251754
{
@@ -1729,49 +1758,78 @@ static int typekey_compare(jl_datatype_t *tt, jl_value_t **key, size_t n)
17291758
if (n < tnp) return -1;
17301759
if (n > tnp) return 1;
17311760
for(j=0; j < n; j++) {
1732-
jl_value_t *tj = jl_svecref(tt->parameters,j);
1733-
jl_value_t *kj = key[j];
1761+
jl_value_t *kj = key[j], *tj = jl_svecref(tt->parameters,j);
17341762
if (tj != kj) {
1735-
if (!type_eqv__(tj, kj, 1)) {
1736-
uptrint_t tid =
1737-
(jl_is_datatype(tj) && ((jl_datatype_t*)tj)->uid) ? ((jl_datatype_t*)tj)->uid : jl_object_id(tj);
1738-
uptrint_t kid =
1739-
(jl_is_datatype(kj) && ((jl_datatype_t*)kj)->uid) ? ((jl_datatype_t*)kj)->uid : jl_object_id(kj);
1763+
int dtt = jl_is_datatype(tj);
1764+
int dtk = jl_is_datatype(kj);
1765+
if (!dtt && !dtk && jl_egal(tj, kj))
1766+
continue;
1767+
uptrint_t tid = (dtt && ((jl_datatype_t*)tj)->uid ? ((jl_datatype_t*)tj)->uid : jl_object_id(tj));
1768+
uptrint_t kid = (dtk && ((jl_datatype_t*)kj)->uid ? ((jl_datatype_t*)kj)->uid : jl_object_id(kj));
1769+
if (kid != tid)
17401770
return kid < tid ? -1 : 1;
1741-
}
17421771
}
17431772
}
17441773
return 0;
17451774
}
17461775

1747-
// look up a type in a cache by binary search.
1776+
static int typekey_eq(jl_datatype_t *tt, jl_value_t **key, size_t n)
1777+
{
1778+
size_t j;
1779+
size_t tnp = jl_nparams(tt);
1780+
if (n != tnp) return 0;
1781+
for(j=0; j < n; j++) {
1782+
jl_value_t *kj = key[j], *tj = jl_svecref(tt->parameters,j);
1783+
if (tj != kj && !type_eqv__(tj, kj, 1))
1784+
return 0;
1785+
}
1786+
return 1;
1787+
}
1788+
1789+
// look up a type in a cache by binary or linear search.
17481790
// if found, returns the index of the found item. if not found, returns
17491791
// ~n, where n is the index where the type should be inserted.
1750-
static ssize_t lookup_type_idx(jl_typename_t *tn, jl_value_t **key, size_t n)
1792+
static ssize_t lookup_type_idx(jl_typename_t *tn, jl_value_t **key, size_t n, int ordered)
17511793
{
17521794
if (n==0) return -1;
1753-
jl_value_t *cache = tn->cache;
1754-
jl_value_t **data = jl_svec_data(cache);
1755-
size_t cl = jl_svec_len(cache);
1756-
ssize_t lo = -1;
1757-
ssize_t hi = cl;
1758-
while (lo < hi-1) {
1759-
ssize_t m = ((size_t)(lo+hi))>>1;
1760-
jl_datatype_t *tt = (jl_datatype_t*)data[m];
1761-
int cmp = typekey_compare(tt, key, n);
1762-
if (cmp == 0) return m;
1763-
if (cmp < 0)
1764-
hi = m;
1765-
else
1766-
lo = m;
1795+
if (ordered) {
1796+
jl_svec_t *cache = tn->cache;
1797+
jl_value_t **data = jl_svec_data(cache);
1798+
size_t cl = jl_svec_len(cache);
1799+
ssize_t lo = -1;
1800+
ssize_t hi = cl;
1801+
while (lo < hi-1) {
1802+
ssize_t m = ((size_t)(lo+hi))>>1;
1803+
jl_datatype_t *tt = (jl_datatype_t*)data[m];
1804+
int cmp = typekey_compare(tt, key, n);
1805+
if (cmp == 0) return m;
1806+
if (cmp < 0)
1807+
hi = m;
1808+
else
1809+
lo = m;
1810+
}
1811+
return ~hi;
1812+
}
1813+
else {
1814+
jl_svec_t *cache = tn->linearcache;
1815+
jl_value_t **data = jl_svec_data(cache);
1816+
size_t cl = jl_svec_len(cache);
1817+
ssize_t i;
1818+
for(i=0; i < cl; i++) {
1819+
jl_datatype_t *tt = (jl_datatype_t*)data[i];
1820+
if (tt == NULL) return ~i;
1821+
if (typekey_eq(tt, key, n))
1822+
return i;
1823+
}
1824+
return ~cl;
17671825
}
1768-
return ~hi;
17691826
}
17701827

17711828
static jl_value_t *lookup_type(jl_typename_t *tn, jl_value_t **key, size_t n)
17721829
{
1773-
ssize_t idx = lookup_type_idx(tn, key, n);
1774-
return (idx < 0) ? NULL : jl_svecref(tn->cache, idx);
1830+
int ord = is_typekey_ordered(key, n);
1831+
ssize_t idx = lookup_type_idx(tn, key, n, ord);
1832+
return (idx < 0) ? NULL : jl_svecref(ord ? tn->cache : tn->linearcache, idx);
17751833
}
17761834

17771835
static int t_uid_ctr = 1;
@@ -1809,21 +1867,28 @@ static int is_cacheable(jl_datatype_t *type)
18091867
return 1;
18101868
}
18111869

1812-
static void cache_insert_type(jl_value_t *type, ssize_t insert_at)
1870+
static void cache_insert_type(jl_value_t *type, ssize_t insert_at, int ordered)
18131871
{
18141872
assert(jl_is_datatype(type));
18151873
// assign uid
18161874
if (!jl_is_abstracttype(type) && ((jl_datatype_t*)type)->uid==0)
18171875
((jl_datatype_t*)type)->uid = jl_assign_type_uid();
1818-
jl_value_t *cache = ((jl_datatype_t*)type)->name->cache;
1876+
jl_svec_t *cache;
1877+
if (ordered)
1878+
cache = ((jl_datatype_t*)type)->name->cache;
1879+
else
1880+
cache = ((jl_datatype_t*)type)->name->linearcache;
18191881
assert(jl_is_svec(cache));
18201882
size_t n = jl_svec_len(cache);
18211883
if (n==0 || jl_svecref(cache,n-1) != NULL) {
18221884
jl_svec_t *nc = jl_alloc_svec(n < 8 ? 8 : (n*3)>>1);
18231885
memcpy(jl_svec_data(nc), jl_svec_data(cache), sizeof(void*) * n);
1824-
((jl_datatype_t*)type)->name->cache = (jl_value_t*)nc;
1886+
if (ordered)
1887+
((jl_datatype_t*)type)->name->cache = nc;
1888+
else
1889+
((jl_datatype_t*)type)->name->linearcache = nc;
18251890
gc_wb(((jl_datatype_t*)type)->name, nc);
1826-
cache = (jl_value_t*)nc;
1891+
cache = nc;
18271892
n = jl_svec_len(nc);
18281893
}
18291894
jl_value_t **p = jl_svec_data(cache);
@@ -1842,11 +1907,12 @@ static void cache_insert_type(jl_value_t *type, ssize_t insert_at)
18421907
jl_value_t *jl_cache_type_(jl_datatype_t *type)
18431908
{
18441909
if (is_cacheable(type)) {
1910+
int ord = is_typekey_ordered(jl_svec_data(type->parameters), jl_svec_len(type->parameters));
18451911
ssize_t idx = lookup_type_idx(type->name, type->parameters->data,
1846-
jl_svec_len(type->parameters));
1912+
jl_svec_len(type->parameters), ord);
18471913
if (idx >= 0)
1848-
return jl_svecref(type->name->cache, idx);
1849-
cache_insert_type((jl_value_t*)type, ~idx);
1914+
return jl_svecref(ord ? type->name->cache : type->name->linearcache, idx);
1915+
cache_insert_type((jl_value_t*)type, ~idx, ord);
18501916
}
18511917
return (jl_value_t*)type;
18521918
}
@@ -1918,6 +1984,8 @@ static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **i
19181984
ndt->size = 0;
19191985
ndt->alignment = 1;
19201986

1987+
if (cacheable) jl_cache_type_(ndt);
1988+
19211989
if (istuple)
19221990
ndt->super = jl_any_type;
19231991
else
@@ -1953,10 +2021,8 @@ static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **i
19532021
ndt->ninitialized = ntp;
19542022
else
19552023
ndt->ninitialized = dt->ninitialized;
1956-
if (cacheable) jl_cache_type_(ndt);
1957-
jl_value_t *result = (jl_value_t*)ndt;
19582024
JL_GC_POP();
1959-
return result;
2025+
return (jl_value_t*)ndt;
19602026
}
19612027

19622028
static jl_tupletype_t *jl_apply_tuple_type_v_(jl_value_t **p, size_t np, jl_svec_t *params)
@@ -2098,7 +2164,7 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_value_t **env, size_t n,
20982164
jl_value_t *lkup = NULL;
20992165
while (tmp != NULL) {
21002166
if (tmp->tt->name==tn && ntp==jl_svec_len(tmp->tt->parameters) &&
2101-
typekey_compare(tmp->tt, iparams, ntp)==0) {
2167+
typekey_eq(tmp->tt, iparams, ntp)) {
21022168
lkup = (jl_value_t*)tmp->tt;
21032169
break;
21042170
}
@@ -2947,8 +3013,7 @@ void jl_init_types(void)
29473013
// create base objects
29483014
jl_datatype_type = jl_new_uninitialized_datatype(9);
29493015
jl_set_typeof(jl_datatype_type, jl_datatype_type);
2950-
jl_typename_type = jl_new_uninitialized_datatype(5);
2951-
jl_typename_type = jl_new_uninitialized_datatype(6);
3016+
jl_typename_type = jl_new_uninitialized_datatype(7);
29523017
jl_sym_type = jl_new_uninitialized_datatype(0);
29533018
jl_symbol_type = jl_sym_type;
29543019
jl_simplevector_type = jl_new_uninitialized_datatype(1);
@@ -2993,11 +3058,13 @@ void jl_init_types(void)
29933058
jl_typename_type->name->primary = (jl_value_t*)jl_typename_type;
29943059
jl_typename_type->super = jl_any_type;
29953060
jl_typename_type->parameters = jl_emptysvec;
2996-
jl_typename_type->name->names = jl_svec(6, jl_symbol("name"), jl_symbol("module"),
3061+
jl_typename_type->name->names = jl_svec(7, jl_symbol("name"), jl_symbol("module"),
29973062
jl_symbol("names"), jl_symbol("primary"),
2998-
jl_symbol("cache"), jl_symbol("uid"));
2999-
jl_typename_type->types = jl_svec(6, jl_sym_type, jl_any_type, jl_simplevector_type,
3000-
jl_type_type, jl_any_type, jl_any_type);
3063+
jl_symbol("cache"), jl_symbol("linearcache"),
3064+
jl_symbol("uid"));
3065+
jl_typename_type->types = jl_svec(7, jl_sym_type, jl_any_type, jl_simplevector_type,
3066+
jl_type_type, jl_simplevector_type, jl_simplevector_type,
3067+
jl_any_type);
30013068
jl_typename_type->uid = jl_assign_type_uid();
30023069
jl_typename_type->instance = NULL;
30033070
jl_typename_type->struct_decl = NULL;
@@ -3287,7 +3354,7 @@ void jl_init_types(void)
32873354
jl_svecset(jl_function_type->types, 0, pointer_void);
32883355
jl_svecset(jl_tvar_type->types, 3, (jl_value_t*)jl_bool_type);
32893356
jl_svecset(jl_simplevector_type->types, 0, jl_long_type);
3290-
jl_svecset(jl_typename_type->types, 5, jl_long_type);
3357+
jl_svecset(jl_typename_type->types, 6, jl_long_type);
32913358

32923359
jl_compute_field_offsets(jl_datatype_type);
32933360
jl_compute_field_offsets(jl_typename_type);

‎src/julia.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ typedef struct {
250250
// a type alias, for example, might make a type constructor that is
251251
// not the original.
252252
jl_value_t *primary;
253-
jl_value_t *cache;
253+
jl_svec_t *cache; // sorted array
254+
jl_svec_t *linearcache; // unsorted array
254255
ptrint_t uid;
255256
} jl_typename_t;
256257

‎src/toplevel.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,8 @@ void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super)
622622
tt->super = (jl_datatype_t*)super;
623623
gc_wb(tt, tt->super);
624624
if (jl_svec_len(tt->parameters) > 0) {
625-
tt->name->cache = (jl_value_t*)jl_emptysvec;
625+
tt->name->cache = jl_emptysvec;
626+
tt->name->linearcache = jl_emptysvec;
626627
jl_reinstantiate_inner_types(tt);
627628
}
628629
}

0 commit comments

Comments
 (0)