1,447 changes: 658 additions & 789 deletions src/rt/aaA.d

Large diffs are not rendered by default.

116 changes: 38 additions & 78 deletions src/rt/lifetime.d
Original file line number Diff line number Diff line change
Expand Up @@ -667,13 +667,14 @@ extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) /+nothrow+/
}
}

package bool hasPostblit(in TypeInfo ti)
{
return (&ti.postblit).funcptr !is &TypeInfo.postblit;
}

void __doPostblit(void *ptr, size_t len, const TypeInfo ti)
{
// optimize out any type info that does not need postblit.
//if((&ti.postblit).funcptr is &TypeInfo.postblit) // compiler doesn't like this
auto fptr = &ti.postblit;
if(fptr.funcptr is &TypeInfo.postblit)
// postblit has not been overridden, no point in looping.
if (!hasPostblit(ti))
return;

if(auto tis = cast(TypeInfo_Struct)ti)
Expand Down Expand Up @@ -1051,83 +1052,43 @@ extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims)
}

/**
* Allocate a non-array item.
* Allocate an uninitialized non-array item.
* This is an optimization to avoid things needed for arrays like the __arrayPad(size).
*/

extern (C) void* _d_newitemT(TypeInfo _ti)
extern (C) void* _d_newitemU(in TypeInfo _ti)
{
auto ti = unqualify(_ti);
auto size = ti.tsize; // array element size
auto baseFlags = !(ti.flags & 1) ? BlkAttr.NO_SCAN : 0;
size_t typeInfoSize = structTypeInfoSize(ti);
size += typeInfoSize; // Need space for the type info
if (typeInfoSize)
baseFlags |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE;
auto flags = !(ti.flags & 1) ? BlkAttr.NO_SCAN : 0;
immutable tiSize = structTypeInfoSize(ti);
immutable size = ti.tsize + tiSize;
if (tiSize)
flags |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE;

debug(PRINTF) printf("_d_newitemT(size = %d)\n", size);
/* not sure if we need this...
* if (length == 0 || size == 0)
result = null;
else
{*/
// allocate a block to hold this item
auto blkInf = GC.qalloc(size, baseFlags, ti);
auto ptr = blkInf.base;
debug(PRINTF) printf(" p = %p\n", ptr);
if(size == ubyte.sizeof)
*cast(ubyte*)ptr = 0;
else if(size == ushort.sizeof)
*cast(ushort*)ptr = 0;
else if(size == uint.sizeof)
*cast(uint*)ptr = 0;
else
memset(ptr, 0, size);

if (typeInfoSize)
*cast(TypeInfo*)(ptr + blkInf.size - typeInfoSize) = ti;
auto blkInf = GC.qalloc(size, flags, ti);
auto p = blkInf.base;

return ptr;
//}
if (tiSize)
*cast(TypeInfo*)(p + blkInf.size - tiSize) = cast() ti;

return p;
}

extern (C) void* _d_newitemiT(TypeInfo _ti)
/// Same as above, zero initializes the item.
extern (C) void* _d_newitemT(in TypeInfo _ti)
{
auto ti = unqualify(_ti);
auto size = ti.tsize; // array element size
auto baseFlags = !(ti.flags & 1) ? BlkAttr.NO_SCAN : 0;
size_t typeInfoSize = structTypeInfoSize(ti);
size += typeInfoSize; // Need space for the type info
if (typeInfoSize)
baseFlags |= BlkAttr.STRUCTFINAL | BlkAttr.FINALIZE;

debug(PRINTF) printf("_d_newitemiT(size = %d)\n", size);

/*if (length == 0 || size == 0)
result = null;
else
{*/
auto initializer = ti.init();
auto isize = initializer.length;
auto q = initializer.ptr;

auto blkInf = GC.qalloc(size, baseFlags, ti);
auto ptr = blkInf.base;
debug(PRINTF) printf(" p = %p\n", ptr);
if (isize == 1)
*cast(ubyte*)ptr = *cast(ubyte*)q;
else if (isize == ushort.sizeof)
*cast(ushort*)ptr = *cast(ushort*)q;
else if (isize == uint.sizeof)
*cast(uint*)ptr = *cast(uint*)q;
else
memcpy(ptr, q, isize);
auto p = _d_newitemU(_ti);
memset(p, 0, _ti.tsize);
return p;
}

if (typeInfoSize)
*cast(TypeInfo*)(ptr + blkInf.size - typeInfoSize) = ti;
return ptr;
//}
/// Same as above, for item with non-zero initializer.
extern (C) void* _d_newitemiT(in TypeInfo _ti)
{
auto p = _d_newitemU(_ti);
auto init = _ti.init();
assert(init.length <= _ti.tsize);
memcpy(p, init.ptr, init.length);
return p;
}

/**
Expand Down Expand Up @@ -2116,8 +2077,7 @@ out (result)

// If a postblit is involved, the contents of result might rightly differ
// from the bitwise concatenation of x and y.
auto pb = &tinext.postblit;
if (pb.funcptr is &TypeInfo.postblit)
if (!hasPostblit(tinext))
{
for (size_t i = 0; i < x.length * sizeelem; i++)
assert((cast(byte*)result)[i] == (cast(byte*)x)[i]);
Expand Down Expand Up @@ -2558,9 +2518,9 @@ unittest
}

// associative arrays
import rt.aaA;
import rt.aaA : entryDtor;
// throw away all existing AA entries with dtor
GC.runFinalizers((cast(char*)(&Entry.Dtor))[0..1]);
GC.runFinalizers((cast(char*)(&entryDtor))[0..1]);

S1[int] aa1;
aa1[0] = S1(0);
Expand All @@ -2569,7 +2529,7 @@ unittest
{
dtorCount = 0;
aa1 = null;
GC.runFinalizers((cast(char*)(&Entry.Dtor))[0..1]);
GC.runFinalizers((cast(char*)(&entryDtor))[0..1]);
assert(dtorCount == 2);
}

Expand All @@ -2581,7 +2541,7 @@ unittest
{
dtorCount = 0;
aa2 = null;
GC.runFinalizers((cast(char*)(&Entry.Dtor))[0..1]);
GC.runFinalizers((cast(char*)(&entryDtor))[0..1]);
assert(dtorCount == 3);
}

Expand All @@ -2592,7 +2552,7 @@ unittest
{
dtorCount = 0;
aa3 = null;
GC.runFinalizers((cast(char*)(&Entry.Dtor))[0..1]);
GC.runFinalizers((cast(char*)(&entryDtor))[0..1]);
assert(dtorCount == 4);
}
}
Expand Down