Skip to content

Commit 1875957

Browse files
authored
Merge pull request #23367 from JuliaLang/jq/bitsunions
Ensure immutable isbits Union fields get set correctly
2 parents 4d9b107 + 2bb430e commit 1875957

13 files changed

+568
-389
lines changed

base/atomics.jl

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -345,28 +345,31 @@ for typ in atomictypes
345345
irt = Base.libllvm_version >= v"3.6" ? "$ilt, $ilt*" : "$ilt*"
346346
@eval getindex(x::Atomic{$typ}) =
347347
llvmcall($"""
348-
%rv = load atomic $rt %0 acquire, align $(alignment(typ))
348+
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
349+
%rv = load atomic $rt %ptr acquire, align $(alignment(typ))
349350
ret $lt %rv
350351
""", $typ, Tuple{Ptr{$typ}}, unsafe_convert(Ptr{$typ}, x))
351352
@eval setindex!(x::Atomic{$typ}, v::$typ) =
352353
llvmcall($"""
353-
store atomic $lt %1, $lt* %0 release, align $(alignment(typ))
354+
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
355+
store atomic $lt %1, $lt* %ptr release, align $(alignment(typ))
354356
ret void
355-
""", Void, Tuple{Ptr{$typ},$typ}, unsafe_convert(Ptr{$typ}, x), v)
357+
""", Void, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v)
356358

357359
# Note: atomic_cas! succeeded (i.e. it stored "new") if and only if the result is "cmp"
358360
if typ <: Integer
359361
@eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) =
360362
llvmcall($"""
361-
%rs = cmpxchg $lt* %0, $lt %1, $lt %2 acq_rel acquire
363+
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
364+
%rs = cmpxchg $lt* %ptr, $lt %1, $lt %2 acq_rel acquire
362365
%rv = extractvalue { $lt, i1 } %rs, 0
363366
ret $lt %rv
364367
""", $typ, Tuple{Ptr{$typ},$typ,$typ},
365368
unsafe_convert(Ptr{$typ}, x), cmp, new)
366369
else
367370
@eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) =
368371
llvmcall($"""
369-
%iptr = bitcast $lt* %0 to $ilt*
372+
%iptr = inttoptr i$WORD_SIZE %0 to $ilt*
370373
%icmp = bitcast $lt %1 to $ilt
371374
%inew = bitcast $lt %2 to $ilt
372375
%irs = cmpxchg $ilt* %iptr, $ilt %icmp, $ilt %inew acq_rel acquire
@@ -387,14 +390,15 @@ for typ in atomictypes
387390
if typ <: Integer
388391
@eval $fn(x::Atomic{$typ}, v::$typ) =
389392
llvmcall($"""
390-
%rv = atomicrmw $rmw $lt* %0, $lt %1 acq_rel
393+
%ptr = inttoptr i$WORD_SIZE %0 to $lt*
394+
%rv = atomicrmw $rmw $lt* %ptr, $lt %1 acq_rel
391395
ret $lt %rv
392396
""", $typ, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v)
393397
else
394398
rmwop == :xchg || continue
395399
@eval $fn(x::Atomic{$typ}, v::$typ) =
396400
llvmcall($"""
397-
%iptr = bitcast $lt* %0 to $ilt*
401+
%iptr = inttoptr i$WORD_SIZE %0 to $ilt*
398402
%ival = bitcast $lt %1 to $ilt
399403
%irv = atomicrmw $rmw $ilt* %iptr, $ilt %ival acq_rel
400404
%rv = bitcast $ilt %irv to $lt

base/fastmath.jl

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -296,34 +296,18 @@ asin_fast(x::FloatTypes) = asin(x)
296296

297297
# explicit implementations
298298

299-
# FIXME: Change to `ccall((:sincos, libm))` when `Ref` calling convention can be
300-
# stack allocated.
301299
@inline function sincos_fast(v::Float64)
302-
return Base.llvmcall("""
303-
%f = bitcast i8 *%1 to void (double, double *, double *)*
304-
%ps = alloca double
305-
%pc = alloca double
306-
call void %f(double %0, double *%ps, double *%pc)
307-
%s = load double, double* %ps
308-
%c = load double, double* %pc
309-
%res0 = insertvalue [2 x double] undef, double %s, 0
310-
%res = insertvalue [2 x double] %res0, double %c, 1
311-
ret [2 x double] %res
312-
""", Tuple{Float64,Float64}, Tuple{Float64,Ptr{Void}}, v, cglobal((:sincos, libm)))
300+
s = Ref{Cdouble}()
301+
c = Ref{Cdouble}()
302+
ccall((:sincos, libm), Void, (Cdouble, Ptr{Cdouble}, Ptr{Cdouble}), v, s, c)
303+
return (s[], c[])
313304
end
314305

315306
@inline function sincos_fast(v::Float32)
316-
return Base.llvmcall("""
317-
%f = bitcast i8 *%1 to void (float, float *, float *)*
318-
%ps = alloca float
319-
%pc = alloca float
320-
call void %f(float %0, float *%ps, float *%pc)
321-
%s = load float, float* %ps
322-
%c = load float, float* %pc
323-
%res0 = insertvalue [2 x float] undef, float %s, 0
324-
%res = insertvalue [2 x float] %res0, float %c, 1
325-
ret [2 x float] %res
326-
""", Tuple{Float32,Float32}, Tuple{Float32,Ptr{Void}}, v, cglobal((:sincosf, libm)))
307+
s = Ref{Cfloat}()
308+
c = Ref{Cfloat}()
309+
ccall((:sincosf, libm), Void, (Cfloat, Ptr{Cfloat}, Ptr{Cfloat}), v, s, c)
310+
return (s[], c[])
327311
end
328312

329313
@inline function sincos_fast(v::Float16)

src/builtins.c

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -77,30 +77,40 @@ static int NOINLINE compare_svec(jl_svec_t *a, jl_svec_t *b)
7777
// See comment above for an explanation of NOINLINE.
7878
static int NOINLINE compare_fields(jl_value_t *a, jl_value_t *b, jl_datatype_t *dt)
7979
{
80-
size_t nf = jl_datatype_nfields(dt);
81-
for (size_t f=0; f < nf; f++) {
80+
size_t f, nf = jl_datatype_nfields(dt);
81+
for (f = 0; f < nf; f++) {
8282
size_t offs = jl_field_offset(dt, f);
8383
char *ao = (char*)jl_data_ptr(a) + offs;
8484
char *bo = (char*)jl_data_ptr(b) + offs;
85-
int eq;
8685
if (jl_field_isptr(dt, f)) {
8786
jl_value_t *af = *(jl_value_t**)ao;
8887
jl_value_t *bf = *(jl_value_t**)bo;
89-
if (af == bf) eq = 1;
90-
else if (af==NULL || bf==NULL) eq = 0;
91-
else eq = jl_egal(af, bf);
88+
if (af != bf) {
89+
if (af == NULL || bf == NULL)
90+
return 0;
91+
if (!jl_egal(af, bf))
92+
return 0;
93+
}
9294
}
9395
else {
9496
jl_datatype_t *ft = (jl_datatype_t*)jl_field_type(dt, f);
97+
if (jl_is_uniontype(ft)) {
98+
uint8_t asel = ((uint8_t*)ao)[jl_field_size(dt, f) - 1];
99+
uint8_t bsel = ((uint8_t*)bo)[jl_field_size(dt, f) - 1];
100+
if (asel != bsel)
101+
return 0;
102+
ft = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)ft, asel);
103+
}
95104
if (!ft->layout->haspadding) {
96-
eq = bits_equal(ao, bo, jl_field_size(dt, f));
105+
if (!bits_equal(ao, bo, jl_field_size(dt, f)))
106+
return 0;
97107
}
98108
else {
99109
assert(jl_datatype_nfields(ft) > 0);
100-
eq = compare_fields((jl_value_t*)ao, (jl_value_t*)bo, ft);
110+
if (!compare_fields((jl_value_t*)ao, (jl_value_t*)bo, ft))
111+
return 0;
101112
}
102113
}
103-
if (!eq) return 0;
104114
}
105115
return 1;
106116
}
@@ -127,9 +137,11 @@ JL_DLLEXPORT int jl_egal(jl_value_t *a, jl_value_t *b)
127137
return 0;
128138
return !memcmp(jl_string_data(a), jl_string_data(b), l);
129139
}
130-
if (dt->mutabl) return 0;
140+
if (dt->mutabl)
141+
return 0;
131142
size_t sz = jl_datatype_size(dt);
132-
if (sz == 0) return 1;
143+
if (sz == 0)
144+
return 1;
133145
size_t nf = jl_datatype_nfields(dt);
134146
if (nf == 0)
135147
return bits_equal(jl_data_ptr(a), jl_data_ptr(b), sz);
@@ -161,10 +173,10 @@ static uintptr_t bits_hash(void *b, size_t sz)
161173
static uintptr_t NOINLINE hash_svec(jl_svec_t *v)
162174
{
163175
uintptr_t h = 0;
164-
size_t l = jl_svec_len(v);
165-
for(size_t i = 0; i < l; i++) {
166-
jl_value_t *x = jl_svecref(v,i);
167-
uintptr_t u = x==NULL ? 0 : jl_object_id(x);
176+
size_t i, l = jl_svec_len(v);
177+
for (i = 0; i < l; i++) {
178+
jl_value_t *x = jl_svecref(v, i);
179+
uintptr_t u = (x == NULL) ? 0 : jl_object_id(x);
168180
h = bitmix(h, u);
169181
}
170182
return h;
@@ -188,9 +200,11 @@ static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v)
188200
if (dt == jl_typename_type)
189201
return ((jl_typename_t*)v)->hash;
190202
#ifdef _P64
191-
if (v == jl_ANY_flag) return 0x31c472f68ee30bddULL;
203+
if (v == jl_ANY_flag)
204+
return 0x31c472f68ee30bddULL;
192205
#else
193-
if (v == jl_ANY_flag) return 0x8ee30bdd;
206+
if (v == jl_ANY_flag)
207+
return 0x8ee30bdd;
194208
#endif
195209
if (dt == jl_string_type) {
196210
#ifdef _P64
@@ -199,24 +213,29 @@ static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v)
199213
return memhash32_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677);
200214
#endif
201215
}
202-
if (dt->mutabl) return inthash((uintptr_t)v);
216+
if (dt->mutabl)
217+
return inthash((uintptr_t)v);
203218
size_t sz = jl_datatype_size(tv);
204219
uintptr_t h = jl_object_id(tv);
205-
if (sz == 0) return ~h;
206-
size_t nf = jl_datatype_nfields(dt);
207-
if (nf == 0) {
220+
if (sz == 0)
221+
return ~h;
222+
size_t f, nf = jl_datatype_nfields(dt);
223+
if (nf == 0)
208224
return bits_hash(jl_data_ptr(v), sz) ^ h;
209-
}
210-
for (size_t f=0; f < nf; f++) {
225+
for (f = 0; f < nf; f++) {
211226
size_t offs = jl_field_offset(dt, f);
212227
char *vo = (char*)jl_data_ptr(v) + offs;
213228
uintptr_t u;
214229
if (jl_field_isptr(dt, f)) {
215230
jl_value_t *f = *(jl_value_t**)vo;
216-
u = f==NULL ? 0 : jl_object_id(f);
231+
u = (f == NULL) ? 0 : jl_object_id(f);
217232
}
218233
else {
219234
jl_datatype_t *fieldtype = (jl_datatype_t*)jl_field_type(dt, f);
235+
if (jl_is_uniontype(fieldtype)) {
236+
uint8_t sel = ((uint8_t*)vo)[jl_field_size(dt, f) - 1];
237+
fieldtype = (jl_datatype_t*)jl_nth_union_component((jl_value_t*)fieldtype, sel);
238+
}
220239
assert(jl_is_datatype(fieldtype) && !fieldtype->abstract && !fieldtype->mutabl);
221240
if (fieldtype->layout->haspadding)
222241
u = jl_object_id_((jl_value_t*)fieldtype, (jl_value_t*)vo);
@@ -244,7 +263,7 @@ JL_CALLABLE(jl_f_is)
244263
JL_NARGS(===, 2, 2);
245264
if (args[0] == args[1])
246265
return jl_true;
247-
return jl_egal(args[0],args[1]) ? jl_true : jl_false;
266+
return jl_egal(args[0], args[1]) ? jl_true : jl_false;
248267
}
249268

250269
JL_CALLABLE(jl_f_typeof)

0 commit comments

Comments
 (0)