Skip to content

Commit

Permalink
Deduplicate __arraySetAllocLength. The only difference really is how we
Browse files Browse the repository at this point in the history
get the typeinfo to store, and how we get the fact that a finalizer is
present or not.
  • Loading branch information
schveiguy committed Nov 18, 2024
1 parent 613394c commit 7314c9a
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 108 deletions.
108 changes: 2 additions & 106 deletions druntime/src/core/internal/array/utils.d
Original file line number Diff line number Diff line change
Expand Up @@ -263,111 +263,7 @@ void *__arrayStart()(return scope BlkInfo info) nothrow pure
*/
bool __setArrayAllocLength(T)(ref BlkInfo info, size_t newLength, bool isShared, size_t oldLength = ~0)
{
import core.atomic;
import core.lifetime : TypeInfoSize;

size_t typeInfoSize = TypeInfoSize!T;

if (info.size <= 256)
{
import core.checkedint;

bool overflow;
auto newLengthPadded = addu(newLength,
addu(SMALLPAD, typeInfoSize, overflow),
overflow);

if (newLengthPadded > info.size || overflow)
// new size does not fit inside block
return false;

auto length = cast(ubyte *)(info.base + info.size - typeInfoSize - SMALLPAD);
if (oldLength != ~0)
{
if (isShared)
{
return cas(cast(shared)length, cast(ubyte)oldLength, cast(ubyte)newLength);
}
else
{
if (*length == cast(ubyte)oldLength)
*length = cast(ubyte)newLength;
else
return false;
}
}
else
{
// setting the initial length, no cas needed
*length = cast(ubyte)newLength;
}
if (typeInfoSize)
{
auto typeInfo = cast(TypeInfo*)(info.base + info.size - size_t.sizeof);
*typeInfo = cast()typeid(T);
}
}
else if (info.size < PAGESIZE)
{
if (newLength + MEDPAD + typeInfoSize > info.size)
// new size does not fit inside block
return false;
auto length = cast(ushort *)(info.base + info.size - typeInfoSize - MEDPAD);
if (oldLength != ~0)
{
if (isShared)
{
return cas(cast(shared)length, cast(ushort)oldLength, cast(ushort)newLength);
}
else
{
if (*length == oldLength)
*length = cast(ushort)newLength;
else
return false;
}
}
else
{
// setting the initial length, no cas needed
*length = cast(ushort)newLength;
}
if (typeInfoSize)
{
auto typeInfo = cast(TypeInfo*)(info.base + info.size - size_t.sizeof);
*typeInfo = cast()typeid(T);
}
}
else
{
if (newLength + LARGEPAD > info.size)
// new size does not fit inside block
return false;
auto length = cast(size_t *)(info.base);
if (oldLength != ~0)
{
if (isShared)
{
return cas(cast(shared)length, cast(size_t)oldLength, cast(size_t)newLength);
}
else
{
if (*length == oldLength)
*length = newLength;
else
return false;
}
}
else
{
// setting the initial length, no cas needed
*length = newLength;
}
if (typeInfoSize)
{
auto typeInfo = cast(TypeInfo*)(info.base + size_t.sizeof);
*typeInfo = cast()typeid(T);
}
}
return true; // resize succeeded
import core.internal.gc.blockmeta : __setArrayAllocLengthImpl;
return __setArrayAllocLengthImpl(info, newLength, isShared, typeid(T), oldLength, TypeInfoSize!T);
}
9 changes: 7 additions & 2 deletions druntime/src/core/internal/gc/blockmeta.d
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,14 @@ size_t structTypeInfoSize(const TypeInfo ti) pure nothrow @nogc
*/
bool __setArrayAllocLength(ref BlkInfo info, size_t newlength, bool isshared, const TypeInfo tinext, size_t oldlength = ~0) pure nothrow
{
import core.atomic;

size_t typeInfoSize = structTypeInfoSize(tinext);
return __setArrayAllocLengthImpl(info, newlength, isshared, tinext, oldlength, typeInfoSize);
}

// the impl function, used both above and in core.internal.array.utils
bool __setArrayAllocLengthImpl(ref BlkInfo info, size_t newlength, bool isshared, const TypeInfo tinext, size_t oldlength, size_t typeInfoSize) pure nothrow
{
import core.atomic;

if (info.size <= 256)
{
Expand Down

0 comments on commit 7314c9a

Please sign in to comment.