@@ -519,32 +519,16 @@ 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
- {
543
- // Manage this header.
544
- int referenceCount;
545
- // __cxa_exception must be last, and no padding can be after it.
546
- __cxa_exception exc;
547
- };
529
+ {
530
+ int referenceCount;
531
+ };
548
532
}
549
533
550
534
extern " C" __cxa_refcounted_exception* __cxa_init_primary_exception (void *obj, std::type_info *tinfo, void (*dest) (void *));
@@ -553,32 +537,55 @@ extern "C"
553
537
OBJC_PUBLIC
554
538
void objc_exception_throw (id object)
555
539
{
556
- id *exc = (id *)__cxa_allocate_exception (sizeof (id));
557
- *exc = object;
558
- objc_retain (object);
559
- DEBUG_LOG (" objc_exception_throw: Throwing 0x%x\n " , *exc);
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
+
562
+ id *exc = (id *)__cxa_allocate_exception (sizeof (id));
563
+ *exc = object;
564
+ objc_retain (object);
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
- __cxa_eh_globals *globals = __cxa_get_globals ();
566
- globals->uncaughtExceptions += 1 ;
567
- __cxa_refcounted_exception *header =
568
- __cxa_init_primary_exception (exc, & __objc_id_type_info, eh_cleanup);
569
- header->referenceCount = 1 ;
570
-
571
- _Unwind_Reason_Code err = _Unwind_RaiseException (&header->exc .unwindHeader );
572
-
573
- DEBUG_LOG (" objc_exception_throw: _Unwind_RaiseException returned 0x%x for exception 0x%x\n " , err, *exc);
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 ();
571
+ __cxa_eh_globals *globals = __cxa_get_globals ();
572
+ globals->uncaughtExceptions += 1 ;
573
+ __cxa_refcounted_exception *header =
574
+ __cxa_init_primary_exception (exc, & __objc_id_type_info, eh_cleanup);
575
+ header->referenceCount = 1 ;
576
+
577
+ _Unwind_Exception *unwindHeader = pointer_add<_Unwind_Exception>(header, exception_struct_size - sizeof (_Unwind_Exception));
578
+ _Unwind_Reason_Code err = _Unwind_RaiseException (unwindHeader);
579
+
580
+ DEBUG_LOG (" objc_exception_throw: _Unwind_RaiseException returned 0x%x for exception 0x%x\n " , err, *exc);
581
+
582
+ if (_URC_END_OF_STACK == err && 0 != _objc_unexpected_exception)
583
+ {
584
+ DEBUG_LOG (" Invoking _objc_unexpected_exception\n " );
585
+ _objc_unexpected_exception (object);
586
+ }
587
+ DEBUG_LOG (" Throw returned %d\n " ,(int ) err);
588
+ abort ();
582
589
#endif
583
590
}
584
591
0 commit comments