Skip to content

Commit c953563

Browse files
committed
Define emscripten exception struct in native code
This is really step 1 of moving more of this code to be native.
1 parent 53b26b8 commit c953563

File tree

5 files changed

+51
-36
lines changed

5 files changed

+51
-36
lines changed

src/library_exceptions.js

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,6 @@ var LibraryExceptions = {
99
$exceptionLast: '0',
1010
$exceptionCaught: ' []',
1111

12-
// Static fields for ExceptionInfo class.
13-
$ExceptionInfoAttrs: {
14-
// ExceptionInfo native structure layout.
15-
DESTRUCTOR_OFFSET: 0,
16-
REFCOUNT_OFFSET: Runtime.POINTER_SIZE,
17-
TYPE_OFFSET: Runtime.POINTER_SIZE + 4,
18-
CAUGHT_OFFSET: Runtime.POINTER_SIZE + 8,
19-
RETHROWN_OFFSET: Runtime.POINTER_SIZE + 9,
20-
21-
// Total structure size with padding, should be multiple of allocation alignment.
22-
SIZE: alignMemory(Runtime.POINTER_SIZE + 10)
23-
},
24-
25-
$ExceptionInfo__deps: ['$ExceptionInfoAttrs'],
2612
// This class is the exception metadata which is prepended to each thrown object (in WASM memory).
2713
// It is allocated in one block among with a thrown object in __cxa_allocate_exception and freed
2814
// in ___cxa_free_exception. It roughly corresponds to __cxa_exception structure in libcxxabi. The
@@ -37,44 +23,44 @@ var LibraryExceptions = {
3723
// excPtr - Thrown object pointer to wrap. Metadata pointer is calculated from it.
3824
$ExceptionInfo: function(excPtr) {
3925
this.excPtr = excPtr;
40-
this.ptr = excPtr - ExceptionInfoAttrs.SIZE;
26+
this.ptr = excPtr - {{{ C_STRUCTS.__cxa_exception.__size__ }}};
4127

4228
this.set_type = function(type) {
43-
{{{ makeSetValue('this.ptr', 'ExceptionInfoAttrs.TYPE_OFFSET', 'type', '*') }}};
29+
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.exceptionType, 'type', '*') }}};
4430
};
4531

4632
this.get_type = function() {
47-
return {{{ makeGetValue('this.ptr', 'ExceptionInfoAttrs.TYPE_OFFSET', '*') }}};
33+
return {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.exceptionType, '*') }}};
4834
};
4935

5036
this.set_destructor = function(destructor) {
51-
{{{ makeSetValue('this.ptr', 'ExceptionInfoAttrs.DESTRUCTOR_OFFSET', 'destructor', '*') }}};
37+
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.exceptionDestructor, 'destructor', '*') }}};
5238
};
5339

5440
this.get_destructor = function() {
55-
return {{{ makeGetValue('this.ptr', 'ExceptionInfoAttrs.DESTRUCTOR_OFFSET', '*') }}};
41+
return {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.exceptionDestructor, '*') }}};
5642
};
5743

5844
this.set_refcount = function(refcount) {
59-
{{{ makeSetValue('this.ptr', 'ExceptionInfoAttrs.REFCOUNT_OFFSET', 'refcount', 'i32') }}};
45+
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'refcount', 'i32') }}};
6046
};
6147

6248
this.set_caught = function (caught) {
6349
caught = caught ? 1 : 0;
64-
{{{ makeSetValue('this.ptr', 'ExceptionInfoAttrs.CAUGHT_OFFSET', 'caught', 'i8') }}};
50+
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.caught, 'caught', 'i8') }}};
6551
};
6652

6753
this.get_caught = function () {
68-
return {{{ makeGetValue('this.ptr', 'ExceptionInfoAttrs.CAUGHT_OFFSET', 'i8') }}} != 0;
54+
return {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.caught, 'i8') }}} != 0;
6955
};
7056

7157
this.set_rethrown = function (rethrown) {
7258
rethrown = rethrown ? 1 : 0;
73-
{{{ makeSetValue('this.ptr', 'ExceptionInfoAttrs.RETHROWN_OFFSET', 'rethrown', 'i8') }}};
59+
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.rethrown, 'rethrown', 'i8') }}};
7460
};
7561

7662
this.get_rethrown = function () {
77-
return {{{ makeGetValue('this.ptr', 'ExceptionInfoAttrs.RETHROWN_OFFSET', 'i8') }}} != 0;
63+
return {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.rethrown, 'i8') }}} != 0;
7864
};
7965

8066
// Initialize native structure fields. Should be called once after allocated.
@@ -88,20 +74,20 @@ var LibraryExceptions = {
8874

8975
this.add_ref = function() {
9076
#if USE_PTHREADS
91-
Atomics.add(HEAP32, (this.ptr + ExceptionInfoAttrs.REFCOUNT_OFFSET) >> 2, 1);
77+
Atomics.add(HEAP32, (this.ptr + {{{ C_STRUCTS.__cxa_exception.referenceCount }}}) >> 2, 1);
9278
#else
93-
var value = {{{ makeGetValue('this.ptr', 'ExceptionInfoAttrs.REFCOUNT_OFFSET', 'i32') }}};
94-
{{{ makeSetValue('this.ptr', 'ExceptionInfoAttrs.REFCOUNT_OFFSET', 'value + 1', 'i32') }}};
79+
var value = {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'i32') }}};
80+
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'value + 1', 'i32') }}};
9581
#endif
9682
};
9783

9884
// Returns true if last reference released.
9985
this.release_ref = function() {
10086
#if USE_PTHREADS
101-
var prev = Atomics.sub(HEAP32, (this.ptr + ExceptionInfoAttrs.REFCOUNT_OFFSET) >> 2, 1);
87+
var prev = Atomics.sub(HEAP32, (this.ptr + C_STRUCTS.__cxa_exception.referenceCount) >> 2, 1);
10288
#else
103-
var prev = {{{ makeGetValue('this.ptr', 'ExceptionInfoAttrs.REFCOUNT_OFFSET', 'i32') }}};
104-
{{{ makeSetValue('this.ptr', 'ExceptionInfoAttrs.REFCOUNT_OFFSET', 'prev - 1', 'i32') }}};
89+
var prev = {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'i32') }}};
90+
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'prev - 1', 'i32') }}};
10591
#endif
10692
#if ASSERTIONS
10793
assert(prev > 0);
@@ -205,11 +191,10 @@ var LibraryExceptions = {
205191
},
206192

207193
// Exceptions
208-
__cxa_allocate_exception__deps: ['$ExceptionInfoAttrs'],
209194
__cxa_allocate_exception__sig: 'vi',
210195
__cxa_allocate_exception: function(size) {
211196
// Thrown object is prepended by exception metadata block
212-
return _malloc(size + ExceptionInfoAttrs.SIZE) + ExceptionInfoAttrs.SIZE;
197+
return _malloc(size + {{{ C_STRUCTS.__cxa_exception.__size__ }}}) + {{{ C_STRUCTS.__cxa_exception.__size__ }}};
213198
},
214199

215200
__cxa_free_exception__deps: ['$ExceptionInfo'],

src/struct_info_internal.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,17 @@
4040
"global_locale"
4141
]
4242
}
43+
},
44+
{
45+
"file": "cxa_exception.h",
46+
"structs": {
47+
"__cxxabiv1::__cxa_exception": [
48+
"exceptionDestructor",
49+
"referenceCount",
50+
"exceptionType",
51+
"caught",
52+
"rethrown"
53+
]
54+
}
4355
}
4456
]

system/lib/libc/musl/arch/emscripten/atomic_arch.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ static inline void a_or_l(volatile void *p, long v)
3636
#define a_cas_p a_cas_p
3737
static inline void *a_cas_p(volatile void *p, void *t, void *s)
3838
{
39-
void* expected = t;
40-
__c11_atomic_compare_exchange_strong((_Atomic uintptr_t*)p, &expected, s, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
41-
return expected;
39+
uintptr_t expected = (uintptr_t)t;
40+
__c11_atomic_compare_exchange_strong((_Atomic uintptr_t*)p, &expected, (uintptr_t)s, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
41+
return (void*)expected;
4242
}
4343

4444
#define a_cas_l a_cas_l

system/lib/libcxxabi/src/cxa_exception.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@
1919

2020
namespace __cxxabiv1 {
2121

22+
#ifdef __USING_EMSCRIPTEN_EXCEPTIONS__
23+
24+
struct _LIBCXXABI_HIDDEN __cxa_exception {
25+
void* exceptionDestructor;
26+
size_t referenceCount;
27+
void* exceptionType;
28+
uint8_t caught;
29+
uint8_t rethrown;
30+
};
31+
32+
#else
33+
2234
static const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC++\0
2335
static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
2436
static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++
@@ -164,6 +176,8 @@ extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals_fast ();
164176
extern "C" _LIBCXXABI_FUNC_VIS void * __cxa_allocate_dependent_exception ();
165177
extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * dependent_exception);
166178

179+
#endif // !__USING_EMSCRIPTEN_EXCEPTIONS__
180+
167181
} // namespace __cxxabiv1
168182

169183
#endif // _CXA_EXCEPTION_H

tools/gen_struct_info.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ def parse_c_output(lines):
141141

142142
for line in lines:
143143
arg = line[1:].strip()
144+
if '::' in arg:
145+
arg = arg.split('::', 1)[1]
144146
if line[0] == 'K':
145147
# This is a key
146148
key = arg
@@ -252,7 +254,7 @@ def inspect_headers(headers, cflags):
252254
show('Compiling generated code...')
253255

254256
# -Oz optimizes enough to avoid warnings on code size/num locals
255-
cmd = [shared.EMCC] + cflags + ['-o', js_file[1], src_file[1],
257+
cmd = [shared.EMXX] + cflags + ['-o', js_file[1], src_file[1],
256258
'-O0',
257259
'-Werror',
258260
'-Wno-format',
@@ -408,6 +410,8 @@ def main(args):
408410

409411
internal_cflags = [
410412
'-I' + shared.path_from_root('system', 'lib', 'libc', 'musl', 'src', 'internal'),
413+
'-I' + shared.path_from_root('system', 'lib', 'libcxxabi', 'src'),
414+
'-D__USING_EMSCRIPTEN_EXCEPTIONS__',
411415
]
412416

413417
# Look for structs in all passed headers.

0 commit comments

Comments
 (0)