aboutsummaryrefslogtreecommitdiff
path: root/libphobos/libdruntime
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/libdruntime
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/libdruntime')
-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
16 files changed, 199 insertions, 60 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,