aboutsummaryrefslogtreecommitdiff
path: root/libphobos
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2023-01-29 21:06:59 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2023-02-21 15:33:38 +0100
commitf99303eb4aafef70075951731b3ad99266fe6225 (patch)
tree582ebb6e3e8fd966732bc3b92da1a63caad1aca7 /libphobos
parent7e9dd9de169034810b92d47bf78284db731fa5da (diff)
downloadgcc-f99303eb4aafef70075951731b3ad99266fe6225.zip
gcc-f99303eb4aafef70075951731b3ad99266fe6225.tar.gz
gcc-f99303eb4aafef70075951731b3ad99266fe6225.tar.bz2
d: Merge upstream dmd, druntime 09faa4eacd, phobos 13ef27a56.
D front-end changes: - Import dmd v2.102.0-beta.1 - `static assert' now supports multiple message arguments. D runtime changes: - Import druntime v2.102.0-beta.1 - The default `Throwable.TraceInfo' generation now is `@nogc'. - `Object.factory' method has now been deprecated. Phobos changes: - Import phobos v2.102.0-beta.1 - Added float- and double-precision implementations for log function families in std.math. - `std.typecons.Unique' now calls `destroy` on struct types gcc/d/ChangeLog: * Make-lang.in (D_FRONTEND_OBJS): Add d/location.o. * d-lang.cc (d_init_options): Update for new front-end interface. (d_post_options): Call Loc::set after handling options. * dmd/MERGE: Merge upstream dmd 09faa4eacd. * dmd/VERSION: Bump version to v2.102.0-beta.1. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 09faa4eacd. * src/MERGE: Merge upstream phobos 13ef27a56. * testsuite/libphobos.exceptions/refcounted.d: Add test for chained reference counted exceptions. * testsuite/libphobos.shared/finalize.d: Add dg-warning for deprecated factory interfaces. * testsuite/libphobos.gc/issue22843.d: New test. gcc/testsuite/ChangeLog: * gdc.dg/simd2a.d: Update. * gdc.dg/simd2b.d: Update. * gdc.dg/simd2c.d: Update. * gdc.dg/simd2d.d: Update. * gdc.dg/simd2e.d: Update. * gdc.dg/simd2f.d: Update. * gdc.dg/simd2g.d: Update. * gdc.dg/simd2h.d: Update. * gdc.dg/simd2i.d: Update. * gdc.dg/simd2j.d: Update.
Diffstat (limited to 'libphobos')
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/core/demangle.d6
-rw-r--r--libphobos/libdruntime/core/exception.d2
-rw-r--r--libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d14
-rw-r--r--libphobos/libdruntime/core/internal/gc/impl/manual/gc.d7
-rw-r--r--libphobos/libdruntime/core/runtime.d89
-rw-r--r--libphobos/libdruntime/core/stdc/config.d16
-rw-r--r--libphobos/libdruntime/core/sys/darwin/mach/getsect.d2
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/wait.d12
-rw-r--r--libphobos/libdruntime/core/sys/windows/dbghelp.d4
-rw-r--r--libphobos/libdruntime/core/sys/windows/stacktrace.d60
-rw-r--r--libphobos/libdruntime/core/thread/osthread.d12
-rw-r--r--libphobos/libdruntime/core/time.d2
-rw-r--r--libphobos/libdruntime/object.d19
-rw-r--r--libphobos/libdruntime/rt/deh.d2
-rw-r--r--libphobos/libdruntime/rt/dmain2.d10
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/std/algorithm/iteration.d5
-rw-r--r--libphobos/src/std/conv.d6
-rw-r--r--libphobos/src/std/math/exponential.d399
-rw-r--r--libphobos/src/std/math/operations.d2
-rw-r--r--libphobos/src/std/numeric.d2
-rw-r--r--libphobos/src/std/parallelism.d13
-rw-r--r--libphobos/src/std/random.d14
-rw-r--r--libphobos/src/std/regex/package.d2
-rw-r--r--libphobos/src/std/typecons.d26
-rw-r--r--libphobos/testsuite/libphobos.exceptions/refcounted.d34
-rw-r--r--libphobos/testsuite/libphobos.gc/issue22843.d12
-rw-r--r--libphobos/testsuite/libphobos.shared/finalize.d4
29 files changed, 620 insertions, 160 deletions
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 5ee6f62..ac3dd12 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-c8ae4adb2eda515b09b326948e3a4aa9f489af45
+09faa4eacd4fb147107e94eeebf56b3a73fdcc05
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/core/demangle.d b/libphobos/libdruntime/core/demangle.d
index 869ade6..fe27331 100644
--- a/libphobos/libdruntime/core/demangle.d
+++ b/libphobos/libdruntime/core/demangle.d
@@ -2134,7 +2134,7 @@ pure @safe:
*/
char[] demangle(return scope const(char)[] buf, return scope char[] dst = null, CXX_DEMANGLER __cxa_demangle = null) nothrow pure @safe
{
- if (buf.length > 2 && buf[0..2] == "_Z")
+ if (__cxa_demangle && buf.length > 2 && buf[0..2] == "_Z")
return demangleCXX(buf, __cxa_demangle, dst);
auto d = Demangle!()(buf, dst);
// fast path (avoiding throwing & catching exception) for obvious
@@ -2734,6 +2734,9 @@ unittest
s ~= "FiZi";
expected ~= "F";
assert(s.demangle == expected);
+
+ // https://issues.dlang.org/show_bug.cgi?id=23562
+ assert(demangle("_Zv") == "_Zv");
}
// https://issues.dlang.org/show_bug.cgi?id=22235
@@ -2929,6 +2932,7 @@ CXX_DEMANGLER getCXXDemangler() nothrow @trusted
version (FreeBSD) import core.sys.freebsd.dlfcn : RTLD_DEFAULT;
version (linux) import core.sys.linux.dlfcn : RTLD_DEFAULT;
version (NetBSD) import core.sys.netbsd.dlfcn : RTLD_DEFAULT;
+ version (OpenBSD) import core.sys.openbsd.dlfcn : RTLD_DEFAULT;
version (OSX) import core.sys.darwin.dlfcn : RTLD_DEFAULT;
version (Solaris) import core.sys.solaris.dlfcn : RTLD_DEFAULT;
diff --git a/libphobos/libdruntime/core/exception.d b/libphobos/libdruntime/core/exception.d
index 62179fe..d2016b1 100644
--- a/libphobos/libdruntime/core/exception.d
+++ b/libphobos/libdruntime/core/exception.d
@@ -278,7 +278,6 @@ class FinalizeError : Error
this( TypeInfo ci, string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc
{
super( "Finalization error", file, line, next );
- super.info = SuppressTraceInfo.instance;
info = ci;
}
@@ -393,7 +392,6 @@ class InvalidMemoryOperationError : Error
this(string file = __FILE__, size_t line = __LINE__, Throwable next = null ) @safe pure nothrow @nogc
{
super( "Invalid memory operation", file, line, next );
- this.info = SuppressTraceInfo.instance;
}
override string toString() const @trusted
diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
index e29e426..6d19247 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
@@ -110,13 +110,23 @@ alias GC gc_t;
/* ============================ GC =============================== */
// register GC in C constructor (_STI_)
-extern(C) pragma(crt_constructor) void _d_register_conservative_gc()
+private pragma(crt_constructor) void gc_conservative_ctor()
+{
+ _d_register_conservative_gc();
+}
+
+extern(C) void _d_register_conservative_gc()
{
import core.gc.registry;
registerGCFactory("conservative", &initialize);
}
-extern(C) pragma(crt_constructor) void _d_register_precise_gc()
+private pragma(crt_constructor) void gc_precise_ctor()
+{
+ _d_register_precise_gc();
+}
+
+extern(C) void _d_register_precise_gc()
{
import core.gc.registry;
registerGCFactory("precise", &initialize_precise);
diff --git a/libphobos/libdruntime/core/internal/gc/impl/manual/gc.d b/libphobos/libdruntime/core/internal/gc/impl/manual/gc.d
index a65c636..570781e 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/manual/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/manual/gc.d
@@ -29,7 +29,12 @@ static import core.memory;
extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */
// register GC in C constructor (_STI_)
-extern(C) pragma(crt_constructor) void _d_register_manual_gc()
+private pragma(crt_constructor) void gc_manual_ctor()
+{
+ _d_register_manual_gc();
+}
+
+extern(C) void _d_register_manual_gc()
{
import core.gc.registry;
registerGCFactory("manual", &initialize);
diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d
index 799e525..19bb61b 100644
--- a/libphobos/libdruntime/core/runtime.d
+++ b/libphobos/libdruntime/core/runtime.d
@@ -112,7 +112,7 @@ private
alias void delegate( Throwable ) ExceptionHandler;
extern (C) void _d_print_throwable(Throwable t);
- extern (C) void* thread_stackBottom();
+ extern (C) void* thread_stackBottom() nothrow @nogc;
}
@@ -122,7 +122,7 @@ shared static this()
// still possible the app could exit without a stack trace. If
// this becomes an issue, the handler could be set in C main
// before the module ctors are run.
- Runtime.traceHandler = &defaultTraceHandler;
+ Runtime.traceHandler(&defaultTraceHandler, &defaultTraceDeallocator);
}
@@ -284,10 +284,18 @@ struct Runtime
* If the supplied pointer is null then the trace routine should determine
* an appropriate calling context from which to begin the trace.
*
+ * If the deallocator is set, then it is called with the traceinfo when the
+ * exception is finalized. The deallocator is only set in the exception if
+ * the default handler is used to generate the trace info.
+ *
* Params:
* h = The new trace handler. Set to null to disable exception backtracing.
+ * d = The new trace deallocator. If non-null, this will be called on
+ * exception destruction with the trace info, only when the trace
+ * handler is used to generate TraceInfo.
*/
- extern(C) pragma(mangle, "rt_setTraceHandler") static @property void traceHandler(TraceHandler h);
+ extern(C) pragma(mangle, "rt_setTraceHandler") static @property void traceHandler(TraceHandler h,
+ Throwable.TraceDeallocator d = null);
/**
* Gets the current trace handler.
@@ -298,6 +306,14 @@ struct Runtime
extern(C) pragma(mangle, "rt_getTraceHandler") static @property TraceHandler traceHandler();
/**
+ * Gets the current trace deallocator.
+ *
+ * Returns:
+ * The current trace deallocator or null if none has been set.
+ */
+ extern(C) pragma(mangle, "rt_getTraceDeallocator") static @property Throwable.TraceDeallocator traceDeallocator();
+
+ /**
* Overrides the default collect hander with a user-supplied version. This
* routine will be called for each resource object that is finalized in a
* non-deterministic manner--typically during a garbage collection cycle.
@@ -705,6 +721,10 @@ extern (C) UnitTestResult runModuleUnitTests()
* This functions returns a trace handler, allowing to inspect the
* current stack trace.
*
+ * IMPORTANT NOTE! the returned trace is potentially not GC allocated, and so
+ * you must call `defaultTraceDeallocator` when you are finished with the
+ * `TraceInfo`
+ *
* Params:
* ptr = (Windows only) The context to get the stack trace from.
* When `null` (the default), start from the current frame.
@@ -714,14 +734,24 @@ extern (C) UnitTestResult runModuleUnitTests()
* or `null`. If called from a finalizer (destructor), always returns `null`
* as trace handlers allocate.
*/
-Throwable.TraceInfo defaultTraceHandler( void* ptr = null )
+Throwable.TraceInfo defaultTraceHandler( void* ptr = null ) // @nogc
{
+ // NOTE: with traces now being allocated using C malloc, no need to worry
+ // about GC reentrancy. This code left commented out for reference.
+ //
// avoid recursive GC calls in finalizer, trace handlers should be made @nogc instead
- import core.memory : GC;
+ /*import core.memory : GC;
if (GC.inFinalizer)
- return null;
+ return null;*/
- static if (__traits(compiles, new LibBacktrace(0)))
+ static T allocate(T, Args...)(auto ref Args args) @nogc
+ {
+ import core.lifetime : emplace;
+ import core.stdc.stdlib : malloc;
+ auto result = cast(T)malloc(__traits(classInstanceSize, T));
+ return emplace(result, args);
+ }
+ static if (__traits(compiles, allocate!LibBacktrace(0)))
{
version (Posix)
static enum FIRSTFRAME = 4;
@@ -729,9 +759,9 @@ Throwable.TraceInfo defaultTraceHandler( void* ptr = null )
static enum FIRSTFRAME = 4;
else
static enum FIRSTFRAME = 0;
- return new LibBacktrace(FIRSTFRAME);
+ return allocate!LibBacktrace(FIRSTFRAME);
}
- else static if (__traits(compiles, new UnwindBacktrace(0)))
+ else static if (__traits(compiles, allocate!UnwindBacktrace(0)))
{
version (Posix)
static enum FIRSTFRAME = 5;
@@ -739,25 +769,25 @@ Throwable.TraceInfo defaultTraceHandler( void* ptr = null )
static enum FIRSTFRAME = 4;
else
static enum FIRSTFRAME = 0;
- return new UnwindBacktrace(FIRSTFRAME);
+ return allocate!UnwindBacktrace(FIRSTFRAME);
}
else version (Windows)
{
import core.sys.windows.stacktrace;
- static if (__traits(compiles, new StackTrace(0, null)))
+ static if (__traits(compiles, allocate!StackTrace(0, null)))
{
import core.sys.windows.winnt : CONTEXT;
version (Win64)
enum FIRSTFRAME = 4;
else version (Win32)
enum FIRSTFRAME = 0;
- return new StackTrace(FIRSTFRAME, cast(CONTEXT*)ptr);
+ return allocate!StackTrace(FIRSTFRAME, cast(CONTEXT*)ptr);
}
else
return null;
}
- else static if (__traits(compiles, new DefaultTraceInfo()))
- return new DefaultTraceInfo();
+ else static if (__traits(compiles, allocate!DefaultTraceInfo()))
+ return allocate!DefaultTraceInfo();
else
return null;
}
@@ -775,9 +805,32 @@ unittest
{
printf("%.*s\n", cast(int)line.length, line.ptr);
}
+ defaultTraceDeallocator(trace);
}
}
+/***
+ * Deallocate a traceinfo generated by deaultTraceHander.
+ *
+ * Call this function on a TraceInfo generated via `defaultTraceHandler` when
+ * you are done with it. If necessary, this cleans up any manually managed
+ * resources from the `TraceInfo`, and invalidates it. After this, the object
+ * is no longer valid.
+ *
+ * Params:
+ * info = The `TraceInfo` to deallocate. This should only be a value that
+ * was returned by `defaultTraceHandler`.
+ */
+void defaultTraceDeallocator(Throwable.TraceInfo info) nothrow
+{
+ if (info is null)
+ return;
+ auto obj = cast(Object)info;
+ destroy(obj);
+ import core.stdc.stdlib : free;
+ free(cast(void *)obj);
+}
+
version (DRuntime_Use_Libunwind)
{
import core.internal.backtrace.handler;
@@ -791,7 +844,7 @@ else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInf
import core.stdc.stdlib : free;
import core.stdc.string : strlen, memchr, memmove;
- this()
+ this() @nogc
{
// it may not be 1 but it is good enough to get
// in CALL instruction address range for backtrace
@@ -805,13 +858,13 @@ else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInf
elem -= CALL_INSTRUCTION_SIZE;
else // backtrace() failed, do it ourselves
{
- static void** getBasePtr()
+ static void** getBasePtr() @nogc
{
version (D_InlineAsm_X86)
- asm { naked; mov EAX, EBP; ret; }
+ asm @nogc { naked; mov EAX, EBP; ret; }
else
version (D_InlineAsm_X86_64)
- asm { naked; mov RAX, RBP; ret; }
+ asm @nogc { naked; mov RAX, RBP; ret; }
else
return null;
}
diff --git a/libphobos/libdruntime/core/stdc/config.d b/libphobos/libdruntime/core/stdc/config.d
index c576e99..16bc475 100644
--- a/libphobos/libdruntime/core/stdc/config.d
+++ b/libphobos/libdruntime/core/stdc/config.d
@@ -286,6 +286,22 @@ private struct _Complex(T)
{
T re;
T im;
+
+ // Helper properties.
+ pragma(inline, true)
+ {
+ static @property epsilon()() { return _Complex(T.epsilon, T.epsilon); }
+ static @property infinity()() { return _Complex(T.infinity, T.infinity); }
+ static @property max()() { return _Complex(T.max, T.max); }
+ static @property min_normal()() { return _Complex(T.min_normal, T.min_normal); }
+ static @property nan()() { return _Complex(T.nan, T.nan); }
+ static @property dig()() { return T.dig; }
+ static @property mant_dig()() { return T.mant_dig; }
+ static @property max_10_exp()() { return T.max_10_exp; }
+ static @property max_exp()() { return T.max_exp; }
+ static @property min_10_exp()() { return T.min_10_exp; }
+ static @property min_exp()() { return T.min_exp; }
+ }
}
enum __c_complex_float : _Complex!float;
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/getsect.d b/libphobos/libdruntime/core/sys/darwin/mach/getsect.d
index dc42a2d..b6e10a8 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/getsect.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/getsect.d
@@ -148,7 +148,7 @@ version (CoreDdoc)
*
* auto mph = _NSGetMachExecuteHeader();
* int size;
- * assert(getsectdata(mph, "__TEXT", "__text", &size));
+ * assert(getsectiondata(mph, "__TEXT", "__text", &size));
* assert(size > 0);
* }
* ---
diff --git a/libphobos/libdruntime/core/sys/posix/sys/wait.d b/libphobos/libdruntime/core/sys/posix/sys/wait.d
index 145149b..f6b0674 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/wait.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/wait.d
@@ -386,9 +386,15 @@ else version (NetBSD)
else version (OpenBSD)
{
enum WCONTINUED = 8;
- // OpenBSD does not define the following:
- //enum WSTOPPED
- //enum WNOWAIT
+ enum WSTOPPED = WUNTRACED;
+ enum WNOWAIT = 16;
+
+ enum idtype_t
+ {
+ P_ALL,
+ P_PID,
+ P_PGID
+ }
}
else version (DragonFlyBSD)
{
diff --git a/libphobos/libdruntime/core/sys/windows/dbghelp.d b/libphobos/libdruntime/core/sys/windows/dbghelp.d
index de14bce..55fbc56 100644
--- a/libphobos/libdruntime/core/sys/windows/dbghelp.d
+++ b/libphobos/libdruntime/core/sys/windows/dbghelp.d
@@ -31,7 +31,7 @@ extern(Windows)
alias PVOID function(HANDLE hProcess, DWORD64 AddrBase) SymFunctionTableAccess64Func;
alias BOOL function(DWORD MachineType, HANDLE hProcess, HANDLE hThread, STACKFRAME64 *StackFrame, PVOID ContextRecord,
ReadProcessMemoryProc64 ReadMemoryRoutine, FunctionTableAccessProc64 FunctoinTableAccess,
- GetModuleBaseProc64 GetModuleBaseRoutine, TranslateAddressProc64 TranslateAddress) StackWalk64Func;
+ GetModuleBaseProc64 GetModuleBaseRoutine, TranslateAddressProc64 TranslateAddress) @nogc StackWalk64Func;
alias BOOL function(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, IMAGEHLP_LINEA64 *line) SymGetLineFromAddr64Func;
alias DWORD64 function(HANDLE hProcess, DWORD64 dwAddr) SymGetModuleBase64Func;
alias BOOL function(HANDLE hProcess, DWORD64 dwAddr, IMAGEHLP_MODULEA64 *ModuleInfo) SymGetModuleInfo64Func;
@@ -66,7 +66,7 @@ struct DbgHelp
SymRegisterCallback64Func SymRegisterCallback64;
ImagehlpApiVersionFunc ImagehlpApiVersion;
- static DbgHelp* get()
+ static DbgHelp* get() @nogc
{
if ( sm_hndl != sm_hndl.init )
return &sm_inst;
diff --git a/libphobos/libdruntime/core/sys/windows/stacktrace.d b/libphobos/libdruntime/core/sys/windows/stacktrace.d
index 6e5c4cd..8df2972 100644
--- a/libphobos/libdruntime/core/sys/windows/stacktrace.d
+++ b/libphobos/libdruntime/core/sys/windows/stacktrace.d
@@ -24,10 +24,10 @@ import core.sys.windows.windef;
debug(PRINTF) import core.stdc.stdio;
-extern(Windows) void RtlCaptureContext(CONTEXT* ContextRecord);
+extern(Windows) void RtlCaptureContext(CONTEXT* ContextRecord) @nogc;
extern(Windows) DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR pBuffer, DWORD nSize);
-extern(Windows) alias USHORT function(ULONG FramesToSkip, ULONG FramesToCapture, PVOID *BackTrace, PULONG BackTraceHash) RtlCaptureStackBackTraceFunc;
+extern(Windows) alias USHORT function(ULONG FramesToSkip, ULONG FramesToCapture, PVOID *BackTrace, PULONG BackTraceHash) @nogc RtlCaptureStackBackTraceFunc;
private __gshared RtlCaptureStackBackTraceFunc RtlCaptureStackBackTrace;
private __gshared immutable bool initialized;
@@ -42,7 +42,7 @@ public:
* skip = The number of stack frames to skip.
* context = The context to receive the stack trace from. Can be null.
*/
- this(size_t skip, CONTEXT* context)
+ this(size_t skip, CONTEXT* context) @nogc
{
if (context is null)
{
@@ -64,7 +64,7 @@ public:
skip += INTERNALFRAMES;
}
if ( initialized )
- m_trace = trace(skip, context);
+ m_trace = trace(tracebuf[], skip, context);
}
int opApply( scope int delegate(ref const(char[])) dg ) const
@@ -100,18 +100,27 @@ public:
}
/**
- * Receive a stack trace in the form of an address list.
+ * Receive a stack trace in the form of an address list. One form accepts
+ * an allocated buffer, the other form automatically allocates the buffer.
+ *
* Params:
* skip = How many stack frames should be skipped.
* context = The context that should be used. If null the current context is used.
+ * buffer = The buffer to use for the trace. This should be at least 63 elements.
* Returns:
* A list of addresses that can be passed to resolve at a later point in time.
*/
static ulong[] trace(size_t skip = 0, CONTEXT* context = null)
{
+ return trace(new ulong[63], skip, context);
+ }
+
+ /// ditto
+ static ulong[] trace(ulong[] buffer, size_t skip = 0, CONTEXT* context = null) @nogc
+ {
synchronized( typeid(StackTrace) )
{
- return traceNoSync(skip, context);
+ return traceNoSync(buffer, skip, context);
}
}
@@ -131,38 +140,43 @@ public:
}
private:
+ ulong[128] tracebuf;
ulong[] m_trace;
- static ulong[] traceNoSync(size_t skip, CONTEXT* context)
+ static ulong[] traceNoSync(ulong[] buffer, size_t skip, CONTEXT* context) @nogc
{
auto dbghelp = DbgHelp.get();
if (dbghelp is null)
return []; // dbghelp.dll not available
- if (RtlCaptureStackBackTrace !is null && context is null)
+ if (buffer.length >= 63 && RtlCaptureStackBackTrace !is null &&
+ context is null)
{
- size_t[63] buffer = void; // On windows xp the sum of "frames to skip" and "frames to capture" can't be greater then 63
- auto backtraceLength = RtlCaptureStackBackTrace(cast(ULONG)skip, cast(ULONG)(buffer.length - skip), cast(void**)buffer.ptr, null);
+ version (Win64)
+ {
+ auto bufptr = cast(void**)buffer.ptr;
+ }
+ version (Win32)
+ {
+ size_t[63] bufstorage = void; // On windows xp the sum of "frames to skip" and "frames to capture" can't be greater then 63
+ auto bufptr = cast(void**)bufstorage.ptr;
+ }
+ auto backtraceLength = RtlCaptureStackBackTrace(cast(ULONG)skip, cast(ULONG)(63 - skip), bufptr, null);
// If we get a backtrace and it does not have the maximum length use it.
// Otherwise rely on tracing through StackWalk64 which is slower but works when no frame pointers are available.
- if (backtraceLength > 1 && backtraceLength < buffer.length - skip)
+ if (backtraceLength > 1 && backtraceLength < 63 - skip)
{
debug(PRINTF) printf("Using result from RtlCaptureStackBackTrace\n");
- version (Win64)
+ version (Win32)
{
- return buffer[0..backtraceLength].dup;
- }
- else version (Win32)
- {
- auto result = new ulong[backtraceLength];
- foreach (i, ref e; result)
+ foreach (i, ref e; buffer[0 .. backtraceLength])
{
- e = buffer[i];
+ e = bufstorage[i];
}
- return result;
}
+ return buffer[0..backtraceLength];
}
}
@@ -210,21 +224,21 @@ private:
else version (X86_64) enum imageType = IMAGE_FILE_MACHINE_AMD64;
else static assert(0, "unimplemented");
- ulong[] result;
size_t frameNum = 0;
+ size_t nframes = 0;
// do ... while so that we don't skip the first stackframe
do
{
if (frameNum >= skip)
{
- result ~= stackframe.AddrPC.Offset;
+ buffer[nframes++] = stackframe.AddrPC.Offset;
}
frameNum++;
}
while (dbghelp.StackWalk64(imageType, hProcess, hThread, &stackframe,
&ctxt, null, null, null, null));
- return result;
+ return buffer[0 .. nframes];
}
static char[][] resolveNoSync(const(ulong)[] addresses)
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index 415430c..7316373 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -1997,12 +1997,17 @@ extern (C) void thread_suspendAll() nothrow
Thread.criticalRegionLock.lock_nothrow();
scope (exit) Thread.criticalRegionLock.unlock_nothrow();
size_t cnt;
+ bool suspendedSelf;
Thread t = ThreadBase.sm_tbeg.toThread;
while (t)
{
auto tn = t.next.toThread;
if (suspend(t))
+ {
+ if (t is ThreadBase.getThis())
+ suspendedSelf = true;
++cnt;
+ }
t = tn;
}
@@ -2010,9 +2015,12 @@ extern (C) void thread_suspendAll() nothrow
{}
else version (Posix)
{
- // subtract own thread
+ // Subtract own thread if we called suspend() on ourselves.
+ // For example, suspendedSelf would be false if the current
+ // thread ran thread_detachThis().
assert(cnt >= 1);
- --cnt;
+ if (suspendedSelf)
+ --cnt;
// wait for semaphore notifications
for (; cnt; --cnt)
{
diff --git a/libphobos/libdruntime/core/time.d b/libphobos/libdruntime/core/time.d
index ea163a0..8d50875 100644
--- a/libphobos/libdruntime/core/time.d
+++ b/libphobos/libdruntime/core/time.d
@@ -2822,7 +2822,7 @@ struct TickDuration
}
- @trusted shared static this()
+ static pragma(crt_constructor) void time_initializer()
{
version (Windows)
{
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 83351f2..0385b51 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -246,7 +246,7 @@ class Object
* }
* ---
*/
- static Object factory(string classname)
+ deprecated static Object factory(string classname)
{
auto ci = TypeInfo_Class.find(classname);
if (ci)
@@ -256,7 +256,7 @@ class Object
return null;
}
- @system unittest
+ deprecated @system unittest
{
Object valid_obj = Object.factory("object.Object");
Object invalid_obj = Object.factory("object.__this_class_doesnt_exist__");
@@ -2481,6 +2481,8 @@ class Throwable : Object
string toString() const;
}
+ alias TraceDeallocator = void function(TraceInfo) nothrow;
+
string msg; /// A message describing the error.
/**
@@ -2502,6 +2504,12 @@ class Throwable : Object
TraceInfo info;
/**
+ * If set, this is used to deallocate the TraceInfo on destruction.
+ */
+ TraceDeallocator infoDeallocator;
+
+
+ /**
* A reference to the _next error in the list. This is used when a new
* $(D Throwable) is thrown from inside a $(D catch) block. The originally
* caught $(D Exception) will be chained to the new $(D Throwable) via this
@@ -2614,6 +2622,13 @@ class Throwable : Object
{
if (nextInChain && nextInChain._refcount)
_d_delThrowable(nextInChain);
+ // handle owned traceinfo
+ if (infoDeallocator !is null)
+ {
+ infoDeallocator(info);
+ info = null; // avoid any kind of dangling pointers if we can help
+ // it.
+ }
}
/**
diff --git a/libphobos/libdruntime/rt/deh.d b/libphobos/libdruntime/rt/deh.d
index 695f2ce..0a44be3 100644
--- a/libphobos/libdruntime/rt/deh.d
+++ b/libphobos/libdruntime/rt/deh.d
@@ -42,12 +42,14 @@ module rt.deh;
extern (C)
{
Throwable.TraceInfo _d_traceContext(void* ptr = null);
+ Throwable.TraceDeallocator rt_getTraceDeallocator();
void _d_createTrace(Throwable t, void* context)
{
if (t !is null && t.info is null &&
cast(byte*) t !is typeid(t).initializer.ptr)
{
t.info = _d_traceContext(context);
+ t.infoDeallocator = rt_getTraceDeallocator();
}
}
}
diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d
index 264fdf6..8a10aac 100644
--- a/libphobos/libdruntime/rt/dmain2.d
+++ b/libphobos/libdruntime/rt/dmain2.d
@@ -182,6 +182,7 @@ extern (C) int rt_term()
*/
alias Throwable.TraceInfo function(void* ptr) TraceHandler;
private __gshared TraceHandler traceHandler = null;
+private __gshared Throwable.TraceDeallocator traceDeallocator = null;
/**
@@ -189,10 +190,12 @@ private __gshared TraceHandler traceHandler = null;
*
* Params:
* h = The new trace handler. Set to null to use the default handler.
+ * d = The new dealloactor to use.
*/
-extern (C) void rt_setTraceHandler(TraceHandler h)
+extern (C) void rt_setTraceHandler(TraceHandler h, Throwable.TraceDeallocator d = null)
{
traceHandler = h;
+ traceDeallocator = d;
}
/**
@@ -203,6 +206,11 @@ extern (C) TraceHandler rt_getTraceHandler()
return traceHandler;
}
+extern (C) Throwable.TraceDeallocator rt_getTraceDeallocator()
+{
+ return traceDeallocator;
+}
+
/**
* This function will be called when an exception is constructed. The
* user-supplied trace handler will be called if one has been supplied,
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 09da6a8..be31395 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-792c8b7c1d5957767e138f78d04bf175d4b92f10
+13ef27a56e4c22e122fc4dd54bb46b5955babdb0
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d
index 9a365d5..967d2a6 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -7737,8 +7737,9 @@ if (isInputRange!R &&
// uniq
/**
-Lazily iterates unique consecutive elements of the given range (functionality
-akin to the $(HTTP wikipedia.org/wiki/_Uniq, _uniq) system
+Lazily iterates unique consecutive elements of the given range, which is
+assumed to be sorted (functionality akin to the
+$(HTTP wikipedia.org/wiki/_Uniq, _uniq) system
utility). Equivalence of elements is assessed by using the predicate
`pred`, by default `"a == b"`. The predicate is passed to
$(REF binaryFun, std,functional), and can either accept a string, or any callable
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index d1b6421..aef2365 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -1891,9 +1891,7 @@ if (!is(S : T) && isAssociativeArray!S &&
}
// test conversions floating => integral
{
- // AllInts[0 .. $ - 1] should be AllInts
- // @@@ BUG IN COMPILER @@@
- foreach (Integral; AllInts[0 .. $ - 1])
+ foreach (Integral; AllInts)
{
foreach (Floating; AllFloats)
{
@@ -1903,7 +1901,7 @@ if (!is(S : T) && isAssociativeArray!S &&
}
// test conversion integral => floating
{
- foreach (Integral; AllInts[0 .. $ - 1])
+ foreach (Integral; AllInts)
{
foreach (Floating; AllFloats)
{
diff --git a/libphobos/src/std/math/exponential.d b/libphobos/src/std/math/exponential.d
index e32330f..66f4b8a 100644
--- a/libphobos/src/std/math/exponential.d
+++ b/libphobos/src/std/math/exponential.d
@@ -2910,7 +2910,7 @@ private
alias log10P = logP;
alias log10Q = logQ;
- // Coefficients for log(x) = z + z^^3 P(z^^2)/Q(z^^2)
+ // Coefficients for log(x) = z + z^^3 R(z^^2)/S(z^^2)
// where z = 2(x-1)/(x+1)
// Theoretical peak relative error = 1.1e-35
static immutable real[6] logR = [
@@ -2931,7 +2931,8 @@ private
1.0
];
}
- else
+ else static if (floatTraits!T.realFormat == RealFormat.ieeeExtended ||
+ floatTraits!T.realFormat == RealFormat.ieeeExtended53)
{
// Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)/Q(x)
// Theoretical peak relative error = 2.32e-20
@@ -2980,7 +2981,7 @@ private
alias log10P = log2P;
alias log10Q = log2Q;
- // Coefficients for log(x) = z + z^^3 P(z^^2)/Q(z^^2)
+ // Coefficients for log(x) = z + z^^3 R(z^^2)/S(z^^2)
// where z = 2(x-1)/(x+1)
// Theoretical peak relative error = 6.16e-22
static immutable real[4] logR = [
@@ -2996,6 +2997,85 @@ private
1.0000000000000000000000E0L,
];
}
+ else static if (floatTraits!T.realFormat == RealFormat.ieeeDouble)
+ {
+ // Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)/Q(x)
+ static immutable double[6] logP = [
+ 7.70838733755885391666E0,
+ 1.79368678507819816313E1,
+ 1.44989225341610930846E1,
+ 4.70579119878881725854E0,
+ 4.97494994976747001425E-1,
+ 1.01875663804580931796E-4,
+ ];
+ static immutable double[6] logQ = [
+ 2.31251620126765340583E1,
+ 7.11544750618563894466E1,
+ 8.29875266912776603211E1,
+ 4.52279145837532221105E1,
+ 1.12873587189167450590E1,
+ 1.00000000000000000000E0,
+ ];
+
+ // log2 uses the same coefficients as log.
+ alias log2P = logP;
+ alias log2Q = logQ;
+
+ // Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)/Q(x)
+ static immutable double[7] log10P = [
+ 1.98892446572874072159E1,
+ 5.67349287391754285487E1,
+ 6.06127134467767258030E1,
+ 2.97877425097986925891E1,
+ 6.56312093769992875930E0,
+ 4.98531067254050724270E-1,
+ 4.58482948458143443514E-5,
+ ];
+ static immutable double[7] log10Q = [
+ 5.96677339718622216300E1,
+ 2.14955586696422947765E2,
+ 3.07254189979530058263E2,
+ 2.20664384982121929218E2,
+ 8.27410449222435217021E1,
+ 1.50314182634250003249E1,
+ 1.00000000000000000000E0,
+ ];
+
+ // Coefficients for log(x) = z + z^^3 R(z)/S(z)
+ // where z = 2(x-1)/(x+1)
+ static immutable double[3] logR = [
+ -6.41409952958715622951E1,
+ 1.63866645699558079767E1,
+ -7.89580278884799154124E-1,
+ ];
+ static immutable double[4] logS = [
+ -7.69691943550460008604E2,
+ 3.12093766372244180303E2,
+ -3.56722798256324312549E1,
+ 1.00000000000000000000E0,
+ ];
+ }
+ else static if (floatTraits!T.realFormat == RealFormat.ieeeSingle)
+ {
+ // Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)
+ static immutable float[9] logP = [
+ 3.3333331174E-1,
+ -2.4999993993E-1,
+ 2.0000714765E-1,
+ -1.6668057665E-1,
+ 1.4249322787E-1,
+ -1.2420140846E-1,
+ 1.1676998740E-1,
+ -1.1514610310E-1,
+ 7.0376836292E-2,
+ ];
+
+ // log2 and log10 uses the same coefficients as log.
+ alias log2P = logP;
+ alias log10P = logP;
+ }
+ else
+ static assert(0, "no coefficients for log()");
}
}
@@ -3009,6 +3089,7 @@ private
* $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no))
* )
*/
+pragma(inline, true)
real log(real x) @safe pure nothrow @nogc
{
version (INLINE_YL2X)
@@ -3020,6 +3101,31 @@ real log(real x) @safe pure nothrow @nogc
return logImpl(x);
}
+/// ditto
+pragma(inline, true)
+double log(double x) @safe pure nothrow @nogc { return __ctfe ? cast(double) log(cast(real) x) : logImpl(x); }
+
+/// ditto
+pragma(inline, true)
+float log(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) log(cast(real) x) : logImpl(x); }
+
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log` called with argument types `(int)` matches both "
+ ~ "`log(real)`, `log(double)`, and `log(float)`. Cast argument to floating point type instead.")
+real log(int x) @safe pure nothrow @nogc { return log(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log` called with argument types `(uint)` matches both "
+ ~ "`log(real)`, `log(double)`, and `log(float)`. Cast argument to floating point type instead.")
+real log(uint x) @safe pure nothrow @nogc { return log(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log` called with argument types `(long)` matches both "
+ ~ "`log(real)`, `log(double)`, and `log(float)`. Cast argument to floating point type instead.")
+real log(long x) @safe pure nothrow @nogc { return log(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log` called with argument types `(ulong)` matches both "
+ ~ "`log(real)`, `log(double)`, and `log(float)`. Cast argument to floating point type instead.")
+real log(ulong x) @safe pure nothrow @nogc { return log(cast(real) x); }
+
///
@safe pure nothrow @nogc unittest
{
@@ -3034,12 +3140,31 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
import std.math.constants : SQRT1_2;
import std.math.algebraic : poly;
import std.math.traits : isInfinity, isNaN, signbit;
+ import std.math : floatTraits, RealFormat;
alias coeffs = LogCoeffs!T;
+ alias F = floatTraits!T;
- // C1 + C2 = LN2.
- enum T C1 = 6.93145751953125E-1L;
- enum T C2 = 1.428606820309417232121458176568075500134E-6L;
+ static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53 ||
+ F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ // C1 + C2 = LN2.
+ enum T C1 = 6.93145751953125E-1L;
+ enum T C2 = 1.428606820309417232121458176568075500134E-6L;
+ }
+ else static if (F.realFormat == RealFormat.ieeeDouble)
+ {
+ enum T C1 = 0.693359375;
+ enum T C2 = -2.121944400546905827679e-4;
+ }
+ else static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ enum T C1 = 0.693359375;
+ enum T C2 = -2.12194440e-4;
+ }
+ else
+ static assert(0, "Not implemented for this architecture");
// Special cases.
if (isNaN(x))
@@ -3058,30 +3183,36 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
x = frexp(x, exp);
- // Logarithm using log(x) = z + z^^3 R(z) / S(z),
- // where z = 2(x - 1)/(x + 1)
- if ((exp > 2) || (exp < -2))
+ static if (F.realFormat == RealFormat.ieeeDouble ||
+ F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53 ||
+ F.realFormat == RealFormat.ieeeQuadruple)
{
- if (x < SQRT1_2)
- { // 2(2x - 1)/(2x + 1)
- exp -= 1;
- z = x - 0.5;
- y = 0.5 * z + 0.5;
- }
- else
- { // 2(x - 1)/(x + 1)
- z = x - 0.5;
- z -= 0.5;
- y = 0.5 * x + 0.5;
- }
- x = z / y;
- z = x * x;
- z = x * (z * poly(z, coeffs.logR) / poly(z, coeffs.logS));
- z += exp * C2;
- z += x;
- z += exp * C1;
+ // Logarithm using log(x) = z + z^^3 R(z) / S(z),
+ // where z = 2(x - 1)/(x + 1)
+ if ((exp > 2) || (exp < -2))
+ {
+ if (x < SQRT1_2)
+ { // 2(2x - 1)/(2x + 1)
+ exp -= 1;
+ z = x - 0.5;
+ y = 0.5 * z + 0.5;
+ }
+ else
+ { // 2(x - 1)/(x + 1)
+ z = x - 0.5;
+ z -= 0.5;
+ y = 0.5 * x + 0.5;
+ }
+ x = z / y;
+ z = x * x;
+ z = x * (z * poly(z, coeffs.logR) / poly(z, coeffs.logS));
+ z += exp * C2;
+ z += x;
+ z += exp * C1;
- return z;
+ return z;
+ }
}
// Logarithm using log(1 + x) = x - .5x^^2 + x^^3 P(x) / Q(x)
@@ -3095,7 +3226,10 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
x = x - 1.0;
}
z = x * x;
- y = x * (z * poly(x, coeffs.logP) / poly(x, coeffs.logQ));
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ y = x * (z * poly(x, coeffs.logP));
+ else
+ y = x * (z * poly(x, coeffs.logP) / poly(x, coeffs.logQ));
y += exp * C2;
z = y - 0.5 * z;
@@ -3117,6 +3251,7 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
* $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no))
* )
*/
+pragma(inline, true)
real log10(real x) @safe pure nothrow @nogc
{
version (INLINE_YL2X)
@@ -3128,12 +3263,37 @@ real log10(real x) @safe pure nothrow @nogc
return log10Impl(x);
}
+/// ditto
+pragma(inline, true)
+double log10(double x) @safe pure nothrow @nogc { return __ctfe ? cast(double) log10(cast(real) x) : log10Impl(x); }
+
+/// ditto
+pragma(inline, true)
+float log10(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) log10(cast(real) x) : log10Impl(x); }
+
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log10` called with argument types `(int)` matches both "
+ ~ "`log10(real)`, `log10(double)`, and `log10(float)`. Cast argument to floating point type instead.")
+real log10(int x) @safe pure nothrow @nogc { return log10(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log10` called with argument types `(uint)` matches both "
+ ~ "`log10(real)`, `log10(double)`, and `log10(float)`. Cast argument to floating point type instead.")
+real log10(uint x) @safe pure nothrow @nogc { return log10(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log10` called with argument types `(long)` matches both "
+ ~ "`log10(real)`, `log10(double)`, and `log10(float)`. Cast argument to floating point type instead.")
+real log10(long x) @safe pure nothrow @nogc { return log10(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log10` called with argument types `(ulong)` matches both "
+ ~ "`log10(real)`, `log10(double)`, and `log10(float)`. Cast argument to floating point type instead.")
+real log10(ulong x) @safe pure nothrow @nogc { return log10(cast(real) x); }
+
///
@safe pure nothrow @nogc unittest
{
import std.math.algebraic : fabs;
- assert(fabs(log10(1000) - 3) < .000001);
+ assert(fabs(log10(1000.0L) - 3) < .000001);
}
private T log10Impl(T)(T x) @safe pure nothrow @nogc
@@ -3141,16 +3301,34 @@ private T log10Impl(T)(T x) @safe pure nothrow @nogc
import std.math.constants : SQRT1_2;
import std.math.algebraic : poly;
import std.math.traits : isNaN, isInfinity, signbit;
+ import std.math : floatTraits, RealFormat;
alias coeffs = LogCoeffs!T;
+ alias F = floatTraits!T;
- // log10(2) split into two parts.
- enum T L102A = 0.3125L;
- enum T L102B = -1.14700043360188047862611052755069732318101185E-2L;
+ static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53 ||
+ F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ // log10(2) split into two parts.
+ enum T L102A = 0.3125L;
+ enum T L102B = -1.14700043360188047862611052755069732318101185E-2L;
- // log10(e) split into two parts.
- enum T L10EA = 0.5L;
- enum T L10EB = -6.570551809674817234887108108339491770560299E-2L;
+ // log10(e) split into two parts.
+ enum T L10EA = 0.5L;
+ enum T L10EB = -6.570551809674817234887108108339491770560299E-2L;
+ }
+ else static if (F.realFormat == RealFormat.ieeeDouble ||
+ F.realFormat == RealFormat.ieeeSingle)
+ {
+ enum T L102A = 3.0078125E-1;
+ enum T L102B = 2.48745663981195213739E-4;
+
+ enum T L10EA = 4.3359375E-1;
+ enum T L10EB = 7.00731903251827651129E-4;
+ }
+ else
+ static assert(0, "Not implemented for this architecture");
// Special cases are the same as for log.
if (isNaN(x))
@@ -3169,26 +3347,31 @@ private T log10Impl(T)(T x) @safe pure nothrow @nogc
x = frexp(x, exp);
- // Logarithm using log(x) = z + z^^3 R(z) / S(z),
- // where z = 2(x - 1)/(x + 1)
- if ((exp > 2) || (exp < -2))
- {
- if (x < SQRT1_2)
- { // 2(2x - 1)/(2x + 1)
- exp -= 1;
- z = x - 0.5;
- y = 0.5 * z + 0.5;
- }
- else
- { // 2(x - 1)/(x + 1)
- z = x - 0.5;
- z -= 0.5;
- y = 0.5 * x + 0.5;
+ static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53 ||
+ F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ // Logarithm using log(x) = z + z^^3 R(z) / S(z),
+ // where z = 2(x - 1)/(x + 1)
+ if ((exp > 2) || (exp < -2))
+ {
+ if (x < SQRT1_2)
+ { // 2(2x - 1)/(2x + 1)
+ exp -= 1;
+ z = x - 0.5;
+ y = 0.5 * z + 0.5;
+ }
+ else
+ { // 2(x - 1)/(x + 1)
+ z = x - 0.5;
+ z -= 0.5;
+ y = 0.5 * x + 0.5;
+ }
+ x = z / y;
+ z = x * x;
+ y = x * (z * poly(z, coeffs.logR) / poly(z, coeffs.logS));
+ goto Ldone;
}
- x = z / y;
- z = x * x;
- y = x * (z * poly(z, coeffs.logR) / poly(z, coeffs.logS));
- goto Ldone;
}
// Logarithm using log(1 + x) = x - .5x^^2 + x^^3 P(x) / Q(x)
@@ -3201,7 +3384,10 @@ private T log10Impl(T)(T x) @safe pure nothrow @nogc
x = x - 1.0;
z = x * x;
- y = x * (z * poly(x, coeffs.log10P) / poly(x, coeffs.log10Q));
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ y = x * (z * poly(x, coeffs.log10P));
+ else
+ y = x * (z * poly(x, coeffs.log10P) / poly(x, coeffs.log10Q));
y = y - 0.5 * z;
// Multiply log of fraction by log10(e) and base 2 exponent by log10(2).
@@ -3232,6 +3418,7 @@ Ldone:
* $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no))
* )
*/
+pragma(inline, true)
real log1p(real x) @safe pure nothrow @nogc
{
version (INLINE_YL2X)
@@ -3245,6 +3432,31 @@ real log1p(real x) @safe pure nothrow @nogc
return log1pImpl(x);
}
+/// ditto
+pragma(inline, true)
+double log1p(double x) @safe pure nothrow @nogc { return __ctfe ? cast(double) log1p(cast(real) x) : log1pImpl(x); }
+
+/// ditto
+pragma(inline, true)
+float log1p(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) log1p(cast(real) x) : log1pImpl(x); }
+
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log1p` called with argument types `(int)` matches both "
+ ~ "`log1p(real)`, `log1p(double)`, and `log1p(float)`. Cast argument to floating point type instead.")
+real log1p(int x) @safe pure nothrow @nogc { return log1p(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log1p` called with argument types `(uint)` matches both "
+ ~ "`log1p(real)`, `log1p(double)`, and `log1p(float)`. Cast argument to floating point type instead.")
+real log1p(uint x) @safe pure nothrow @nogc { return log1p(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log1p` called with argument types `(long)` matches both "
+ ~ "`log1p(real)`, `log1p(double)`, and `log1p(float)`. Cast argument to floating point type instead.")
+real log1p(long x) @safe pure nothrow @nogc { return log1p(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log1p` called with argument types `(ulong)` matches both "
+ ~ "`log1p(real)`, `log1p(double)`, and `log1p(float)`. Cast argument to floating point type instead.")
+real log1p(ulong x) @safe pure nothrow @nogc { return log1p(cast(real) x); }
+
///
@safe pure unittest
{
@@ -3289,6 +3501,7 @@ private T log1pImpl(T)(T x) @safe pure nothrow @nogc
* $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no) )
* )
*/
+pragma(inline, true)
real log2(real x) @safe pure nothrow @nogc
{
version (INLINE_YL2X)
@@ -3297,6 +3510,31 @@ real log2(real x) @safe pure nothrow @nogc
return log2Impl(x);
}
+/// ditto
+pragma(inline, true)
+double log2(double x) @safe pure nothrow @nogc { return __ctfe ? cast(double) log2(cast(real) x) : log2Impl(x); }
+
+/// ditto
+pragma(inline, true)
+float log2(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) log2(cast(real) x) : log2Impl(x); }
+
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log2` called with argument types `(int)` matches both "
+ ~ "`log2(real)`, `log2(double)`, and `log2(float)`. Cast argument to floating point type instead.")
+real log2(int x) @safe pure nothrow @nogc { return log2(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log2` called with argument types `(uint)` matches both "
+ ~ "`log2(real)`, `log2(double)`, and `log2(float)`. Cast argument to floating point type instead.")
+real log2(uint x) @safe pure nothrow @nogc { return log2(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log2` called with argument types `(long)` matches both "
+ ~ "`log2(real)`, `log2(double)`, and `log2(float)`. Cast argument to floating point type instead.")
+real log2(long x) @safe pure nothrow @nogc { return log2(cast(real) x); }
+// @@@DEPRECATED_[2.112.0]@@@
+deprecated("`std.math.exponential.log2` called with argument types `(ulong)` matches both "
+ ~ "`log2(real)`, `log2(double)`, and `log2(float)`. Cast argument to floating point type instead.")
+real log2(ulong x) @safe pure nothrow @nogc { return log2(cast(real) x); }
+
///
@safe unittest
{
@@ -3318,8 +3556,10 @@ private T log2Impl(T)(T x) @safe pure nothrow @nogc
import std.math.traits : isNaN, isInfinity, signbit;
import std.math.constants : SQRT1_2, LOG2E;
import std.math.algebraic : poly;
+ import std.math : floatTraits, RealFormat;
alias coeffs = LogCoeffs!T;
+ alias F = floatTraits!T;
// Special cases are the same as for log.
if (isNaN(x))
@@ -3338,26 +3578,32 @@ private T log2Impl(T)(T x) @safe pure nothrow @nogc
x = frexp(x, exp);
- // Logarithm using log(x) = z + z^^3 R(z) / S(z),
- // where z = 2(x - 1)/(x + 1)
- if ((exp > 2) || (exp < -2))
+ static if (F.realFormat == RealFormat.ieeeDouble ||
+ F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53 ||
+ F.realFormat == RealFormat.ieeeQuadruple)
{
- if (x < SQRT1_2)
- { // 2(2x - 1)/(2x + 1)
- exp -= 1;
- z = x - 0.5;
- y = 0.5 * z + 0.5;
- }
- else
- { // 2(x - 1)/(x + 1)
- z = x - 0.5;
- z -= 0.5;
- y = 0.5 * x + 0.5;
+ // Logarithm using log(x) = z + z^^3 R(z) / S(z),
+ // where z = 2(x - 1)/(x + 1)
+ if ((exp > 2) || (exp < -2))
+ {
+ if (x < SQRT1_2)
+ { // 2(2x - 1)/(2x + 1)
+ exp -= 1;
+ z = x - 0.5;
+ y = 0.5 * z + 0.5;
+ }
+ else
+ { // 2(x - 1)/(x + 1)
+ z = x - 0.5;
+ z -= 0.5;
+ y = 0.5 * x + 0.5;
+ }
+ x = z / y;
+ z = x * x;
+ y = x * (z * poly(z, coeffs.logR) / poly(z, coeffs.logS));
+ goto Ldone;
}
- x = z / y;
- z = x * x;
- y = x * (z * poly(z, coeffs.logR) / poly(z, coeffs.logS));
- goto Ldone;
}
// Logarithm using log(1 + x) = x - .5x^^2 + x^^3 P(x) / Q(x)
@@ -3370,7 +3616,10 @@ private T log2Impl(T)(T x) @safe pure nothrow @nogc
x = x - 1.0;
z = x * x;
- y = x * (z * poly(x, coeffs.log2P) / poly(x, coeffs.log2Q));
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ y = x * (z * poly(x, coeffs.log2P));
+ else
+ y = x * (z * poly(x, coeffs.log2P) / poly(x, coeffs.log2Q));
y = y - 0.5 * z;
// Multiply log of fraction by log10(e) and base 2 exponent by log10(2).
diff --git a/libphobos/src/std/math/operations.d b/libphobos/src/std/math/operations.d
index cb3c805..f2e1800 100644
--- a/libphobos/src/std/math/operations.d
+++ b/libphobos/src/std/math/operations.d
@@ -1793,7 +1793,7 @@ if (isFloatingPoint!T)
}
import std.math.exponential : log2;
- enum log2_max_exp = cast(int) log2(T.max_exp);
+ enum log2_max_exp = cast(int) log2(T(T.max_exp));
ret.mantissa = ival & ((1L << (T.mant_dig - 1)) - 1);
ret.exponent = (ival >> (T.mant_dig - 1)) & ((1L << (log2_max_exp + 1)) - 1);
diff --git a/libphobos/src/std/numeric.d b/libphobos/src/std/numeric.d
index df7ac39..648b70e 100644
--- a/libphobos/src/std/numeric.d
+++ b/libphobos/src/std/numeric.d
@@ -436,7 +436,7 @@ public:
static @property size_t dig()
{
auto shiftcnt = precision - ((flags&Flags.storeNormalized) == 0);
- return shiftcnt == 64 ? 19 : cast(size_t) log10(1uL << shiftcnt);
+ return shiftcnt == 64 ? 19 : cast(size_t) log10(real(1uL << shiftcnt));
}
/// Returns: smallest increment to the value 1
diff --git a/libphobos/src/std/parallelism.d b/libphobos/src/std/parallelism.d
index 2c97638..9b231f3 100644
--- a/libphobos/src/std/parallelism.d
+++ b/libphobos/src/std/parallelism.d
@@ -1508,7 +1508,7 @@ public:
if (this.size == 0)
{
- return rangeLen;
+ return max(rangeLen, 1);
}
immutable size_t eightSize = 4 * (this.size + 1);
@@ -3644,6 +3644,15 @@ ParallelForeach!R parallel(R)(R range, size_t workUnitSize)
assert(arrIndex.sum == 10.iota.sum);
}
+// https://issues.dlang.org/show_bug.cgi?id=22745
+@system unittest
+{
+ auto pool = new TaskPool(0);
+ int[] empty;
+ foreach (i; pool.parallel(empty)) {}
+ pool.finish();
+}
+
// Thrown when a parallel foreach loop is broken from.
class ParallelForeachError : Error
{
@@ -4339,7 +4348,7 @@ version (StdUnittest)
foreach (i, elem; logs)
{
- assert(isClose(elem, cast(double) log(i + 1)));
+ assert(isClose(elem, log(double(i + 1))));
}
assert(poolInstance.amap!"a * a"([1,2,3,4,5]) == [1,4,9,16,25]);
diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d
index 9b3c5ed..93be764 100644
--- a/libphobos/src/std/random.d
+++ b/libphobos/src/std/random.d
@@ -2516,7 +2516,7 @@ if (!is(T == enum) && (isIntegral!T || isSomeChar!T))
assert(rnd.uniform!ulong == 4838462006927449017);
enum Fruit { apple, mango, pear }
- version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
+ version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
assert(rnd.uniform!Fruit == Fruit.mango);
}
@@ -2798,7 +2798,7 @@ auto ref choice(Range)(ref Range range)
auto rnd = MinstdRand0(42);
auto elem = [1, 2, 3, 4, 5].choice(rnd);
- version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
+ version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
assert(elem == 3);
}
@@ -2913,7 +2913,7 @@ if (isRandomAccessRange!Range)
auto rnd = MinstdRand0(42);
auto arr = [1, 2, 3, 4, 5].randomShuffle(rnd);
- version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
+ version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
assert(arr == [3, 5, 2, 4, 1]);
}
@@ -3003,15 +3003,15 @@ if (isRandomAccessRange!Range)
auto arr = [1, 2, 3, 4, 5, 6];
arr = arr.dup.partialShuffle(1, rnd);
- version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
+ version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
assert(arr == [2, 1, 3, 4, 5, 6]); // 1<->2
arr = arr.dup.partialShuffle(2, rnd);
- version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
+ version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
assert(arr == [1, 4, 3, 2, 5, 6]); // 1<->2, 2<->4
arr = arr.dup.partialShuffle(3, rnd);
- version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
+ version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
assert(arr == [5, 4, 6, 2, 1, 3]); // 1<->5, 2<->4, 3<->6
}
@@ -3428,7 +3428,7 @@ if (isRandomAccessRange!Range)
import std.range : iota;
auto rnd = MinstdRand0(42);
- version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
+ version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
assert(10.iota.randomCover(rnd).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5]));
}
diff --git a/libphobos/src/std/regex/package.d b/libphobos/src/std/regex/package.d
index 1562d79..d6a01e2 100644
--- a/libphobos/src/std/regex/package.d
+++ b/libphobos/src/std/regex/package.d
@@ -212,7 +212,7 @@ They met on 24/01/1970.
names work like aliases in addition to direct numbers.
)
$(REG_TITLE Assertions, Match position rather than character )
- $(REG_ROW ^, Matches at the begining of input or line (in multiline mode).)
+ $(REG_ROW ^, Matches at the beginning of input or line (in multiline mode).)
$(REG_ROW $, Matches at the end of input or line (in multiline mode). )
$(REG_ROW \b, Matches at word boundary. )
$(REG_ROW \B, Matches when $(U not) at word boundary. )
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index e83b6171..25cf9e0 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -225,7 +225,10 @@ public:
{
if (_p !is null)
{
- destroy(_p);
+ static if (is(T == class) || is(T == interface))
+ destroy(_p);
+ else
+ destroy(*_p);
_p = null;
}
}
@@ -259,7 +262,7 @@ private:
///
@safe unittest
{
- static struct S
+ struct S
{
int i;
this(int i){this.i = i;}
@@ -284,6 +287,7 @@ private:
Unique!S u1;
assert(u1.isEmpty);
u1 = produce();
+ assert(u1.i == 5);
increment(u1);
assert(u1.i == 6);
//consume(u1); // Error: u1 is not copyable
@@ -292,6 +296,24 @@ private:
assert(u1.isEmpty);
}
+@safe unittest
+{
+ int i;
+ struct S
+ {
+ ~this()
+ {
+ // check context pointer still exists - dtor also called before GC frees struct
+ if (this.tupleof[0])
+ i++;
+ }
+ }
+ {
+ Unique!S u = new S;
+ }
+ assert(i == 1);
+}
+
@system unittest
{
// test conversion to base ref
diff --git a/libphobos/testsuite/libphobos.exceptions/refcounted.d b/libphobos/testsuite/libphobos.exceptions/refcounted.d
index 2b7e79b..e4ed8e8 100644
--- a/libphobos/testsuite/libphobos.exceptions/refcounted.d
+++ b/libphobos/testsuite/libphobos.exceptions/refcounted.d
@@ -2,9 +2,9 @@
class E : Exception
{
static int instances;
- this(string msg = "")
+ this(string msg = "", Throwable nextInChain = null)
{
- super(msg);
+ super(msg, nextInChain);
instances++;
}
@@ -93,4 +93,34 @@ void main()
}
assert(E.instances == 0);
+
+ try
+ {
+ throw new E("first");
+ }
+ catch (E first)
+ {
+ assert(first.refcount == 2);
+ assert(E.instances == 1);
+
+ try
+ {
+ throw new E("second", first);
+ }
+ catch (E second)
+ {
+ assert(first.next is null);
+ assert(second.next is first);
+
+ assert(first.refcount == 3);
+ assert(second.refcount == 2);
+
+ assert(E.instances == 2);
+ }
+
+ assert(first.refcount == 2);
+ assert(E.instances == 1);
+ }
+
+ assert(E.instances == 0);
}
diff --git a/libphobos/testsuite/libphobos.gc/issue22843.d b/libphobos/testsuite/libphobos.gc/issue22843.d
new file mode 100644
index 0000000..bf6e830
--- /dev/null
+++ b/libphobos/testsuite/libphobos.gc/issue22843.d
@@ -0,0 +1,12 @@
+import core.memory;
+void main()
+{
+ auto collections = GC.profileStats().numCollections;
+ // loop until we trigger a collection
+ for (;;)
+ {
+ cast(void)GC.malloc(100_000, GC.BlkAttr.NO_SCAN);
+ if (GC.profileStats().numCollections == collections+1)
+ break;
+ }
+}
diff --git a/libphobos/testsuite/libphobos.shared/finalize.d b/libphobos/testsuite/libphobos.shared/finalize.d
index f31b818..fcec87b 100644
--- a/libphobos/testsuite/libphobos.shared/finalize.d
+++ b/libphobos/testsuite/libphobos.shared/finalize.d
@@ -7,9 +7,9 @@ import core.sys.posix.dlfcn;
void runTest()
{
Object obj;
- obj = Object.factory("lib.MyFinalizer");
+ obj = Object.factory("lib.MyFinalizer"); // { dg-warning "is deprecated" }
assert(obj.toString() == "lib.MyFinalizer");
- obj = Object.factory("lib.MyFinalizerBig");
+ obj = Object.factory("lib.MyFinalizerBig"); // { dg-warning "is deprecated" }
assert(obj.toString() == "lib.MyFinalizerBig");
}