ObjFW  Check-in [13c2017326]

Overview
Comment:runtime: Add support for emergency exceptions
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 13c2017326f6ad0dd91cbad8b123feaef6b5a1c6dbded98c99cb2a91eab36da9
User & Date: js on 2017-04-14 02:16:35
Other Links: manifest | tags
Context
2017-04-14
02:28
OFSandbox: Revert using a bitfield check-in: 02ccf37477 user: js tags: trunk
02:16
runtime: Add support for emergency exceptions check-in: 13c2017326 user: js tags: trunk
2017-04-13
13:30
-[OFObject release]: Add memory barriers check-in: 05e2b4b851 user: js tags: trunk
Changes

Modified src/runtime/exception.m from [ae672d1e54] to [80255e6a7d].

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29



30
31
32
33
34
35
36
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"


#include <stdlib.h>
#include <string.h>

#ifdef HAVE_SEH_EXCEPTIONS
# include <windows.h>
#endif

#import "runtime.h"
#import "runtime-private.h"

#import "macros.h"




#if defined(HAVE_DWARF_EXCEPTIONS)
# define PERSONALITY __gnu_objc_personality_v0
# define CXX_PERSONALITY_STR "__gxx_personality_v0"
#elif defined(HAVE_SJLJ_EXCEPTIONS)
# define PERSONALITY __gnu_objc_personality_sj0
# define CXX_PERSONALITY_STR "__gxx_personality_sj0"







>











>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_SEH_EXCEPTIONS
# include <windows.h>
#endif

#import "runtime.h"
#import "runtime-private.h"

#import "macros.h"
#ifdef OF_HAVE_THREADS
# include "threading.h"
#endif

#if defined(HAVE_DWARF_EXCEPTIONS)
# define PERSONALITY __gnu_objc_personality_v0
# define CXX_PERSONALITY_STR "__gxx_personality_v0"
#elif defined(HAVE_SJLJ_EXCEPTIONS)
# define PERSONALITY __gnu_objc_personality_sj0
# define CXX_PERSONALITY_STR "__gxx_personality_sj0"
59
60
61
62
63
64
65


66
67
68
69
70
71
72
	    struct _Unwind_Context *ctx)
# define CALL_PERSONALITY(func) func(state, ex, ctx)
#endif

#define GNUCOBJC_EXCEPTION_CLASS UINT64_C(0x474E55434F424A43) /* GNUCOBJC */
#define GNUCCXX0_EXCEPTION_CLASS UINT64_C(0x474E5543432B2B00) /* GNUCC++\0 */
#define CLNGCXX0_EXCEPTION_CLASS UINT64_C(0x434C4E47432B2B00) /* CLNGC++\0 */



#define _UA_SEARCH_PHASE  0x01
#define _UA_CLEANUP_PHASE 0x02
#define _UA_HANDLER_FRAME 0x04
#define _UA_FORCE_UNWIND  0x08

#define DW_EH_PE_absptr	  0x00







>
>







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
	    struct _Unwind_Context *ctx)
# define CALL_PERSONALITY(func) func(state, ex, ctx)
#endif

#define GNUCOBJC_EXCEPTION_CLASS UINT64_C(0x474E55434F424A43) /* GNUCOBJC */
#define GNUCCXX0_EXCEPTION_CLASS UINT64_C(0x474E5543432B2B00) /* GNUCC++\0 */
#define CLNGCXX0_EXCEPTION_CLASS UINT64_C(0x434C4E47432B2B00) /* CLNGC++\0 */

#define NUM_EMERGENCY_EXCEPTIONS 4

#define _UA_SEARCH_PHASE  0x01
#define _UA_CLEANUP_PHASE 0x02
#define _UA_HANDLER_FRAME 0x04
#define _UA_FORCE_UNWIND  0x08

#define DW_EH_PE_absptr	  0x00
221
222
223
224
225
226
227










228
229
230
231
232
233
234
#ifdef HAVE_SEH_EXCEPTIONS
extern EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void*,
    PCONTEXT, PDISPATCHER_CONTEXT, _Unwind_Reason_Code(*)(int, int, uint64_t,
    struct _Unwind_Exception*, struct _Unwind_Context*));
#endif

static objc_uncaught_exception_handler uncaught_exception_handler;











static uint64_t
read_uleb128(const uint8_t **ptr)
{
	uint64_t value = 0;
	uint8_t shift = 0;








>
>
>
>
>
>
>
>
>
>







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#ifdef HAVE_SEH_EXCEPTIONS
extern EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void*,
    PCONTEXT, PDISPATCHER_CONTEXT, _Unwind_Reason_Code(*)(int, int, uint64_t,
    struct _Unwind_Exception*, struct _Unwind_Context*));
#endif

static objc_uncaught_exception_handler uncaught_exception_handler;
static struct objc_exception emergency_exceptions[NUM_EMERGENCY_EXCEPTIONS];
#ifdef OF_HAVE_THREADS
static of_spinlock_t emergency_exceptions_spinlock;

OF_CONSTRUCTOR()
{
	if (!of_spinlock_new(&emergency_exceptions_spinlock))
		OBJC_ERROR("Cannot create spinlock!")
}
#endif

static uint64_t
read_uleb128(const uint8_t **ptr)
{
	uint64_t value = 0;
	uint8_t shift = 0;

660
661
662
663
664
665
666
667
















668
669
670
671

672





673

















674
675
676
677
678
679
680
681
682
683
684
685
}

static void
cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception *ex)
{
	free(ex);
}

















void
objc_exception_throw(id object)
{
	struct objc_exception *e;







	if ((e = malloc(sizeof(*e))) == NULL)

















		OBJC_ERROR("Not enough memory to allocate exception!")

	memset(e, 0, sizeof(*e));
	e->exception.class = GNUCOBJC_EXCEPTION_CLASS;
	e->exception.cleanup = cleanup;
	e->object = object;

	if (_Unwind_RaiseException(&e->exception) == _URC_END_OF_STACK &&
	    uncaught_exception_handler != NULL)
		uncaught_exception_handler(object);

	OBJC_ERROR("_Unwind_RaiseException() returned!")








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
>

>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|







676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
}

static void
cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception *ex)
{
	free(ex);
}

static void
cleanup_emergency(_Unwind_Reason_Code reason, struct _Unwind_Exception *ex)
{
#ifdef OF_HAVE_THREADS
	if (!of_spinlock_lock(&emergency_exceptions_spinlock))
		OBJC_ERROR("Cannot lock spinlock!");
#endif

	ex->class = 0;

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_unlock(&emergency_exceptions_spinlock))
		OBJC_ERROR("Cannot unlock spinlock!");
#endif
}

void
objc_exception_throw(id object)
{
	struct objc_exception *e = malloc(sizeof(*e));
	bool emergency = false;

	if (e == NULL) {
#ifdef OF_HAVE_THREADS
		if (!of_spinlock_lock(&emergency_exceptions_spinlock))
			OBJC_ERROR("Cannot lock spinlock!");
#endif

		for (uint_fast8_t i = 0; i < NUM_EMERGENCY_EXCEPTIONS; i++) {
			if (emergency_exceptions[i].exception.class == 0) {
				e = &emergency_exceptions[i];
				e->exception.class = GNUCOBJC_EXCEPTION_CLASS;
				emergency = true;

				break;
			}
		}

#ifdef OF_HAVE_THREADS
		if (!of_spinlock_unlock(&emergency_exceptions_spinlock))
			OBJC_ERROR("Cannot lock spinlock!");
#endif
	}

	if (e == NULL)
		OBJC_ERROR("Not enough memory to allocate exception!")

	memset(e, 0, sizeof(*e));
	e->exception.class = GNUCOBJC_EXCEPTION_CLASS;
	e->exception.cleanup = (emergency ? cleanup_emergency : cleanup);
	e->object = object;

	if (_Unwind_RaiseException(&e->exception) == _URC_END_OF_STACK &&
	    uncaught_exception_handler != NULL)
		uncaught_exception_handler(object);

	OBJC_ERROR("_Unwind_RaiseException() returned!")