aboutsummaryrefslogtreecommitdiff
path: root/libphobos/libdruntime
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-07-06 19:45:28 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-07-06 19:51:38 +0200
commit208fbc779c713715da1465a1a2c6710c084c9b05 (patch)
treef8698626e4c2fd65701eddf36918ebf4f2cc6763 /libphobos/libdruntime
parentc785204735b2cace9a676969de0967105a06438d (diff)
downloadgcc-208fbc779c713715da1465a1a2c6710c084c9b05.zip
gcc-208fbc779c713715da1465a1a2c6710c084c9b05.tar.gz
gcc-208fbc779c713715da1465a1a2c6710c084c9b05.tar.bz2
d: Merge upstream dmd 56589f0f4, druntime 651389b5, phobos 1516ecad9.
D front-end changes: - Import latest bug fixes to mainline. D runtime changes: - Import latest bug fixes to mainline. Phobos changes: - Import latest bug fixes to mainline. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 56589f0f4. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 651389b5. * src/MERGE: Merge upstream phobos 1516ecad9.
Diffstat (limited to 'libphobos/libdruntime')
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/core/internal/parseoptions.d17
-rw-r--r--libphobos/libdruntime/core/thread/osthread.d9
-rw-r--r--libphobos/libdruntime/rt/aApply.d108
-rw-r--r--libphobos/libdruntime/rt/aApplyR.d71
-rw-r--r--libphobos/libdruntime/rt/aaA.d39
-rw-r--r--libphobos/libdruntime/rt/arrayassign.d83
-rw-r--r--libphobos/libdruntime/rt/lifetime.d378
8 files changed, 520 insertions, 187 deletions
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 2fc1bc1..6e25a9d 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-148608b7935c3f9a4ea3a26f74cb90cd07efc91c
+651389b52243dcadb338dd0c14dd27e7850cda8d
The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository.
diff --git a/libphobos/libdruntime/core/internal/parseoptions.d b/libphobos/libdruntime/core/internal/parseoptions.d
index 9920443..ed6251f 100644
--- a/libphobos/libdruntime/core/internal/parseoptions.d
+++ b/libphobos/libdruntime/core/internal/parseoptions.d
@@ -168,6 +168,7 @@ inout(char)[] find(alias pred)(inout(char)[] str)
}
bool parse(T : size_t)(const(char)[] optname, ref inout(char)[] str, ref T res, const(char)[] errName, bool mayHaveSuffix = false)
+if (is(T == size_t))
in { assert(str.length); }
do
{
@@ -242,6 +243,22 @@ do
if (v > res.max)
return parseError("a number " ~ T.max.stringof ~ " or below", optname, str[0 .. i], errName);
str = str[i .. $];
+ res = v;
+ return true;
+}
+
+bool parse(T : size_t)(const(char)[] optname, ref inout(char)[] str, ref T res, const(char)[] errName, bool mayHaveSuffix = false)
+if (!is(T == size_t))
+in { assert(str.length); }
+do
+{
+ const oldStr = str;
+ size_t v;
+ if (!parse!size_t(optname, str, v, errName, mayHaveSuffix))
+ return false;
+
+ if (v > res.max)
+ return parseError("a number " ~ T.max.stringof ~ " or below", optname, oldStr[0 .. $-str.length], errName);
res = cast(T) v;
return true;
}
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index 1165320..415430c 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -2130,6 +2130,15 @@ extern (C) void thread_init() @nogc nothrow
}
else version (Posix)
{
+ version (OpenBSD)
+ {
+ // OpenBSD does not support SIGRTMIN or SIGRTMAX
+ // Use SIGUSR1 for SIGRTMIN, SIGUSR2 for SIGRTMIN + 1
+ // And use 32 for SIGRTMAX (32 is the max signal number on OpenBSD)
+ enum SIGRTMIN = SIGUSR1;
+ enum SIGRTMAX = 32;
+ }
+
if ( suspendSignalNumber == 0 )
{
suspendSignalNumber = SIGRTMIN;
diff --git a/libphobos/libdruntime/rt/aApply.d b/libphobos/libdruntime/rt/aApply.d
index bea441f..5d5ddb3 100644
--- a/libphobos/libdruntime/rt/aApply.d
+++ b/libphobos/libdruntime/rt/aApply.d
@@ -1,7 +1,5 @@
/**
- * This code handles decoding UTF strings for foreach loops. There are 6
- * combinations of conversions between char, wchar, and dchar, and 2 of each
- * of those.
+ * This code handles decoding UTF strings for foreach loops.
*
* Copyright: Copyright Digital Mars 2004 - 2010.
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
@@ -15,9 +13,64 @@ import core.internal.utf : decode, toUTF8;
/**********************************************/
/* 1 argument versions */
-// dg is D, but _aApplycd() is C
-extern (D) alias int delegate(void *) dg_t;
+/**
+Delegate type corresponding to transformed loop body
+
+The parameter is a pointer to the current `char`, `wchar` or `dchar`
+
+Returns: non-zero when a `break` statement is hit
+*/
+extern (D) alias dg_t = int delegate(void* c);
+
+// Note: dg is extern(D), but _aApplycd() is extern(C)
+
+/**
+Loop over a string while changing the UTF encoding
+
+There are 6 combinations of conversions between `char`, `wchar`, and `dchar`,
+and 2 of each of those.
+
+The naming convention is as follows:
+
+_aApply{c,d,w}{c,d,w}{1,2}
+The first letter corresponds to the input string encoding, and the second letter corresponds to the target character type.
+
+- c = `char`
+- w = `wchar`
+- d = `dchar`
+
+The `1` variant only produces the character, the `2` variant also produces a loop index.
+
+Examples:
+---
+void main()
+{
+ string str;
+ wtring wstr;
+ dstring dstr;
+
+ foreach (dchar c; str) {}
+ // _aApplycd1
+
+ foreach (wchar c; dstr) {}
+ // _aApplydw1
+
+ foreach (i, wchar c; str) {}
+ // _aApplycw2
+
+ foreach (wchar w; wstr) {}
+ // no conversion
+}
+---
+
+Params:
+ aa = input string
+ dg = foreach body transformed into a delegate, similar to `opApply`
+
+Returns:
+ non-zero when the loop was exited through a `break`
+*/
extern (C) int _aApplycd1(in char[] aa, dg_t dg)
{
int result;
@@ -78,8 +131,7 @@ unittest
assert(i == 4);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplywd1(in wchar[] aa, dg_t dg)
{
int result;
@@ -140,8 +192,7 @@ unittest
assert(i == 4);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplycw1(in char[] aa, dg_t dg)
{
int result;
@@ -215,8 +266,7 @@ unittest
assert(i == 5);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplywc1(in wchar[] aa, dg_t dg)
{
int result;
@@ -296,8 +346,7 @@ unittest
assert(i == 9);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplydc1(in dchar[] aa, dg_t dg)
{
int result;
@@ -373,8 +422,7 @@ unittest
assert(i == 9);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplydw1(in dchar[] aa, dg_t dg)
{
int result;
@@ -446,9 +494,20 @@ unittest
/****************************************************************************/
/* 2 argument versions */
-// dg is D, but _aApplycd2() is C
-extern (D) alias int delegate(void *, void *) dg2_t;
+/**
+Delegate type corresponding to transformed loop body
+
+Parameters are pointers to a `size_t` loop index, and the current `char`, `wchar` or `dchar`.
+Returns: non-zero when a `break` statement is hit
+*/
+extern (D) alias dg2_t = int delegate(void* i, void* c);
+
+// Note: dg is extern(D), but _aApplycd2() is extern(C)
+
+/**
+Variants of _aApplyXXX that include a loop index.
+*/
extern (C) int _aApplycd2(in char[] aa, dg2_t dg)
{
int result;
@@ -516,8 +575,7 @@ unittest
assert(i == 4);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplywd2(in wchar[] aa, dg2_t dg)
{
int result;
@@ -585,8 +643,7 @@ unittest
assert(i == 4);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplycw2(in char[] aa, dg2_t dg)
{
int result;
@@ -665,8 +722,7 @@ unittest
assert(i == 5);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplywc2(in wchar[] aa, dg2_t dg)
{
int result;
@@ -751,8 +807,7 @@ unittest
assert(i == 9);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplydc2(in dchar[] aa, dg2_t dg)
{
int result;
@@ -832,8 +887,7 @@ unittest
assert(i == 9);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplydw2(in dchar[] aa, dg2_t dg)
{ int result;
diff --git a/libphobos/libdruntime/rt/aApplyR.d b/libphobos/libdruntime/rt/aApplyR.d
index 7f19fa8..ce3bb9e 100644
--- a/libphobos/libdruntime/rt/aApplyR.d
+++ b/libphobos/libdruntime/rt/aApplyR.d
@@ -1,7 +1,5 @@
/**
- * This code handles decoding UTF strings for foreach_reverse loops. There are
- * 6 combinations of conversions between char, wchar, and dchar, and 2 of each
- * of those.
+ * This code handles decoding UTF strings for `foreach_reverse` loops.
*
* Copyright: Copyright Digital Mars 2004 - 2010.
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
@@ -15,9 +13,27 @@ import core.internal.utf;
/**********************************************/
/* 1 argument versions */
-// dg is D, but _aApplyRcd() is C
-extern (D) alias int delegate(void *) dg_t;
+// Note: dg is extern(D), but _aApplyRcd() is extern(C)
+/**
+Delegate type corresponding to transformed loop body
+
+The parameter is a pointer to the current `char`, `wchar` or `dchar`
+
+Returns: non-zero when a `break` statement is hit
+*/
+extern (D) alias dg_t = int delegate(void* c);
+
+/**
+Same as `_aApplyXXX` functions, but for `foreach_reverse`
+
+Params:
+ aa = input string
+ dg = foreach body transformed into a delegate, similar to `opApply`
+
+Returns:
+ non-zero when the loop was exited through a `break`
+*/
extern (C) int _aApplyRcd1(in char[] aa, dg_t dg)
{ int result;
@@ -90,8 +106,7 @@ unittest
assert(i == 4);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg)
{ int result;
@@ -154,8 +169,7 @@ unittest
assert(i == 4);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRcw1(in char[] aa, dg_t dg)
{ int result;
@@ -241,8 +255,7 @@ unittest
assert(i == 5);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg)
{ int result;
@@ -326,8 +339,7 @@ unittest
assert(i == 9);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg)
{ int result;
@@ -405,8 +417,7 @@ unittest
assert(i == 9);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg)
{ int result;
@@ -477,9 +488,20 @@ unittest
/****************************************************************************/
/* 2 argument versions */
-// dg is D, but _aApplyRcd2() is C
-extern (D) alias int delegate(void *, void *) dg2_t;
+/**
+Delegate type corresponding to transformed loop body
+
+Parameters are pointers to a `size_t` loop index, and the current `char`, `wchar` or `dchar`.
+Returns: non-zero when a `break` statement is hit
+*/
+extern (D) alias dg2_t = int delegate(void* i, void* c);
+
+// Note: dg is extern(D), but _aApplyRcd2() is extern(C)
+
+/**
+Variants of _aApplyRXXX that include a loop index.
+*/
extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg)
{ int result;
size_t i;
@@ -555,8 +577,7 @@ unittest
assert(i == 4);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg)
{ int result;
@@ -621,8 +642,7 @@ unittest
assert(i == 4);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg)
{ int result;
@@ -710,8 +730,7 @@ unittest
assert(i == 5);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg)
{ int result;
@@ -797,8 +816,7 @@ unittest
assert(i == 9);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg)
{ int result;
@@ -877,8 +895,7 @@ unittest
assert(i == 9);
}
-/*****************************/
-
+/// ditto
extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg)
{ int result;
diff --git a/libphobos/libdruntime/rt/aaA.d b/libphobos/libdruntime/rt/aaA.d
index ab93f19..f264b01 100644
--- a/libphobos/libdruntime/rt/aaA.d
+++ b/libphobos/libdruntime/rt/aaA.d
@@ -50,7 +50,7 @@ struct AA
private struct Impl
{
private:
- this(scope const TypeInfo_AssociativeArray ti, size_t sz = INIT_NUM_BUCKETS)
+ this(scope const TypeInfo_AssociativeArray ti, size_t sz = INIT_NUM_BUCKETS) nothrow
{
keysz = cast(uint) ti.key.tsize;
valsz = cast(uint) ti.value.tsize;
@@ -125,7 +125,7 @@ private:
}
}
- void grow(scope const TypeInfo keyti)
+ void grow(scope const TypeInfo keyti) pure nothrow
{
// If there are so many deleted entries, that growing would push us
// below the shrink threshold, we just purge deleted entries instead.
@@ -135,7 +135,7 @@ private:
resize(GROW_FAC * dim);
}
- void shrink(scope const TypeInfo keyti)
+ void shrink(scope const TypeInfo keyti) pure nothrow
{
if (dim > INIT_NUM_BUCKETS)
resize(dim / GROW_FAC);
@@ -233,7 +233,7 @@ package void entryDtor(void* p, const TypeInfo_Struct sti)
extra[1].destroy(p + talign(extra[0].tsize, extra[1].talign));
}
-private bool hasDtor(const TypeInfo ti)
+private bool hasDtor(const TypeInfo ti) pure nothrow
{
import rt.lifetime : unqualify;
@@ -246,7 +246,7 @@ private bool hasDtor(const TypeInfo ti)
return false;
}
-private immutable(void)* getRTInfo(const TypeInfo ti)
+private immutable(void)* getRTInfo(const TypeInfo ti) pure nothrow
{
// classes are references
const isNoClass = ti && typeid(ti) !is typeid(TypeInfo_Class);
@@ -254,7 +254,7 @@ private immutable(void)* getRTInfo(const TypeInfo ti)
}
// build type info for Entry with additional key and value fields
-TypeInfo_Struct fakeEntryTI(ref Impl aa, const TypeInfo keyti, const TypeInfo valti)
+TypeInfo_Struct fakeEntryTI(ref Impl aa, const TypeInfo keyti, const TypeInfo valti) nothrow
{
import rt.lifetime : unqualify;
@@ -319,7 +319,8 @@ TypeInfo_Struct fakeEntryTI(ref Impl aa, const TypeInfo keyti, const TypeInfo va
}
// build appropriate RTInfo at runtime
-immutable(void)* rtinfoEntry(ref Impl aa, immutable(size_t)* keyinfo, immutable(size_t)* valinfo, size_t* rtinfoData, size_t rtinfoSize)
+immutable(void)* rtinfoEntry(ref Impl aa, immutable(size_t)* keyinfo,
+ immutable(size_t)* valinfo, size_t* rtinfoData, size_t rtinfoSize) pure nothrow
{
enum bitsPerWord = 8 * size_t.sizeof;
@@ -456,7 +457,7 @@ private size_t mix(size_t h) @safe pure nothrow @nogc
return h;
}
-private size_t calcHash(scope const void* pkey, scope const TypeInfo keyti)
+private size_t calcHash(scope const void* pkey, scope const TypeInfo keyti) nothrow
{
immutable hash = keyti.getHash(pkey);
// highest bit is set to distinguish empty/deleted from filled buckets
@@ -485,6 +486,18 @@ pure nothrow @nogc unittest
// API Implementation
//------------------------------------------------------------------------------
+/** Allocate associative array data.
+ * Called for `new SomeAA` expression.
+ * Params:
+ * ti = TypeInfo for the associative array
+ * Returns:
+ * A new associative array.
+ */
+extern (C) Impl* _aaNew(const TypeInfo_AssociativeArray ti)
+{
+ return new Impl(ti);
+}
+
/// Determine number of entries in associative array.
extern (C) size_t _aaLen(scope const AA aa) pure nothrow @nogc
{
@@ -736,7 +749,15 @@ extern (C) int _aaApply2(AA aa, const size_t keysz, dg2_t dg)
return 0;
}
-/// Construct an associative array of type ti from keys and value
+/** Construct an associative array of type ti from corresponding keys and values.
+ * Called for an AA literal `[k1:v1, k2:v2]`.
+ * Params:
+ * ti = TypeInfo for the associative array
+ * keys = array of keys
+ * vals = array of values
+ * Returns:
+ * A new associative array opaque pointer, or null if `keys` is empty.
+ */
extern (C) Impl* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys,
void[] vals)
{
diff --git a/libphobos/libdruntime/rt/arrayassign.d b/libphobos/libdruntime/rt/arrayassign.d
index 9a34ec7..c9db2fc 100644
--- a/libphobos/libdruntime/rt/arrayassign.d
+++ b/libphobos/libdruntime/rt/arrayassign.d
@@ -19,8 +19,10 @@ private
debug(PRINTF) import core.stdc.stdio;
}
-/**
- * Keep for backward binary compatibility. This function can be removed in the future.
+/*
+ * Superseded array assignment hook. Does not take into account destructors:
+ * https://issues.dlang.org/show_bug.cgi?id=13661
+ * Kept for backward binary compatibility. This function can be removed in the future.
*/
extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to)
{
@@ -40,15 +42,44 @@ extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to)
}
/**
- * Does array assignment (not construction) from another
- * lvalue array of the same element type.
- * Handles overlapping copies.
- * Input:
- * ti TypeInfo of the element type.
- * dst Points target memory. Its .length is equal to the element count, not byte length.
- * src Points source memory. Its .length is equal to the element count, not byte length.
- * ptmp Temporary memory for element swapping.
- */
+Does array assignment (not construction) from another array of the same
+element type.
+
+Handles overlapping copies.
+
+The `_d_arrayassign_l` variant assumes the right hand side is an lvalue,
+while `_d_arrayassign_r` assumes it's an rvalue, which means it doesn't have to call copy constructors.
+
+Used for static array assignment with non-POD element types:
+---
+struct S
+{
+ ~this() {} // destructor, so not Plain Old Data
+}
+
+void main()
+{
+ S[3] arr;
+ S[3] lvalue;
+
+ arr = lvalue;
+ // Generates:
+ // S _tmp;
+ // _d_arrayassign_l(typeid(S), (cast(void*) lvalue.ptr)[0..lvalue.length], (cast(void*) arr.ptr)[0..arr.length], &_tmp);
+
+ S[3] getRvalue() {return lvalue;}
+ arr = getRvalue();
+ // Similar, but `_d_arrayassign_r`
+}
+---
+
+Params:
+ ti = `TypeInfo` of the array element type.
+ dst = target memory. Its `.length` is equal to the element count, not byte length.
+ src = source memory. Its `.length` is equal to the element count, not byte length.
+ ptmp = Temporary memory for element swapping, must have capacity of `ti.tsize` bytes.
+Returns: `dst`
+*/
extern (C) void[] _d_arrayassign_l(TypeInfo ti, void[] src, void[] dst, void* ptmp)
{
debug(PRINTF) printf("_d_arrayassign_l(src = %p,%d, dst = %p,%d) size = %d\n", src.ptr, src.length, dst.ptr, dst.length, ti.tsize);
@@ -131,16 +162,7 @@ unittest // Bugzilla 14024
assert(op == "YzXy", op);
}
-/**
- * Does array assignment (not construction) from another
- * rvalue array of the same element type.
- * Input:
- * ti TypeInfo of the element type.
- * dst Points target memory. Its .length is equal to the element count, not byte length.
- * src Points source memory. Its .length is equal to the element count, not byte length.
- * It is always allocated on stack and never overlapping with dst.
- * ptmp Temporary memory for element swapping.
- */
+/// ditto
extern (C) void[] _d_arrayassign_r(TypeInfo ti, void[] src, void[] dst, void* ptmp)
{
debug(PRINTF) printf("_d_arrayassign_r(src = %p,%d, dst = %p,%d) size = %d\n", src.ptr, src.length, dst.ptr, dst.length, ti.tsize);
@@ -163,9 +185,22 @@ extern (C) void[] _d_arrayassign_r(TypeInfo ti, void[] src, void[] dst, void* pt
}
/**
- * Do assignment to an array.
- * p[0 .. count] = value;
- */
+Set all elements of an array to a single value.
+
+---
+p[0 .. count] = value;
+---
+
+Takes into account postblits and destructors, for Plain Old Data elements,
+`rt/memset.d` is used.
+
+Params:
+ p = pointer to start of array
+ value = bytes of the element to set. Size is derived from `ti`.
+ count = amount of array elements to set
+ ti = type info of the array element type / `value`
+Returns: `p`
+*/
extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti)
{
void* pstart = p;
diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d
index 18ecc31..026001f 100644
--- a/libphobos/libdruntime/rt/lifetime.d
+++ b/libphobos/libdruntime/rt/lifetime.d
@@ -48,16 +48,39 @@ deprecated extern (C) void lifetime_init()
}
/**
- *
- */
+Allocate memory using the garbage collector
+
+DMD uses this to allocate closures:
+---
+void f(byte[24] x)
+{
+ return () => x; // `x` is on stack, must be moved to heap to keep it alive
+}
+---
+
+Params:
+ sz = number of bytes to allocate
+
+Returns: pointer to `sz` bytes of free, uninitialized memory, managed by the GC.
+*/
extern (C) void* _d_allocmemory(size_t sz) @weak
{
return GC.malloc(sz);
}
/**
- *
- */
+Create a new class instance.
+
+Allocates memory and sets fields to their initial value, but does not call a constructor.
+
+---
+new Object() // _d_newclass(typeid(Object))
+---
+Params:
+ ci = `TypeInfo_Class` object, to provide instance size and initial bytes to copy
+
+Returns: newly created object
+*/
extern (C) Object _d_newclass(const ClassInfo ci) @weak
{
import core.stdc.stdlib;
@@ -352,7 +375,7 @@ bool __setArrayAllocLength(ref BlkInfo info, size_t newlength, bool isshared, co
/**
get the allocation size of the array for the given block (without padding or type info)
*/
-size_t __arrayAllocLength(ref BlkInfo info, const TypeInfo tinext) pure nothrow
+private size_t __arrayAllocLength(ref BlkInfo info, const TypeInfo tinext) pure nothrow
{
if (info.size <= 256)
return *cast(ubyte *)(info.base + info.size - structTypeInfoSize(tinext) - SMALLPAD);
@@ -366,7 +389,7 @@ size_t __arrayAllocLength(ref BlkInfo info, const TypeInfo tinext) pure nothrow
/**
get the start of the array for the given block
*/
-void *__arrayStart(return scope BlkInfo info) nothrow pure
+private void *__arrayStart(return scope BlkInfo info) nothrow pure
{
return info.base + ((info.size & BIGLENGTHMASK) ? LARGEPREFIX : 0);
}
@@ -376,7 +399,7 @@ void *__arrayStart(return scope BlkInfo info) nothrow pure
NOT included in the passed in size. Therefore, do NOT call this function
with the size of an allocated block.
*/
-size_t __arrayPad(size_t size, const TypeInfo tinext) nothrow pure @trusted
+private size_t __arrayPad(size_t size, const TypeInfo tinext) nothrow pure @trusted
{
return size > MAXMEDSIZE ? LARGEPAD : ((size > MAXSMALLSIZE ? MEDPAD : SMALLPAD) + structTypeInfoSize(tinext));
}
@@ -401,7 +424,7 @@ private void __arrayClearPad(ref BlkInfo info, size_t arrsize, size_t padsize) n
allocate an array memory block by applying the proper padding and
assigning block attributes if not inherited from the existing block
*/
-BlkInfo __arrayAlloc(size_t arrsize, const scope TypeInfo ti, const TypeInfo tinext) nothrow pure
+private BlkInfo __arrayAlloc(size_t arrsize, const scope TypeInfo ti, const TypeInfo tinext) nothrow pure
{
import core.checkedint;
@@ -423,7 +446,7 @@ BlkInfo __arrayAlloc(size_t arrsize, const scope TypeInfo ti, const TypeInfo tin
return bi;
}
-BlkInfo __arrayAlloc(size_t arrsize, ref BlkInfo info, const scope TypeInfo ti, const TypeInfo tinext)
+private BlkInfo __arrayAlloc(size_t arrsize, ref BlkInfo info, const scope TypeInfo ti, const TypeInfo tinext)
{
import core.checkedint;
@@ -446,7 +469,7 @@ BlkInfo __arrayAlloc(size_t arrsize, ref BlkInfo info, const scope TypeInfo ti,
/**
cache for the lookup of the block info
*/
-enum N_CACHE_BLOCKS=8;
+private enum N_CACHE_BLOCKS=8;
// note this is TLS, so no need to sync.
BlkInfo *__blkcache_storage;
@@ -644,10 +667,15 @@ void __insertBlkInfoCache(BlkInfo bi, BlkInfo *curpos) nothrow
}
/**
- * Shrink the "allocated" length of an array to be the exact size of the array.
- * It doesn't matter what the current allocated length of the array is, the
- * user is telling the runtime that he knows what he is doing.
- */
+Shrink the "allocated" length of an array to be the exact size of the array.
+
+It doesn't matter what the current allocated length of the array is, the
+user is telling the runtime that he knows what he is doing.
+
+Params:
+ ti = `TypeInfo` of array type
+ arr = array to shrink. Its `.length` is element length, not byte length, despite `void` type
+*/
extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) /+nothrow+/
{
// note, we do not care about shared. We are setting the length no matter
@@ -690,7 +718,7 @@ extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) /+nothrow+/
}
}
-package bool hasPostblit(in TypeInfo ti)
+package bool hasPostblit(in TypeInfo ti) nothrow pure
{
return (&ti.postblit).funcptr !is &TypeInfo.postblit;
}
@@ -726,12 +754,21 @@ void __doPostblit(void *ptr, size_t len, const TypeInfo ti)
/**
- * set the array capacity. If the array capacity isn't currently large enough
- * to hold the requested capacity (in number of elements), then the array is
- * resized/reallocated to the appropriate size. Pass in a requested capacity
- * of 0 to get the current capacity. Returns the number of elements that can
- * actually be stored once the resizing is done.
- */
+Set the array capacity.
+
+If the array capacity isn't currently large enough
+to hold the requested capacity (in number of elements), then the array is
+resized/reallocated to the appropriate size.
+
+Pass in a requested capacity of 0 to get the current capacity.
+
+Params:
+ ti = type info of element type
+ newcapacity = requested new capacity
+ p = pointer to array to set. Its `length` is left unchanged.
+
+Returns: the number of elements that can actually be stored once the resizing is done
+*/
extern(C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* p) @weak
in
{
@@ -902,9 +939,18 @@ Lcontinue:
}
/**
- * Allocate a new uninitialized array of length elements.
- * ti is the type of the resulting array, or pointer to element.
- */
+Allocate an array with the garbage collector.
+
+Has three variants:
+- `_d_newarrayU` leave elements uninitialized
+- `_d_newarrayT` initializes to 0 (e.g `new int[]`)
+- `_d_newarrayiT` initializes based on initializer retrieved from TypeInfo (e.g `new float[]`)
+
+Params:
+ ti = the type of the resulting array, (may also be the corresponding `array.ptr` type)
+ length = `.length` of resulting array
+Returns: newly allocated array
+*/
extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow @weak
{
import core.exception : onOutOfMemoryError;
@@ -961,11 +1007,7 @@ Lcontinue:
return arrstart[0..length];
}
-/**
- * Allocate a new array of length elements.
- * ti is the type of the resulting array, or pointer to element.
- * (For when the array is initialized to 0)
- */
+/// ditto
extern (C) void[] _d_newarrayT(const TypeInfo ti, size_t length) pure nothrow @weak
{
import core.stdc.string;
@@ -978,9 +1020,7 @@ extern (C) void[] _d_newarrayT(const TypeInfo ti, size_t length) pure nothrow @w
return result;
}
-/**
- * For when the array has a non-zero initializer.
- */
+/// ditto
extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) pure nothrow @weak
{
import core.internal.traits : AliasSeq;
@@ -1016,10 +1056,10 @@ extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) pure nothrow @
}
-/**
- *
+/*
+ * Helper for creating multi-dimensional arrays
*/
-void[] _d_newarrayOpT(alias op)(const TypeInfo ti, size_t[] dims)
+private void[] _d_newarrayOpT(alias op)(const TypeInfo ti, size_t[] dims)
{
debug(PRINTF) printf("_d_newarrayOpT(ndims = %d)\n", dims.length);
if (dims.length == 0)
@@ -1058,8 +1098,30 @@ void[] _d_newarrayOpT(alias op)(const TypeInfo ti, size_t[] dims)
/**
- *
- */
+Create a new multi-dimensional array
+
+Has two variants:
+- `_d_newarraymTX` which initializes to 0
+- `_d_newarraymiTX` which initializes elements based on `TypeInfo`
+
+---
+void main()
+{
+ new int[][](10, 20);
+ // _d_newarraymTX(typeid(float), [10, 20]);
+
+ new float[][][](10, 20, 30);
+ // _d_newarraymiTX(typeid(float), [10, 20, 30]);
+}
+---
+
+Params:
+ ti = `TypeInfo` of the array type
+ dims = array length values for each dimension
+
+Returns:
+ newly allocated array
+*/
extern (C) void[] _d_newarraymTX(const TypeInfo ti, size_t[] dims) @weak
{
debug(PRINTF) printf("_d_newarraymT(dims.length = %d)\n", dims.length);
@@ -1072,10 +1134,7 @@ extern (C) void[] _d_newarraymTX(const TypeInfo ti, size_t[] dims) @weak
}
}
-
-/**
- *
- */
+/// ditto
extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims) @weak
{
debug(PRINTF) printf("_d_newarraymiT(dims.length = %d)\n", dims.length);
@@ -1089,9 +1148,31 @@ extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims) @weak
}
/**
- * Allocate an uninitialized non-array item.
- * This is an optimization to avoid things needed for arrays like the __arrayPad(size).
- */
+Allocate an uninitialized non-array item.
+
+This is an optimization to avoid things needed for arrays like the __arrayPad(size).
+
+- `_d_newitemU` leaves the item uninitialized
+- `_d_newitemT` zero initializes the item
+- `_d_newitemiT` uses a non-zero initializer from `TypeInfo`
+
+Used to allocate struct instances on the heap.
+---
+struct Sz {int x = 0;}
+struct Si {int x = 3;}
+
+void main()
+{
+ new Sz(); // _d_newitemT(typeid(Sz))
+ new Si(); // _d_newitemiT(typeid(Si))
+}
+---
+
+Params:
+ _ti = `TypeInfo` of item to allocate
+Returns:
+ newly allocated item
+*/
extern (C) void* _d_newitemU(scope const TypeInfo _ti) pure nothrow @weak
{
auto ti = unqualify(_ti);
@@ -1115,7 +1196,7 @@ extern (C) void* _d_newitemU(scope const TypeInfo _ti) pure nothrow @weak
return p;
}
-/// Same as above, zero initializes the item.
+/// ditto
extern (C) void* _d_newitemT(in TypeInfo _ti) pure nothrow @weak
{
import core.stdc.string;
@@ -1135,15 +1216,6 @@ extern (C) void* _d_newitemiT(in TypeInfo _ti) pure nothrow @weak
return p;
}
-/**
- *
- */
-struct Array
-{
- size_t length;
- byte* data;
-}
-
debug(PRINTF)
{
extern(C) void printArrayCache()
@@ -1426,6 +1498,7 @@ extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true)
}
}
+/// Backwards compatibility
extern (C) void rt_finalize(void* p, bool det = true) nothrow
{
rt_finalize2(p, det, true);
@@ -1444,8 +1517,29 @@ extern (C) void rt_finalizeFromGC(void* p, size_t size, uint attr) nothrow
/**
- * Resize dynamic arrays with 0 initializers.
- */
+Resize a dynamic array by setting the `.length` property
+
+Newly created elements are initialized to their default value.
+
+Has two variants:
+- `_d_arraysetlengthT` for arrays with elements that initialize to 0
+- `_d_arraysetlengthiT` for non-zero initializers retrieved from `TypeInfo`
+
+---
+void main()
+{
+ int[] a = [1, 2];
+ a.length = 3; // gets lowered to `_d_arraysetlengthT(typeid(int[]), 3, &a)`
+}
+---
+
+Params:
+ ti = `TypeInfo` of array
+ newlength = new value for the array's `.length`
+ p = pointer to array to update the `.length` of.
+ While it's cast to `void[]`, its `.length` is still treated as element length.
+Returns: `*p` after being updated
+*/
extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p) @weak
in
{
@@ -1639,15 +1733,7 @@ do
return *p;
}
-
-/**
- * Resize arrays for non-zero initializers.
- * p pointer to array lvalue to be updated
- * newlength new .length property of array
- * sizeelem size of each element of array
- * initsize size of initializer
- * ... initializer
- */
+/// ditto
extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p) @weak
in
{
@@ -1859,8 +1945,31 @@ do
/**
- *
- */
+Given an array of length `size` that needs to be expanded to `newlength`,
+compute a new capacity.
+
+Better version by Dave Fladebo:
+This uses an inverse logorithmic algorithm to pre-allocate a bit more
+space for larger arrays.
+- Arrays smaller than PAGESIZE bytes are left as-is, so for the most
+common cases, memory allocation is 1 to 1. The small overhead added
+doesn't affect small array perf. (it's virtually the same as
+current).
+- Larger arrays have some space pre-allocated.
+- As the arrays grow, the relative pre-allocated space shrinks.
+- The logorithmic algorithm allocates relatively more space for
+mid-size arrays, making it very fast for medium arrays (for
+mid-to-large arrays, this turns out to be quite a bit faster than the
+equivalent realloc() code in C, on Linux at least. Small arrays are
+just as fast as GCC).
+- Perhaps most importantly, overall memory usage and stress on the GC
+is decreased significantly for demanding environments.
+
+Params:
+ newlength = new `.length`
+ size = old `.length`
+Returns: new capacity for array
+*/
size_t newCapacity(size_t newlength, size_t size)
{
version (none)
@@ -1869,24 +1978,6 @@ size_t newCapacity(size_t newlength, size_t size)
}
else
{
- /*
- * Better version by Dave Fladebo:
- * This uses an inverse logorithmic algorithm to pre-allocate a bit more
- * space for larger arrays.
- * - Arrays smaller than PAGESIZE bytes are left as-is, so for the most
- * common cases, memory allocation is 1 to 1. The small overhead added
- * doesn't affect small array perf. (it's virtually the same as
- * current).
- * - Larger arrays have some space pre-allocated.
- * - As the arrays grow, the relative pre-allocated space shrinks.
- * - The logorithmic algorithm allocates relatively more space for
- * mid-size arrays, making it very fast for medium arrays (for
- * mid-to-large arrays, this turns out to be quite a bit faster than the
- * equivalent realloc() code in C, on Linux at least. Small arrays are
- * just as fast as GCC).
- * - Perhaps most importantly, overall memory usage and stress on the GC
- * is decreased significantly for demanding environments.
- */
size_t newcap = newlength * size;
size_t newext = 0;
@@ -1940,10 +2031,17 @@ size_t newCapacity(size_t newlength, size_t size)
}
-/**************************************
- * Extend an array by n elements.
- * Caller must initialize those elements.
- */
+/**
+Extend an array by n elements.
+
+Caller must initialize those elements.
+
+Params:
+ ti = type info of array type (not element type)
+ px = array to append to, cast to `byte[]` while keeping the same `.length`. Will be updated.
+ n = number of elements to append
+Returns: `px` after being appended to
+*/
extern (C)
byte[] _d_arrayappendcTX(const TypeInfo ti, return scope ref byte[] px, size_t n) @weak
{
@@ -2047,8 +2145,21 @@ byte[] _d_arrayappendcTX(const TypeInfo ti, return scope ref byte[] px, size_t n
/**
- * Append dchar to char[]
- */
+Append `dchar` to `char[]`, converting UTF-32 to UTF-8
+
+---
+void main()
+{
+ char[] s;
+ s ~= 'α';
+}
+---
+
+Params:
+ x = array to append to cast to `byte[]`. Will be modified.
+ c = `dchar` to append
+Returns: updated `x` cast to `void[]`
+*/
extern (C) void[] _d_arrayappendcd(ref byte[] x, dchar c) @weak
{
// c could encode into from 1 to 4 characters
@@ -2129,8 +2240,23 @@ unittest
/**
- * Append dchar to wchar[]
- */
+Append `dchar` to `wchar[]`, converting UTF-32 to UTF-16
+
+---
+void main()
+{
+ dchar x;
+ wchar[] s;
+ s ~= 'α';
+}
+---
+
+Params:
+ x = array to append to cast to `byte[]`. Will be modified.
+ c = `dchar` to append
+
+Returns: updated `x` cast to `void[]`
+*/
extern (C) void[] _d_arrayappendwd(ref byte[] x, dchar c) @weak
{
// c could encode into from 1 to 2 w characters
@@ -2162,8 +2288,24 @@ extern (C) void[] _d_arrayappendwd(ref byte[] x, dchar c) @weak
/**
- *
- */
+Concatenate two arrays into a new array
+
+---
+void main()
+{
+ int[] x = [10, 20, 30];
+ int[] y = [40, 50];
+ int[] c = x ~ y; // _d_arraycatT(typeid(int[]), (cast(byte*) x)[0..x.length], (cast(byte*) y)[0..y.length]);
+}
+---
+
+Params:
+ ti = type that the two arrays share
+ x = left hand side array casted to `byte[]`. Despite this cast, its `.length` is original element length, not byte length
+ y = right hand side array casted to `byte[]`. Despite this cast, its `.length` is original element length, not byte length
+Returns:
+ resulting concatenated array, with `.length` equal to new element length despite `byte` type
+*/
extern (C) byte[] _d_arraycatT(const TypeInfo ti, byte[] x, byte[] y) @weak
out (result)
{
@@ -2228,8 +2370,27 @@ do
/**
- *
- */
+Concatenate multiple arrays at once
+
+This is more efficient than repeatedly concatenating pairs of arrays because the total size is known in advance.
+
+```
+void main()
+{
+ int[] a, b, c;
+ int[] res = a ~ b ~ c;
+ // _d_arraycatnTX(typeid(int[]),
+ // [(cast(byte*)a.ptr)[0..a.length], (cast(byte*)b.ptr)[0..b.length], (cast(byte*)c.ptr)[0..c.length]]);
+}
+```
+
+Params:
+ ti = type of arrays to concatenate and resulting array
+ arrs = array of arrays to concatenate, cast to `byte[]` while keeping `.length` the same
+
+Returns:
+ newly created concatenated array, `.length` equal to the total element length despite `void` type
+*/
extern (C) void[] _d_arraycatnTX(const TypeInfo ti, scope byte[][] arrs) @weak
{
import core.stdc.string;
@@ -2268,8 +2429,27 @@ extern (C) void[] _d_arraycatnTX(const TypeInfo ti, scope byte[][] arrs) @weak
/**
- * Allocate the array, rely on the caller to do the initialization of the array.
- */
+Allocate an array literal
+
+Rely on the caller to do the initialization of the array.
+
+---
+int[] getArr()
+{
+ return [10, 20];
+ // auto res = cast(int*) _d_arrayliteralTX(typeid(int[]), 2);
+ // res[0] = 10;
+ // res[1] = 20;
+ // return res[0..2];
+}
+---
+
+Params:
+ ti = `TypeInfo` of resulting array type
+ length = `.length` of array literal
+
+Returns: pointer to allocated array
+*/
extern (C)
void* _d_arrayliteralTX(const TypeInfo ti, size_t length) @weak
{