@@ -7,6 +7,10 @@ typedef struct objc_object* id;
7
7
#include " visibility.h"
8
8
#include " objc/runtime.h"
9
9
#include " objc/objc-arc.h"
10
+ #ifdef __MINGW32__
11
+ #include " objc/objc-exception.h"
12
+ #include " objc/hooks.h"
13
+ #endif
10
14
11
15
#ifndef DEBUG_EXCEPTIONS
12
16
#define DEBUG_LOG (...)
@@ -515,14 +519,72 @@ static void eh_cleanup(void *exception)
515
519
objc_release (*(id*)exception );
516
520
}
517
521
522
+ namespace __cxxabiv1
523
+ {
524
+ struct __cxa_refcounted_exception
525
+ {
526
+ int referenceCount;
527
+ };
528
+ }
529
+
530
+ extern " C" __cxa_refcounted_exception* __cxa_init_primary_exception (void *obj, std::type_info *tinfo, void (*dest) (void *));
531
+
518
532
extern " C"
519
533
OBJC_PUBLIC
520
534
void objc_exception_throw (id object)
521
535
{
536
+ #ifdef __GLIBCXX__
537
+ // Don't bother with a mutex here. It doesn't matter if two threads set
538
+ // these values at the same time.
539
+ if (!done_setup)
540
+ {
541
+ DEBUG_LOG (" objc_exception_throw: Doing initial setup\n " );
542
+ MagicValueHolder *magicExc = (MagicValueHolder *)__cxa_allocate_exception (sizeof (MagicValueHolder));
543
+ MagicValueHolder x;
544
+ *magicExc = x;
545
+
546
+ __cxa_refcounted_exception *header =
547
+ __cxa_init_primary_exception (magicExc, & __objc_id_type_info, NULL );
548
+ exception_struct_size = find_forwards (header, MagicValueHolder::magic);
549
+ __cxa_free_exception (magicExc);
550
+
551
+ DEBUG_LOG (" objc_exception_throw: exception_struct_size: 0x%x\n " , unsigned (exception_struct_size));
552
+
553
+ done_setup = true ;
554
+ }
555
+ #endif
556
+
522
557
id *exc = (id *)__cxa_allocate_exception (sizeof (id));
523
558
*exc = object;
524
559
objc_retain (object);
525
560
DEBUG_LOG (" objc_exception_throw: Throwing 0x%x\n " , *exc);
561
+
562
+ #ifndef __GLIBCXX__
563
+ // At the moment, only libstdc++ exposes __cxa_init_primary_exception.
526
564
__cxa_throw (exc, & __objc_id_type_info, eh_cleanup);
565
+ #else
566
+ __cxa_eh_globals *globals = __cxa_get_globals ();
567
+ globals->uncaughtExceptions += 1 ;
568
+ __cxa_refcounted_exception *header =
569
+ __cxa_init_primary_exception (exc, & __objc_id_type_info, eh_cleanup);
570
+ header->referenceCount = 1 ;
571
+
572
+ _Unwind_Exception *unwindHeader = pointer_add<_Unwind_Exception>(header, exception_struct_size - sizeof (_Unwind_Exception));
573
+ _Unwind_Reason_Code err = _Unwind_RaiseException (unwindHeader);
574
+
575
+ if (_URC_END_OF_STACK == err && 0 != _objc_unexpected_exception)
576
+ {
577
+ DEBUG_LOG (" Invoking _objc_unexpected_exception\n " );
578
+ _objc_unexpected_exception (object);
579
+ }
580
+ DEBUG_LOG (" Throw returned %d\n " ,(int ) err);
581
+ abort ();
582
+ #endif
527
583
}
584
+
585
+ OBJC_PUBLIC extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler (objc_uncaught_exception_handler handler)
586
+ {
587
+ return __atomic_exchange_n (&_objc_unexpected_exception, handler, __ATOMIC_SEQ_CST);
588
+ }
589
+
528
590
#endif
0 commit comments