Skip to content

Commit 33afb81

Browse files
vtjnashKeno
andauthored
remove svec(#null) from the language (#46975)
This was not supported, and almost never used, so audit all places it could happen and avoid it at the source. Fix #46784 Co-authored-by: Keno Fischer <keno@juliacomputing.com>
1 parent e34860e commit 33afb81

File tree

12 files changed

+57
-70
lines changed

12 files changed

+57
-70
lines changed

base/essentials.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,10 @@ end
690690

691691
@eval getindex(v::SimpleVector, i::Int) = Core._svec_ref($(Expr(:boundscheck)), v, i)
692692
function length(v::SimpleVector)
693-
return ccall(:jl_svec_len, Int, (Any,), v)
693+
t = @_gc_preserve_begin v
694+
len = unsafe_load(Ptr{Int}(pointer_from_objref(v)))
695+
@_gc_preserve_end t
696+
return len
694697
end
695698
firstindex(v::SimpleVector) = 1
696699
lastindex(v::SimpleVector) = length(v)
@@ -745,7 +748,7 @@ function isassigned end
745748

746749
function isassigned(v::SimpleVector, i::Int)
747750
@boundscheck 1 <= i <= length(v) || return false
748-
return ccall(:jl_svec_isassigned, Bool, (Any, Int), v, i - 1)
751+
return true
749752
end
750753

751754

src/builtins.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ STATIC_INLINE void _grow_to(jl_value_t **root, jl_value_t ***oldargs, jl_svec_t
569569
*n_alloc = newalloc;
570570
}
571571

572-
static jl_value_t *do_apply( jl_value_t **args, uint32_t nargs, jl_value_t *iterate)
572+
static jl_value_t *do_apply(jl_value_t **args, uint32_t nargs, jl_value_t *iterate)
573573
{
574574
jl_function_t *f = args[0];
575575
if (nargs == 2) {

src/ccall.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ TRANSFORMED_CCALL_STAT(jl_set_next_task);
2828
TRANSFORMED_CCALL_STAT(jl_sigatomic_begin);
2929
TRANSFORMED_CCALL_STAT(jl_sigatomic_end);
3030
TRANSFORMED_CCALL_STAT(jl_svec_len);
31-
TRANSFORMED_CCALL_STAT(jl_svec_isassigned);
3231
TRANSFORMED_CCALL_STAT(jl_svec_ref);
3332
TRANSFORMED_CCALL_STAT(jl_array_isassigned);
3433
TRANSFORMED_CCALL_STAT(jl_string_ptr);
@@ -1687,28 +1686,6 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
16871686
JL_GC_POP();
16881687
return mark_or_box_ccall_result(ctx, len, retboxed, rt, unionall, static_rt);
16891688
}
1690-
else if (is_libjulia_func(jl_svec_isassigned) &&
1691-
argv[1].typ == (jl_value_t*)jl_long_type) {
1692-
++CCALL_STAT(jl_svec_isassigned);
1693-
assert(!isVa && !llvmcall && nccallargs == 2);
1694-
const jl_cgval_t &svecv = argv[0];
1695-
const jl_cgval_t &idxv = argv[1];
1696-
Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), idxv, (jl_value_t*)jl_long_type);
1697-
idx = ctx.builder.CreateAdd(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
1698-
auto ptr = emit_bitcast(ctx, boxed(ctx, svecv), ctx.types().T_pprjlvalue);
1699-
Value *slot_addr = ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue,
1700-
decay_derived(ctx, ptr), idx);
1701-
LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, slot_addr,
1702-
Align(sizeof(void*)));
1703-
load->setAtomic(AtomicOrdering::Unordered);
1704-
// Only mark with TBAA if we are sure about the type.
1705-
// This could otherwise be in a dead branch
1706-
if (svecv.typ == (jl_value_t*)jl_simplevector_type)
1707-
tbaa_decorate(ctx.tbaa().tbaa_const, load);
1708-
Value *res = ctx.builder.CreateZExt(ctx.builder.CreateICmpNE(load, Constant::getNullValue(ctx.types().T_prjlvalue)), getInt8Ty(ctx.builder.getContext()));
1709-
JL_GC_POP();
1710-
return mark_or_box_ccall_result(ctx, res, retboxed, rt, unionall, static_rt);
1711-
}
17121689
else if (is_libjulia_func(jl_svec_ref) && argv[1].typ == (jl_value_t*)jl_long_type) {
17131690
++CCALL_STAT(jl_svec_ref);
17141691
assert(lrt == ctx.types().T_prjlvalue);
@@ -1727,7 +1704,6 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17271704
// This could otherwise be in a dead branch
17281705
if (svecv.typ == (jl_value_t*)jl_simplevector_type)
17291706
tbaa_decorate(ctx.tbaa().tbaa_const, load);
1730-
null_pointer_check(ctx, load);
17311707
JL_GC_POP();
17321708
return mark_or_box_ccall_result(ctx, load, retboxed, rt, unionall, static_rt);
17331709
}

src/gf.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,7 @@ static jl_method_instance_t *cache_method(
11511151
// NULL, jl_emptysvec, /*guard*/NULL, jl_cachearg_offset(mt), other->min_world, other->max_world);
11521152
}
11531153
}
1154+
assert(guards == jl_svec_len(guardsigs));
11541155
}
11551156
if (!cache_with_orig) {
11561157
// determined above that there's no ambiguity in also using compilationsig as the cacheablesig

src/jl_exported_funcs.inc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,6 @@
453453
XX(jl_svec2) \
454454
XX(jl_svec_copy) \
455455
XX(jl_svec_fill) \
456-
XX(jl_svec_isassigned) \
457456
XX(jl_svec_ref) \
458457
XX(jl_switch) \
459458
XX(jl_switchto) \

src/jltypes.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -657,9 +657,9 @@ static jl_datatype_t *lookup_type_set(jl_svec_t *cache, jl_value_t **key, size_t
657657
size_t iter = 0;
658658
do {
659659
jl_datatype_t *val = jl_atomic_load_relaxed(&tab[index]);
660-
if (val == NULL)
660+
if ((jl_value_t*)val == jl_nothing)
661661
return NULL;
662-
if ((jl_value_t*)val != jl_nothing && val->hash == hv && typekey_eq(val, key, n))
662+
if (val->hash == hv && typekey_eq(val, key, n))
663663
return val;
664664
index = (index + 1) & (sz - 1);
665665
iter++;
@@ -680,9 +680,9 @@ static jl_datatype_t *lookup_type_setvalue(jl_svec_t *cache, jl_value_t *key1, j
680680
size_t iter = 0;
681681
do {
682682
jl_datatype_t *val = jl_atomic_load_relaxed(&tab[index]);
683-
if (val == NULL)
683+
if ((jl_value_t*)val == jl_nothing)
684684
return NULL;
685-
if ((jl_value_t*)val != jl_nothing && val->hash == hv && typekeyvalue_eq(val, key1, key, n, leaf))
685+
if (val->hash == hv && typekeyvalue_eq(val, key1, key, n, leaf))
686686
return val;
687687
index = (index + 1) & (sz - 1);
688688
iter++;
@@ -702,7 +702,7 @@ static ssize_t lookup_type_idx_linear(jl_svec_t *cache, jl_value_t **key, size_t
702702
ssize_t i;
703703
for (i = 0; i < cl; i++) {
704704
jl_datatype_t *tt = jl_atomic_load_relaxed(&data[i]);
705-
if (tt == NULL)
705+
if ((jl_value_t*)tt == jl_nothing)
706706
return ~i;
707707
if (typekey_eq(tt, key, n))
708708
return i;
@@ -719,7 +719,7 @@ static ssize_t lookup_type_idx_linearvalue(jl_svec_t *cache, jl_value_t *key1, j
719719
ssize_t i;
720720
for (i = 0; i < cl; i++) {
721721
jl_datatype_t *tt = jl_atomic_load_relaxed(&data[i]);
722-
if (tt == NULL)
722+
if ((jl_value_t*)tt == jl_nothing)
723723
return ~i;
724724
if (typekeyvalue_eq(tt, key1, key, n, 1))
725725
return i;
@@ -777,7 +777,7 @@ static int cache_insert_type_set_(jl_svec_t *a, jl_datatype_t *val, uint_t hv, i
777777
size_t maxprobe = max_probe(sz);
778778
do {
779779
jl_value_t *tab_i = jl_atomic_load_relaxed(&tab[index]);
780-
if (tab_i == NULL || tab_i == jl_nothing) {
780+
if (tab_i == jl_nothing) {
781781
if (atomic)
782782
jl_atomic_store_release(&tab[index], (jl_value_t*)val);
783783
else
@@ -792,8 +792,6 @@ static int cache_insert_type_set_(jl_svec_t *a, jl_datatype_t *val, uint_t hv, i
792792
return 0;
793793
}
794794

795-
static jl_svec_t *cache_rehash_set(jl_svec_t *a, size_t newsz);
796-
797795
static void cache_insert_type_set(jl_datatype_t *val, uint_t hv)
798796
{
799797
jl_svec_t *a = jl_atomic_load_relaxed(&val->name->cache);
@@ -820,17 +818,17 @@ static void cache_insert_type_set(jl_datatype_t *val, uint_t hv)
820818
}
821819
}
822820

823-
static jl_svec_t *cache_rehash_set(jl_svec_t *a, size_t newsz)
821+
jl_svec_t *cache_rehash_set(jl_svec_t *a, size_t newsz)
824822
{
825823
jl_value_t **ol = jl_svec_data(a);
826824
size_t sz = jl_svec_len(a);
827825
while (1) {
828826
size_t i;
829-
jl_svec_t *newa = jl_alloc_svec(newsz);
827+
jl_svec_t *newa = jl_svec_fill(newsz, jl_nothing);
830828
JL_GC_PUSH1(&newa);
831829
for (i = 0; i < sz; i += 1) {
832830
jl_value_t *val = ol[i];
833-
if (val != NULL && val != jl_nothing) {
831+
if (val != jl_nothing) {
834832
uint_t hv = ((jl_datatype_t*)val)->hash;
835833
if (!cache_insert_type_set_(newa, (jl_datatype_t*)val, hv, 0)) {
836834
break;
@@ -849,15 +847,15 @@ static void cache_insert_type_linear(jl_datatype_t *type, ssize_t insert_at)
849847
jl_svec_t *cache = jl_atomic_load_relaxed(&type->name->linearcache);
850848
assert(jl_is_svec(cache));
851849
size_t n = jl_svec_len(cache);
852-
if (n == 0 || jl_svecref(cache, n - 1) != NULL) {
853-
jl_svec_t *nc = jl_alloc_svec(n < 8 ? 8 : (n*3)>>1);
850+
if (n == 0 || jl_svecref(cache, n - 1) != jl_nothing) {
851+
jl_svec_t *nc = jl_svec_fill(n < 4 ? 4 : n * 2, jl_nothing);
854852
memcpy(jl_svec_data(nc), jl_svec_data(cache), sizeof(void*) * n);
855853
jl_atomic_store_release(&type->name->linearcache, nc);
856854
jl_gc_wb(type->name, nc);
857855
cache = nc;
858856
n = jl_svec_len(nc);
859857
}
860-
assert(jl_svecref(cache, insert_at) == NULL);
858+
assert(jl_svecref(cache, insert_at) == jl_nothing);
861859
jl_svecset(cache, insert_at, (jl_value_t*)type); // todo: make this an atomic-store
862860
}
863861

src/julia_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ jl_vararg_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n);
685685
void jl_reinstantiate_inner_types(jl_datatype_t *t);
686686
jl_datatype_t *jl_lookup_cache_type_(jl_datatype_t *type);
687687
void jl_cache_type_(jl_datatype_t *type);
688+
jl_svec_t *cache_rehash_set(jl_svec_t *a, size_t newsz);
688689
void set_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *rhs, int isatomic) JL_NOTSAFEPOINT;
689690
jl_value_t *swap_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *rhs, int isatomic);
690691
jl_value_t *modify_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *op, jl_value_t *rhs, int isatomic);
@@ -1430,7 +1431,6 @@ int jl_typemap_intersection_visitor(jl_typemap_t *a, int offs, struct typemap_in
14301431

14311432
// For codegen only.
14321433
JL_DLLEXPORT size_t (jl_svec_len)(jl_svec_t *t) JL_NOTSAFEPOINT;
1433-
JL_DLLEXPORT int8_t jl_svec_isassigned(jl_svec_t *t JL_PROPAGATES_ROOT, ssize_t i) JL_NOTSAFEPOINT;
14341434
JL_DLLEXPORT jl_value_t *jl_svec_ref(jl_svec_t *t JL_PROPAGATES_ROOT, ssize_t i);
14351435

14361436

src/simplevector.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,9 @@ JL_DLLEXPORT size_t (jl_svec_len)(jl_svec_t *t) JL_NOTSAFEPOINT
9393
return jl_svec_len(t);
9494
}
9595

96-
JL_DLLEXPORT int8_t jl_svec_isassigned(jl_svec_t *t JL_PROPAGATES_ROOT, ssize_t i) JL_NOTSAFEPOINT
97-
{
98-
return jl_svecref(t, (size_t)i) != NULL;
99-
}
100-
10196
JL_DLLEXPORT jl_value_t *jl_svec_ref(jl_svec_t *t JL_PROPAGATES_ROOT, ssize_t i)
10297
{
10398
jl_value_t *v = jl_svecref(t, (size_t)i);
104-
if (__unlikely(v == NULL))
105-
jl_throw(jl_undefref_exception);
99+
assert(v != NULL);
106100
return v;
107101
}

src/staticdata.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,7 +1646,7 @@ static void jl_scan_type_cache_gv(jl_serializer_state *s, jl_svec_t *cache)
16461646
size_t l = jl_svec_len(cache), i;
16471647
for (i = 0; i < l; i++) {
16481648
jl_value_t *ti = jl_svecref(cache, i);
1649-
if (ti == NULL || ti == jl_nothing)
1649+
if (ti == jl_nothing)
16501650
continue;
16511651
if (jl_get_llvm_gv(native_functions, ti)) {
16521652
jl_serialize_value(s, ti);
@@ -1660,31 +1660,35 @@ static void jl_scan_type_cache_gv(jl_serializer_state *s, jl_svec_t *cache)
16601660
}
16611661

16621662
// remove cached types not referenced in the stream
1663-
static void jl_prune_type_cache_hash(jl_svec_t *cache)
1663+
static jl_svec_t *jl_prune_type_cache_hash(jl_svec_t *cache) JL_GC_DISABLED
16641664
{
16651665
size_t l = jl_svec_len(cache), i;
16661666
for (i = 0; i < l; i++) {
16671667
jl_value_t *ti = jl_svecref(cache, i);
1668-
if (ti == NULL || ti == jl_nothing)
1668+
if (ti == jl_nothing)
16691669
continue;
16701670
if (ptrhash_get(&backref_table, ti) == HT_NOTFOUND)
16711671
jl_svecset(cache, i, jl_nothing);
16721672
}
1673+
void *idx = ptrhash_get(&backref_table, cache);
1674+
ptrhash_remove(&backref_table, cache);
1675+
cache = cache_rehash_set(cache, l);
1676+
ptrhash_put(&backref_table, cache, idx);
1677+
return cache;
16731678
}
16741679

16751680
static void jl_prune_type_cache_linear(jl_svec_t *cache)
16761681
{
16771682
size_t l = jl_svec_len(cache), ins = 0, i;
16781683
for (i = 0; i < l; i++) {
16791684
jl_value_t *ti = jl_svecref(cache, i);
1680-
if (ti == NULL)
1685+
if (ti == jl_nothing)
16811686
break;
16821687
if (ptrhash_get(&backref_table, ti) != HT_NOTFOUND)
16831688
jl_svecset(cache, ins++, ti);
16841689
}
1685-
if (i > ins) {
1686-
memset(&jl_svec_data(cache)[ins], 0, (i - ins) * sizeof(jl_value_t*));
1687-
}
1690+
while (ins < l)
1691+
jl_svecset(cache, ins++, jl_nothing);
16881692
}
16891693

16901694
static jl_value_t *strip_codeinfo_meta(jl_method_t *m, jl_value_t *ci_, int orig)
@@ -1958,7 +1962,8 @@ static void jl_save_system_image_to_stream(ios_t *f) JL_GC_DISABLED
19581962
// built-in type caches
19591963
for (i = 0; i < typenames.len; i++) {
19601964
jl_typename_t *tn = (jl_typename_t*)typenames.items[i];
1961-
jl_prune_type_cache_hash(tn->cache);
1965+
tn->cache = jl_prune_type_cache_hash(tn->cache);
1966+
jl_gc_wb(tn, tn->cache);
19621967
jl_prune_type_cache_linear(tn->linearcache);
19631968
}
19641969
arraylist_free(&typenames);

src/subtype.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3547,17 +3547,26 @@ jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t *
35473547
}
35483548
}
35493549
if (sz == 0 && szb > 0) {
3550-
while (jl_is_unionall(b)) {
3551-
env[i++] = (jl_value_t*)((jl_unionall_t*)b)->var;
3552-
b = ((jl_unionall_t*)b)->body;
3550+
jl_unionall_t *ub = (jl_unionall_t*)b;
3551+
while (jl_is_unionall(ub)) {
3552+
env[i++] = (jl_value_t*)ub->var;
3553+
ub = (jl_unionall_t*)ub->body;
35533554
}
35543555
sz = szb;
35553556
}
35563557
if (penv) {
35573558
jl_svec_t *e = jl_alloc_svec(sz);
35583559
*penv = e;
3559-
for(i=0; i < sz; i++)
3560+
for (i = 0; i < sz; i++)
35603561
jl_svecset(e, i, env[i]);
3562+
jl_unionall_t *ub = (jl_unionall_t*)b;
3563+
for (i = 0; i < sz; i++) {
3564+
assert(jl_is_unionall(ub));
3565+
// TODO: assert(env[i] != NULL);
3566+
if (env[i] == NULL)
3567+
env[i] = (jl_value_t*)ub->var;
3568+
ub = (jl_unionall_t*)ub->body;
3569+
}
35613570
}
35623571
bot:
35633572
JL_GC_POP();
@@ -3601,6 +3610,14 @@ int jl_subtype_matching(jl_value_t *a, jl_value_t *b, jl_svec_t **penv)
36013610
*penv = e;
36023611
for (i = 0; i < szb; i++)
36033612
jl_svecset(e, i, env[i]);
3613+
jl_unionall_t *ub = (jl_unionall_t*)b;
3614+
for (i = 0; i < szb; i++) {
3615+
assert(jl_is_unionall(ub));
3616+
// TODO: assert(env[i] != NULL);
3617+
if (env[i] == NULL)
3618+
env[i] = (jl_value_t*)ub->var;
3619+
ub = (jl_unionall_t*)ub->body;
3620+
}
36043621
}
36053622
JL_GC_POP();
36063623
return sub;

test/core.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ end
784784
mutable struct Type11167{T,N} end
785785
function count11167()
786786
let cache = Type11167.body.body.name.cache
787-
return sum(i -> isassigned(cache, i), 0:length(cache))
787+
return count(!isnothing, cache)
788788
end
789789
end
790790
@test count11167() == 0

test/show.jl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,12 +1275,6 @@ end
12751275
let repr = sprint(dump, Core.svec())
12761276
@test repr == "empty SimpleVector\n"
12771277
end
1278-
let sv = Core.svec(:a, :b, :c)
1279-
# unsafe replacement of :c with #undef to test handling of incomplete SimpleVectors
1280-
unsafe_store!(convert(Ptr{Ptr{Cvoid}}, Base.pointer_from_objref(sv)) + 3 * sizeof(Ptr), C_NULL)
1281-
repr = sprint(dump, sv)
1282-
@test repr == "SimpleVector\n 1: Symbol a\n 2: Symbol b\n 3: #undef\n"
1283-
end
12841278
let repr = sprint(dump, sin)
12851279
@test repr == "sin (function of type typeof(sin))\n"
12861280
end

0 commit comments

Comments
 (0)