@@ -519,31 +519,15 @@ static void eh_cleanup(void *exception)
519
519
objc_release (*(id*)exception );
520
520
}
521
521
522
- namespace __cxxabiv1
522
+ static void eh_cleanup_noop ( void * exception )
523
523
{
524
- struct __cxa_exception
525
- {
526
- // Manage the exception object itself.
527
- std::type_info *exceptionType;
528
- void (*exceptionDestructor)(void *);
529
- terminate_handler unexpectedHandler;
530
- terminate_handler terminateHandler;
531
- __cxa_exception *nextException;
532
- int handlerCount;
533
- int handlerSwitchValue;
534
- const unsigned char *actionRecord;
535
- const unsigned char *languageSpecificData;
536
- void *catchTemp;
537
- void *adjustedPtr;
538
- _Unwind_Exception unwindHeader;
539
- };
524
+ }
540
525
526
+ namespace __cxxabiv1
527
+ {
541
528
struct __cxa_refcounted_exception
542
529
{
543
- // Manage this header.
544
530
int referenceCount;
545
- // __cxa_exception must be last, and no padding can be after it.
546
- __cxa_exception exc;
547
531
};
548
532
}
549
533
@@ -553,13 +537,35 @@ extern "C"
553
537
OBJC_PUBLIC
554
538
void objc_exception_throw (id object)
555
539
{
540
+ // Don't bother with a mutex here. It doesn't matter if two threads set
541
+ // these values at the same time.
542
+ if (!done_setup)
543
+ {
544
+ DEBUG_LOG (" objc_exception_throw: Doing initial setup\n " );
545
+ MagicValueHolder *magicExc = (MagicValueHolder *)__cxa_allocate_exception (sizeof (MagicValueHolder));
546
+ MagicValueHolder x;
547
+ *magicExc = x;
548
+
549
+ __cxa_refcounted_exception *header =
550
+ __cxa_init_primary_exception (magicExc, & __objc_id_type_info, NULL );
551
+
552
+ type_info_offset = find_forwards (header, & __objc_id_type_info);
553
+ exception_struct_size = find_forwards (header, MagicValueHolder::magic);
554
+ __cxa_free_exception (magicExc);
555
+
556
+ DEBUG_LOG (" objc_exception_throw: type_info_offset: 0x%x\n " , unsigned (type_info_offset));
557
+ DEBUG_LOG (" objc_exception_throw: exception_struct_size: 0x%x\n " , unsigned (exception_struct_size));
558
+
559
+ done_setup = true ;
560
+ }
561
+
556
562
id *exc = (id *)__cxa_allocate_exception (sizeof (id));
557
563
*exc = object;
558
564
objc_retain (object);
559
565
DEBUG_LOG (" objc_exception_throw: Throwing 0x%x\n " , *exc);
560
566
561
567
#ifndef __GLIBCXX__
562
- // At the moment, only libstdc++ exposes __cxa_init_primary_exception
568
+ // At the moment, only libstdc++ exposes __cxa_init_primary_exception.
563
569
__cxa_throw (exc, & __objc_id_type_info, eh_cleanup);
564
570
#else
565
571
__cxa_eh_globals *globals = __cxa_get_globals ();
@@ -568,7 +574,8 @@ void objc_exception_throw(id object)
568
574
__cxa_init_primary_exception (exc, & __objc_id_type_info, eh_cleanup);
569
575
header->referenceCount = 1 ;
570
576
571
- _Unwind_Reason_Code err = _Unwind_RaiseException (&header->exc .unwindHeader );
577
+ _Unwind_Exception *unwindHeader = pointer_add<_Unwind_Exception>(header, exception_struct_size - sizeof (_Unwind_Exception));
578
+ _Unwind_Reason_Code err = _Unwind_RaiseException (unwindHeader);
572
579
573
580
DEBUG_LOG (" objc_exception_throw: _Unwind_RaiseException returned 0x%x for exception 0x%x\n " , err, *exc);
574
581
0 commit comments