@@ -2571,27 +2571,8 @@ class Throwable : Object
25712571 * $(D Throwable) is thrown from inside a $(D catch) block. The originally
25722572 * caught $(D Exception) will be chained to the new $(D Throwable) via this
25732573 * field.
2574- *
2575- * If the 0 bit is set in this, it means the next exception is refcounted,
2576- * meaning this object owns that object and should destroy it on
2577- * destruction.
2578- *
2579- * WARNING: This means we are storing an interior pointer to the next in
2580- * chain, to signify that the next in the chain is actually reference
2581- * counted. We rely on the fact that a pointer to a Throwable is not 1-byte
2582- * aligned. It is important to use a local field to indicate reference
2583- * counting since we are not allowed to look at GC-allocated references
2584- * inside the destructor. It is very important to store this as a void*,
2585- * since optimizers can consider an unaligned pointer to not exist.
25862574 */
2587- private void * _nextInChainPtr;
2588-
2589- private @property bool _nextIsRefcounted() @trusted scope pure nothrow @nogc const
2590- {
2591- if (__ctfe)
2592- return false ;
2593- return (cast (size_t )_nextInChainPtr) & 1 ;
2594- }
2575+ private Throwable nextInChain;
25952576
25962577 private uint _refcount; // 0 : allocated by GC
25972578 // 1 : allocated by _d_newThrowable()
@@ -2604,36 +2585,24 @@ class Throwable : Object
26042585 * caught $(D Exception) will be chained to the new $(D Throwable) via this
26052586 * field.
26062587 */
2607- @property inout (Throwable) next() @trusted inout return scope pure nothrow @nogc
2608- {
2609- if (__ctfe)
2610- return cast (inout (Throwable)) _nextInChainPtr;
2611-
2612- return cast (inout (Throwable)) (_nextInChainPtr - _nextIsRefcounted);
2613- }
2614-
2588+ @property inout (Throwable) next() @safe inout return scope pure nothrow @nogc { return nextInChain; }
26152589
26162590 /**
26172591 * Replace next in chain with `tail`.
26182592 * Use `chainTogether` instead if at all possible.
26192593 */
2620- @property void next(Throwable tail) @trusted scope pure nothrow @nogc
2594+ @property void next(Throwable tail) @safe scope pure nothrow @nogc
26212595 {
2622- void * newTail = cast (void * )tail;
26232596 if (tail && tail._refcount)
2624- {
26252597 ++ tail._refcount; // increment the replacement *first*
2626- ++ newTail; // indicate ref counting is used
2627- }
26282598
2629- auto n = next;
2630- auto nrc = _nextIsRefcounted;
2631- _nextInChainPtr = null ; // sever the tail before deleting it
2599+ auto n = nextInChain;
2600+ nextInChain = null ; // sever the tail before deleting it
26322601
2633- if (nrc )
2602+ if (n && n._refcount )
26342603 _d_delThrowable(n); // now delete the old tail
26352604
2636- _nextInChainPtr = newTail; // and set the new tail
2605+ nextInChain = tail; // and set the new tail
26372606 }
26382607
26392608 /**
@@ -2652,7 +2621,7 @@ class Throwable : Object
26522621 int opApply (scope int delegate (Throwable) dg)
26532622 {
26542623 int result = 0 ;
2655- for (Throwable t = this ; t; t = t.next )
2624+ for (Throwable t = this ; t; t = t.nextInChain )
26562625 {
26572626 result = dg(t);
26582627 if (result)
@@ -2675,12 +2644,14 @@ class Throwable : Object
26752644 return e2;
26762645 if (! e2)
26772646 return e1;
2647+ if (e2.refcount())
2648+ ++ e2.refcount();
26782649
2679- for (auto e = e1; 1 ; e = e.next )
2650+ for (auto e = e1; 1 ; e = e.nextInChain )
26802651 {
2681- if (! e.next )
2652+ if (! e.nextInChain )
26822653 {
2683- e.next = e2;
2654+ e.nextInChain = e2;
26842655 break ;
26852656 }
26862657 }
@@ -2690,7 +2661,9 @@ class Throwable : Object
26902661 @nogc @safe pure nothrow this (string msg, Throwable nextInChain = null )
26912662 {
26922663 this .msg = msg;
2693- this .next = nextInChain;
2664+ this .nextInChain = nextInChain;
2665+ if (nextInChain && nextInChain._refcount)
2666+ ++ nextInChain._refcount;
26942667 // this.info = _d_traceContext();
26952668 }
26962669
@@ -2704,9 +2677,8 @@ class Throwable : Object
27042677
27052678 @trusted nothrow ~this ()
27062679 {
2707- if (_nextIsRefcounted)
2708- _d_delThrowable(next);
2709-
2680+ if (nextInChain && nextInChain._refcount)
2681+ _d_delThrowable(nextInChain);
27102682 // handle owned traceinfo
27112683 if (infoDeallocator ! is null )
27122684 {
@@ -2835,23 +2807,23 @@ class Exception : Throwable
28352807 auto e = new Exception (" msg" );
28362808 assert (e.file == __FILE__ );
28372809 assert (e.line == __LINE__ - 2 );
2838- assert (e._nextInChainPtr is null );
2810+ assert (e.nextInChain is null );
28392811 assert (e.msg == " msg" );
28402812 }
28412813
28422814 {
28432815 auto e = new Exception (" msg" , new Exception (" It's an Exception!" ), " hello" , 42 );
28442816 assert (e.file == " hello" );
28452817 assert (e.line == 42 );
2846- assert (e._nextInChainPtr ! is null );
2818+ assert (e.nextInChain ! is null );
28472819 assert (e.msg == " msg" );
28482820 }
28492821
28502822 {
28512823 auto e = new Exception (" msg" , " hello" , 42 , new Exception (" It's an Exception!" ));
28522824 assert (e.file == " hello" );
28532825 assert (e.line == 42 );
2854- assert (e._nextInChainPtr ! is null );
2826+ assert (e.nextInChain ! is null );
28552827 assert (e.msg == " msg" );
28562828 }
28572829
@@ -2918,7 +2890,7 @@ class Error : Throwable
29182890 auto e = new Error(" msg" );
29192891 assert (e.file is null );
29202892 assert (e.line == 0 );
2921- assert (e._nextInChainPtr is null );
2893+ assert (e.nextInChain is null );
29222894 assert (e.msg == " msg" );
29232895 assert (e.bypassedException is null );
29242896 }
@@ -2927,7 +2899,7 @@ class Error : Throwable
29272899 auto e = new Error(" msg" , new Exception (" It's an Exception!" ));
29282900 assert (e.file is null );
29292901 assert (e.line == 0 );
2930- assert (e._nextInChainPtr ! is null );
2902+ assert (e.nextInChain ! is null );
29312903 assert (e.msg == " msg" );
29322904 assert (e.bypassedException is null );
29332905 }
@@ -2936,7 +2908,7 @@ class Error : Throwable
29362908 auto e = new Error(" msg" , " hello" , 42 , new Exception (" It's an Exception!" ));
29372909 assert (e.file == " hello" );
29382910 assert (e.line == 42 );
2939- assert (e._nextInChainPtr ! is null );
2911+ assert (e.nextInChain ! is null );
29402912 assert (e.msg == " msg" );
29412913 assert (e.bypassedException is null );
29422914 }
0 commit comments