Skip to content

Commit d09d8ca

Browse files
committed
fibers: implement switching exception information, fix invalid exception chain
1 parent c91d50a commit d09d8ca

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

src/core/thread.d

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3905,6 +3905,10 @@ version( LDC )
39053905
version( X86 ) version = CheckFiberMigration;
39063906
version( X86_64 ) version = CheckFiberMigration;
39073907
}
3908+
else version( Windows )
3909+
{
3910+
version( X86 ) version = CheckFiberMigration;
3911+
}
39083912
}
39093913

39103914
// Fiber support for SjLj style exceptions

src/ldc/eh/common.d

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ extern(C) void fatalerror(in char* format, ...)
3636
abort();
3737
}
3838

39+
version(Win32) {} else version = notMSVC;
40+
version(notMSVC):
41+
3942
// ------------------------
4043
// Reading DWARF data
4144
// ------------------------

src/ldc/eh/win32.d

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,14 @@ nothrow:
278278

279279
@property size_t length() const { return _length; }
280280
@property bool empty() const { return !length; }
281-
281+
282+
void swap(ref ExceptionStack other)
283+
{
284+
auto olength = other._length; other._length = _length; _length = olength;
285+
auto op = other._p; other._p = _p; _p = op;
286+
auto ocap = other._cap; other._cap = _cap; _cap = ocap;
287+
}
288+
282289
private:
283290
void grow()
284291
{
@@ -458,7 +465,66 @@ int doRtlUnwind(void* pFrame, ExceptionRecord* eRecord, typeof(RtlUnwind)* handl
458465
ret;
459466
}
460467
}
468+
469+
///////////////////////////////////////////////////////////////
470+
struct FiberContext
471+
{
472+
ExceptionStack exceptionStack;
473+
void* currentException;
474+
void* currentExceptionContext;
475+
int processingContext;
476+
}
477+
478+
FiberContext* fiberContext;
479+
480+
extern(C) void** __current_exception() nothrow;
481+
extern(C) void** __current_exception_context() nothrow;
482+
extern(C) int* __processing_throw() nothrow;
483+
484+
extern(C) void* _d_eh_swapContext(FiberContext* newContext) nothrow
485+
{
486+
import rt.util.container.common : xmalloc;
487+
import core.stdc.string : memset;
488+
if (!fiberContext)
489+
{
490+
fiberContext = cast(FiberContext*) xmalloc(FiberContext.sizeof);
491+
memset(fiberContext, 0, FiberContext.sizeof);
492+
}
493+
fiberContext.exceptionStack.swap(exceptionStack);
494+
fiberContext.currentException = *__current_exception();
495+
fiberContext.currentExceptionContext = *__current_exception_context();
496+
fiberContext.processingContext = *__processing_throw();
497+
498+
if (newContext)
499+
{
500+
exceptionStack.swap(newContext.exceptionStack);
501+
*__current_exception() = newContext.currentException;
502+
*__current_exception_context() = newContext.currentExceptionContext;
503+
*__processing_throw() = newContext.processingContext;
504+
}
505+
else
506+
{
507+
exceptionStack = ExceptionStack();
508+
*__current_exception() = null;
509+
*__current_exception_context() = null;
510+
*__processing_throw() = 0;
511+
}
512+
513+
FiberContext* old = fiberContext;
514+
fiberContext = newContext;
515+
return old;
516+
}
461517

518+
static ~this()
519+
{
520+
import core.stdc.stdlib : free;
521+
if (fiberContext)
522+
{
523+
destroy(*fiberContext);
524+
free(fiberContext);
525+
}
526+
}
527+
462528
///////////////////////////////////////////////////////////////
463529
void msvc_eh_init()
464530
{

0 commit comments

Comments
 (0)