Skip to content

Commit 6e4c810

Browse files
JeffBezansonvtjnash
authored andcommitted
some small tweaks to the layout optimization PR
- replace inbounds with inline where intended - rename jl_justbits - fix compiler warnings about std::move - guard jl_is_datatype_singleton query correctly - add missing undef reference checks to arrayref and fieldref (and fix array isassigned)
1 parent 7176f1a commit 6e4c810

File tree

11 files changed

+50
-40
lines changed

11 files changed

+50
-40
lines changed

base/array.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ false
177177
isbitsunion(u::Union) = allocatedinline(u)
178178
isbitsunion(x) = false
179179

180-
@inbounds function _unsetindex!(A::Array{T}, i::Int) where {T}
180+
function _unsetindex!(A::Array{T}, i::Int) where {T}
181+
@_inline_meta
181182
@boundscheck checkbounds(A, i)
182183
t = @_gc_preserve_begin A
183184
p = Ptr{Ptr{Cvoid}}(pointer(A, i))

src/array.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ JL_DLLEXPORT jl_value_t *jl_arrayref(jl_array_t *a, size_t i)
563563
if (jl_is_datatype_singleton((jl_datatype_t*)eltype))
564564
return ((jl_datatype_t*)eltype)->instance;
565565
}
566-
return jl_new_bits(eltype, &((char*)a->data)[i * a->elsize]);
566+
return undefref_check((jl_datatype_t*)eltype, jl_new_bits(eltype, &((char*)a->data)[i * a->elsize]));
567567
}
568568

569569
JL_DLLEXPORT int jl_array_isassigned(jl_array_t *a, size_t i)
@@ -574,9 +574,8 @@ JL_DLLEXPORT int jl_array_isassigned(jl_array_t *a, size_t i)
574574
else if (a->flags.hasptr) {
575575
jl_datatype_t *eltype = (jl_datatype_t*)jl_tparam0(jl_typeof(a));
576576
assert(eltype->layout->first_ptr >= 0);
577-
jl_value_t **slot =
578-
(jl_value_t**)(&((char*)a->data)[i*a->elsize] + eltype->layout->first_ptr);
579-
return *slot != NULL;
577+
jl_value_t **elem = (jl_value_t**)((char*)a->data + i * a->elsize);
578+
return elem[eltype->layout->first_ptr] != NULL;
580579
}
581580
return 1;
582581
}

src/builtins.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -760,10 +760,7 @@ JL_CALLABLE(jl_f_getfield)
760760
jl_sym_t *fld = (jl_sym_t*)args[1];
761761
idx = jl_field_index(st, fld, 1);
762762
}
763-
jl_value_t *fval = jl_get_nth_field(v, idx);
764-
if (fval == NULL)
765-
jl_throw(jl_undefref_exception);
766-
return fval;
763+
return jl_get_nth_field_checked(v, idx);
767764
}
768765

769766
JL_CALLABLE(jl_f_setfield)

src/ccall.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1791,7 +1791,7 @@ jl_cgval_t function_sig_t::emit_a_ccall(
17911791
bool sretboxed = false;
17921792
if (sret) {
17931793
assert(!retboxed && jl_is_datatype(rt) && "sret return type invalid");
1794-
if (jl_justbits(rt, true)) {
1794+
if (jl_is_pointerfree(rt)) {
17951795
result = emit_static_alloca(ctx, lrt);
17961796
argvals[0] = ctx.builder.CreateBitCast(result, fargt_sig.at(0));
17971797
}

src/cgutils.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ JL_DLLEXPORT Type *julia_type_to_llvm(jl_value_t *jt, bool *isboxed)
533533
if (isboxed) *isboxed = false;
534534
if (jt == (jl_value_t*)jl_bottom_type)
535535
return T_void;
536-
if (jl_justbits(jt)) {
536+
if (jl_is_concrete_immutable(jt)) {
537537
if (jl_datatype_nbits(jt) == 0)
538538
return T_void;
539539
Type *t = julia_struct_to_llvm(jt, NULL, isboxed);
@@ -768,7 +768,7 @@ static bool for_each_uniontype_small(
768768
allunbox &= for_each_uniontype_small(f, ((jl_uniontype_t*)ty)->b, counter);
769769
return allunbox;
770770
}
771-
else if (jl_justbits(ty, true)) {
771+
else if (jl_is_pointerfree(ty)) {
772772
f(++counter, (jl_datatype_t*)ty);
773773
return true;
774774
}
@@ -1292,12 +1292,12 @@ std::vector<unsigned> first_ptr(Type *T)
12921292
unsigned i = 0;
12931293
for (Type *ElTy : T->subtypes()) {
12941294
if (isa<PointerType>(ElTy) && ElTy->getPointerAddressSpace() == AddressSpace::Tracked) {
1295-
return std::move(std::vector<unsigned>{i});
1295+
return std::vector<unsigned>{i};
12961296
}
12971297
auto path = first_ptr(ElTy);
12981298
if (!path.empty()) {
12991299
path.push_back(i);
1300-
return std::move(path);
1300+
return path;
13011301
}
13021302
i++;
13031303
}
@@ -1529,7 +1529,7 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx,
15291529
assert(!jl_is_vecelement_type((jl_value_t*)stt));
15301530

15311531
if (!strct.ispointer()) { // unboxed
1532-
assert(jl_justbits((jl_value_t*)stt));
1532+
assert(jl_is_concrete_immutable((jl_value_t*)stt));
15331533
bool isboxed = is_datatype_all_pointers(stt);
15341534
bool issame = is_tupletype_homogeneous(stt->types);
15351535
if (issame) {
@@ -2415,7 +2415,7 @@ static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo)
24152415
}
24162416
else {
24172417
assert(vinfo.V && "Missing data for unboxed value.");
2418-
assert(jl_justbits(jt) && "This type shouldn't have been unboxed.");
2418+
assert(jl_is_concrete_immutable(jt) && "This type shouldn't have been unboxed.");
24192419
Type *t = julia_type_to_llvm(jt);
24202420
assert(!type_is_ghost(t)); // ghost values should have been handled by vinfo.constant above!
24212421
box = _boxed_special(ctx, vinfo, t);
@@ -2438,8 +2438,8 @@ static void emit_unionmove(jl_codectx_t &ctx, Value *dest, MDNode *tbaa_dst, con
24382438
if (jl_is_concrete_type(src.typ) || src.constant) {
24392439
jl_value_t *typ = src.constant ? jl_typeof(src.constant) : src.typ;
24402440
Type *store_ty = julia_type_to_llvm(typ);
2441-
assert(skip || jl_justbits(typ, true));
2442-
if (jl_justbits(typ, true)) {
2441+
assert(skip || jl_is_pointerfree(typ));
2442+
if (jl_is_pointerfree(typ)) {
24432443
if (!src.ispointer() || src.constant) {
24442444
emit_unbox(ctx, store_ty, src, typ, dest, tbaa_dst, isVolatile);
24452445
}

src/codegen.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -366,23 +366,24 @@ static MDNode *best_tbaa(jl_value_t *jt) {
366366

367367
// tracks whether codegen is currently able to simply stack-allocate this type
368368
// note that this includes jl_isbits, although codegen should work regardless
369-
static bool jl_justbits(jl_value_t* t, bool pointerfree=false)
369+
static bool jl_is_concrete_immutable(jl_value_t* t)
370+
{
371+
return jl_is_immutable_datatype(t) && ((jl_datatype_t*)t)->layout;
372+
}
373+
374+
static bool jl_is_pointerfree(jl_value_t* t)
370375
{
371376
if (!jl_is_immutable_datatype(t))
372377
return 0;
373378
const jl_datatype_layout_t *layout = ((jl_datatype_t*)t)->layout;
374-
if (!layout)
375-
return 0;
376-
if (pointerfree && layout->npointers != 0)
377-
return 0;
378-
return 1;
379+
return layout && layout->npointers == 0;
379380
}
380381

381382
// these queries are usually related, but we split them out here
382383
// for convenience and clarity (and because it changes the calling convention)
383384
static bool deserves_stack(jl_value_t* t, bool pointerfree=false)
384385
{
385-
if (!jl_justbits(t))
386+
if (!jl_is_concrete_immutable(t))
386387
return false;
387388
return ((jl_datatype_t*)t)->isinlinealloc;
388389
}
@@ -753,7 +754,7 @@ static inline jl_cgval_t update_julia_type(jl_codectx_t &ctx, const jl_cgval_t &
753754
if (jl_is_datatype(utyp)) {
754755
bool alwaysboxed;
755756
if (jl_is_concrete_type(utyp))
756-
alwaysboxed = !jl_justbits(utyp, true);
757+
alwaysboxed = !jl_is_pointerfree(utyp);
757758
else
758759
alwaysboxed = !((jl_datatype_t*)utyp)->abstract && ((jl_datatype_t*)utyp)->mutabl;
759760
if (alwaysboxed) {
@@ -1012,7 +1013,7 @@ static jl_cgval_t convert_julia_type(jl_codectx_t &ctx, const jl_cgval_t &v, jl_
10121013
return ghostValue(typ);
10131014
Value *new_tindex = NULL;
10141015
if (jl_is_concrete_type(typ)) {
1015-
if (v.TIndex && !jl_justbits(typ, true)) {
1016+
if (v.TIndex && !jl_is_pointerfree(typ)) {
10161017
// discovered that this union-split type must actually be isboxed
10171018
if (v.Vboxed) {
10181019
return jl_cgval_t(v.Vboxed, nullptr, true, typ, NULL);
@@ -2480,8 +2481,8 @@ static Value *emit_f_is(jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgva
24802481
if (jl_type_intersection(rt1, rt2) == (jl_value_t*)jl_bottom_type) // types are disjoint (exhaustive test)
24812482
return ConstantInt::get(T_int1, 0);
24822483

2483-
bool justbits1 = jl_justbits(rt1);
2484-
bool justbits2 = jl_justbits(rt2);
2484+
bool justbits1 = jl_is_concrete_immutable(rt1);
2485+
bool justbits2 = jl_is_concrete_immutable(rt2);
24852486
if (justbits1 || justbits2) { // whether this type is unique'd by value
24862487
jl_value_t *typ = justbits1 ? rt1 : rt2;
24872488
if (rt1 == rt2)
@@ -4110,7 +4111,8 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
41104111
if (var == getfield_undefref_sym) {
41114112
raise_exception_unless(ctx, cond,
41124113
literal_pointer_val(ctx, jl_undefref_exception));
4113-
} else {
4114+
}
4115+
else {
41144116
undef_var_error_ifnot(ctx, cond, var);
41154117
}
41164118
return ghostValue(jl_void_type);
@@ -4661,7 +4663,7 @@ static Function* gen_cfun_wrapper(
46614663
ctx.builder.CreateLoad(emit_bitcast(ctx, val, T_pprjlvalue)),
46624664
true, jl_any_type);
46634665
}
4664-
else if (static_at && jl_justbits(jargty)) { // anything that could be stored unboxed
4666+
else if (static_at && jl_is_concrete_immutable(jargty)) { // anything that could be stored unboxed
46654667
bool isboxed;
46664668
Type *T = julia_type_to_llvm(jargty, &isboxed);
46674669
assert(!isboxed);
@@ -5398,7 +5400,7 @@ static bool uses_specsig(jl_value_t *sig, size_t nreq, jl_value_t *rettype, bool
53985400
bool allSingleton = true;
53995401
for (size_t i = 0; i < jl_nparams(sig); i++) {
54005402
jl_value_t *sigt = jl_tparam(sig, i);
5401-
bool issing = jl_is_datatype_singleton((jl_datatype_t*)sigt);
5403+
bool issing = jl_is_datatype(sigt) && jl_is_datatype_singleton((jl_datatype_t*)sigt);
54025404
allSingleton &= issing;
54035405
if (!deserves_argbox(sigt) && !issing) {
54045406
return true;
@@ -5948,7 +5950,7 @@ static std::unique_ptr<Module> emit_function(
59485950
}
59495951
else if (varinfo.isArgument && !(specsig && i == (size_t)ctx.vaSlot)) {
59505952
// if we can unbox it, just use the input pointer
5951-
if (i != (size_t)ctx.vaSlot && jl_justbits(jt))
5953+
if (i != (size_t)ctx.vaSlot && jl_is_concrete_immutable(jt))
59525954
return;
59535955
}
59545956
else if (jl_is_uniontype(jt)) {

src/datatype.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ JL_DLLEXPORT int jl_stored_inline(jl_value_t *eltype) JL_NOTSAFEPOINT
272272
return jl_islayout_inline(eltype, &fsz, &al);
273273
}
274274

275-
// whether this type is unique'd by pointer
275+
// whether instances of this type can use pointer comparison for `===`
276276
int jl_pointer_egal(jl_value_t *t)
277277
{
278278
if (t == (jl_value_t*)jl_any_type)
@@ -1059,7 +1059,7 @@ JL_DLLEXPORT jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i)
10591059
size_t offs = jl_field_offset(st, i);
10601060
if (jl_field_isptr(st, i)) {
10611061
jl_value_t *fval = *(jl_value_t**)((char*)v + offs);
1062-
if (fval == NULL)
1062+
if (__unlikely(fval == NULL))
10631063
jl_throw(jl_undefref_exception);
10641064
return fval;
10651065
}
@@ -1071,7 +1071,7 @@ JL_DLLEXPORT jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i)
10711071
if (jl_is_datatype_singleton((jl_datatype_t*)ty))
10721072
return ((jl_datatype_t*)ty)->instance;
10731073
}
1074-
return jl_new_bits(ty, (char*)v + offs);
1074+
return undefref_check((jl_datatype_t*)ty, jl_new_bits(ty, (char*)v + offs));
10751075
}
10761076

10771077
JL_DLLEXPORT void jl_set_nth_field(jl_value_t *v, size_t i, jl_value_t *rhs) JL_NOTSAFEPOINT

src/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1713,7 +1713,7 @@ JL_DLLEXPORT int jl_gc_mark_queue_obj(jl_ptls_t ptls, jl_value_t *obj)
17131713
JL_DLLEXPORT void jl_gc_mark_queue_objarray(jl_ptls_t ptls, jl_value_t *parent,
17141714
jl_value_t **objs, size_t nobjs)
17151715
{
1716-
gc_mark_objarray_t data = { parent, objs, objs + nobjs,
1716+
gc_mark_objarray_t data = { parent, objs, objs + nobjs, 1,
17171717
jl_astaggedvalue(parent)->bits.gc & 2 };
17181718
gc_mark_stack_push(&ptls->gc_cache, &ptls->gc_mark_sp,
17191719
gc_mark_label_addrs[GC_MARK_L_objarray],

src/intrinsics.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ static Value *uint_cnvt(jl_codectx_t &ctx, Type *to, Value *x)
149149

150150
static Constant *julia_const_to_llvm(const void *ptr, jl_datatype_t *bt)
151151
{
152-
// assumes `jl_justbits(bt, true)`.
152+
// assumes `jl_is_pointerfree(bt)`.
153153
// `ptr` can point to a inline field, do not read the tag from it.
154154
// make sure to return exactly the type specified by
155155
// julia_type_to_llvm as this will be assumed by the callee.
@@ -270,7 +270,7 @@ static Constant *julia_const_to_llvm(jl_value_t *e)
270270
if (e == jl_false)
271271
return ConstantInt::get(T_int8, 0);
272272
jl_value_t *bt = jl_typeof(e);
273-
if (!jl_justbits(bt, true))
273+
if (!jl_is_pointerfree(bt))
274274
return NULL;
275275
return julia_const_to_llvm(e, (jl_datatype_t*)bt);
276276
}

src/julia_internal.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,17 @@ void jl_set_t_uid_ctr(int i);
352352
uint32_t jl_get_gs_ctr(void);
353353
void jl_set_gs_ctr(uint32_t ctr);
354354

355+
STATIC_INLINE jl_value_t *undefref_check(jl_datatype_t *dt, jl_value_t *v) JL_NOTSAFEPOINT
356+
{
357+
if (dt->layout->first_ptr >= 0) {
358+
jl_value_t *nullp = ((jl_value_t**)v)[dt->layout->first_ptr];
359+
if (__unlikely(nullp == NULL))
360+
jl_throw(jl_undefref_exception);
361+
}
362+
return v;
363+
}
364+
365+
355366
// -- functions -- //
356367

357368
jl_code_info_t *jl_type_infer(jl_method_instance_t *li, size_t world, int force);

0 commit comments

Comments
 (0)