Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/src/dmd/glue/toobj.d
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ void write_instance_pointers(Type type, Symbol* s, uint offset)
return;

Array!(ulong) data;
const ulong sz = getTypePointerBitmap(Loc.initial, type, data, global.errorSink);
ulong count;
const ulong sz = getTypePointerBitmap(Loc.initial, type, data, global.errorSink, count);
if (sz == ulong.max)
return;

Expand Down
26 changes: 20 additions & 6 deletions compiler/src/dmd/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,11 @@ private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg)
* t = type to generate pointer bitmap from
* data = array forming the bitmap
* eSink = error message sink
* count = returns the number of bits set in the bitmap (i.e. the number of pointers)
* Returns:
* size of the type `t` in bytes, ulong.max on error
*/
ulong getTypePointerBitmap(Loc loc, Type t, ref Array!(ulong) data, ErrorSink eSink)
ulong getTypePointerBitmap(Loc loc, Type t, ref Array!(ulong) data, ErrorSink eSink, out ulong count)
{
auto tc = t.isTypeClass();
const ulong sz = (tc && !tc.sym.isInterfaceDeclaration())
Expand Down Expand Up @@ -133,6 +134,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, ref Array!(ulong) data, ErrorSink eS
{
void setpointer(ulong off)
{
count++;
ulong ptroff = off / sz_size_t;
data[cast(size_t)(ptroff / bitsPerElement)] |= 1L << (ptroff % bitsPerElement);
}
Expand Down Expand Up @@ -165,11 +167,14 @@ ulong getTypePointerBitmap(Loc loc, Type t, ref Array!(ulong) data, ErrorSink eS
ulong nextsize = t.next.size();
if (nextsize == SIZE_INVALID)
error = true;
ulong dim = t.dim.toInteger();
for (ulong i = 0; i < dim; i++)
if (t.hasPointers)
{
offset = arrayoff + i * nextsize;
visit(t.next);
ulong dim = t.dim.toInteger();
for (ulong i = 0; i < dim; i++)
{
offset = arrayoff + i * nextsize;
visit(t.next);
}
}
offset = arrayoff;
}
Expand Down Expand Up @@ -286,6 +291,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, ref Array!(ulong) data, ErrorSink eS
* architecture). If set the corresponding memory might contain a pointer/reference.
*
* Returns: [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...]
* OR: [T.sizeof] if the type contains no pointers
*/
private Expression pointerBitmap(TraitsExp e, ErrorSink eSink)
{
Expand All @@ -303,10 +309,18 @@ private Expression pointerBitmap(TraitsExp e, ErrorSink eSink)
}

Array!(ulong) data;
const ulong sz = getTypePointerBitmap(e.loc, t, data, eSink);
ulong count;
const ulong sz = getTypePointerBitmap(e.loc, t, data, eSink, count);
if (sz == ulong.max)
return ErrorExp.get();

if (count == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking t.hasPointers() instead would allow moving this section before the call to getTypePointerBitmap and avoid any counting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, but then there is a perf hit for when hasPointers is true (you'd have to traverse the type ast twice)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasPointers is only a traversal for structs and these cache that information. As the hasPointers or any other method calling determineTypeProperties is very likely to be called anyway before/after, I don't expect much performance penalty. I don't mind that much keeping count as is, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, then better to change it to hasPointers. The count thing is a little ugly, I find.

{
auto exps = new Expressions(1);
(*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t);
return new ArrayLiteralExp(e.loc, Type.tsize_t.sarrayOf(1), exps);
}

auto exps = new Expressions(data.length + 1);
(*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t); // [0] is size in bytes of t
foreach (size_t i; 1 .. exps.length)
Expand Down
2 changes: 1 addition & 1 deletion druntime/src/object.d
Original file line number Diff line number Diff line change
Expand Up @@ -3757,7 +3757,7 @@ template RTInfoImpl(size_t[] pointerBitmap)
template RTInfo(T)
{
enum pointerBitmap = __traits(getPointerBitmap, T);
static if (pointerBitmap[1 .. $] == size_t[pointerBitmap.length - 1].init)
static if (pointerBitmap.length == 1)
enum RTInfo = rtinfoNoPointers;
else
enum RTInfo = RTInfoImpl!(pointerBitmap).ptr;
Expand Down
Loading