Skip to content

Commit df3a308

Browse files
sbc100RReverser
andauthored
Move parts of emscripten exception handling to native code. NFC (#16627)
Co-authored-by: Ingvar Stepanyan <[email protected]>
1 parent 90958d9 commit df3a308

25 files changed

+278
-226
lines changed

emcc.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2785,6 +2785,13 @@ def check_memory_setting(setting):
27852785
'__cxa_is_pointer_type',
27862786
'__cxa_can_catch',
27872787

2788+
# __cxa_begin_catch depends on this but we can't use deps info in this
2789+
# case because that only works for user-level code, and __cxa_begin_catch
2790+
# can be used by the standard library.
2791+
'__cxa_increment_exception_refcount',
2792+
# Same for __cxa_end_catch
2793+
'__cxa_decrement_exception_refcount',
2794+
27882795
# Emscripten exception handling can generate invoke calls, and they call
27892796
# setThrew(). We cannot handle this using deps_info as the invokes are not
27902797
# emitted because of library function usage, but by codegen itself.

src/library_exceptions.js

Lines changed: 11 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@ var LibraryExceptions = {
2323
//
2424
// excPtr - Thrown object pointer to wrap. Metadata pointer is calculated from it.
2525
$ExceptionInfo__docs: '/** @constructor */',
26-
$ExceptionInfo__deps: ['__cxa_is_pointer_type',
2726
#if EXCEPTION_DEBUG
28-
'$ptrToString',
27+
$ExceptionInfo__deps: ['$ptrToString'],
2928
#endif
30-
],
3129
$ExceptionInfo: function(excPtr) {
3230
this.excPtr = excPtr;
3331
this.ptr = excPtr - {{{ C_STRUCTS.__cxa_exception.__size__ }}};
@@ -48,10 +46,6 @@ var LibraryExceptions = {
4846
return {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.exceptionDestructor, '*') }}};
4947
};
5048

51-
this.set_refcount = function(refcount) {
52-
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'refcount', 'i32') }}};
53-
};
54-
5549
this.set_caught = function (caught) {
5650
caught = caught ? 1 : 0;
5751
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.caught, 'caught', 'i8') }}};
@@ -78,34 +72,8 @@ var LibraryExceptions = {
7872
this.set_adjusted_ptr(0);
7973
this.set_type(type);
8074
this.set_destructor(destructor);
81-
this.set_refcount(0);
82-
this.set_caught(false);
83-
this.set_rethrown(false);
8475
}
8576

86-
this.add_ref = function() {
87-
#if SHARED_MEMORY
88-
Atomics.add(HEAP32, (this.ptr + {{{ C_STRUCTS.__cxa_exception.referenceCount }}}) >> 2, 1);
89-
#else
90-
var value = {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'i32') }}};
91-
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'value + 1', 'i32') }}};
92-
#endif
93-
};
94-
95-
// Returns true if last reference released.
96-
this.release_ref = function() {
97-
#if SHARED_MEMORY
98-
var prev = Atomics.sub(HEAP32, (this.ptr + {{{ C_STRUCTS.__cxa_exception.referenceCount }}}) >> 2, 1);
99-
#else
100-
var prev = {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'i32') }}};
101-
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'prev - 1', 'i32') }}};
102-
#endif
103-
#if ASSERTIONS
104-
assert(prev > 0);
105-
#endif
106-
return prev === 1;
107-
};
108-
10977
this.set_adjusted_ptr = function(adjustedPtr) {
11078
{{{ makeSetValue('this.ptr', C_STRUCTS.__cxa_exception.adjustedPtr, 'adjustedPtr', '*') }}};
11179
};
@@ -131,52 +99,6 @@ var LibraryExceptions = {
13199
};
132100
},
133101

134-
$exception_addRef: function (info) {
135-
#if EXCEPTION_DEBUG
136-
dbg('exception_addRef ' + ptrToString(info.excPtr));
137-
#endif
138-
info.add_ref();
139-
},
140-
141-
$exception_decRef__deps: ['__cxa_free_exception'
142-
#if EXCEPTION_DEBUG
143-
, '$exceptionLast', '$exceptionCaught'
144-
#endif
145-
],
146-
$exception_decRef: function(info) {
147-
#if EXCEPTION_DEBUG
148-
dbg('exception_decRef ' + ptrToString(info.excPtr));
149-
#endif
150-
// A rethrown exception can reach refcount 0; it must not be discarded
151-
// Its next handler will clear the rethrown flag and addRef it, prior to
152-
// final decRef and destruction here
153-
if (info.release_ref() && !info.get_rethrown()) {
154-
var destructor = info.get_destructor();
155-
if (destructor) {
156-
// In Wasm, destructors return 'this' as in ARM
157-
{{{ makeDynCall('pp', 'destructor') }}}(info.excPtr);
158-
}
159-
___cxa_free_exception(info.excPtr);
160-
#if EXCEPTION_DEBUG
161-
dbg('decref freeing exception ' + [ptrToString(info.excPtr), exceptionLast, 'stack', exceptionCaught]);
162-
#endif
163-
}
164-
},
165-
166-
__cxa_increment_exception_refcount__deps: ['$exception_addRef', '$ExceptionInfo'],
167-
__cxa_increment_exception_refcount__sig: 'vp',
168-
__cxa_increment_exception_refcount: function(ptr) {
169-
if (!ptr) return;
170-
exception_addRef(new ExceptionInfo(ptr));
171-
},
172-
173-
__cxa_decrement_exception_refcount__deps: ['$exception_decRef', '$ExceptionInfo'],
174-
__cxa_decrement_exception_refcount__sig: 'vp',
175-
__cxa_decrement_exception_refcount: function(ptr) {
176-
if (!ptr) return;
177-
exception_decRef(new ExceptionInfo(ptr));
178-
},
179-
180102
// Here, we throw an exception after recording a couple of values that we need to remember
181103
// We also remember that it was the last exception thrown as we need to know that later.
182104
__cxa_throw__sig: 'vppp',
@@ -224,7 +146,8 @@ var LibraryExceptions = {
224146
return type;
225147
},
226148

227-
__cxa_begin_catch__deps: ['$exceptionCaught', '$exception_addRef', '$uncaughtExceptionCount'],
149+
__cxa_begin_catch__deps: ['$exceptionCaught', '__cxa_increment_exception_refcount',
150+
'$uncaughtExceptionCount'],
228151
__cxa_begin_catch__sig: 'pp',
229152
__cxa_begin_catch: function(ptr) {
230153
var info = new ExceptionInfo(ptr);
@@ -237,15 +160,15 @@ var LibraryExceptions = {
237160
#if EXCEPTION_DEBUG
238161
dbg('__cxa_begin_catch ' + [ptrToString(ptr), 'stack', exceptionCaught]);
239162
#endif
240-
exception_addRef(info);
163+
___cxa_increment_exception_refcount(info.excPtr);
241164
return info.get_exception_ptr();
242165
},
243166

244167
// We're done with a catch. Now, we can run the destructor if there is one
245168
// and free the exception. Note that if the dynCall on the destructor fails
246169
// due to calling apply on undefined, that means that the destructor is
247170
// an invalid index into the FUNCTION_TABLE, so something has gone wrong.
248-
__cxa_end_catch__deps: ['$exceptionCaught', '$exceptionLast', '$exception_decRef'],
171+
__cxa_end_catch__deps: ['$exceptionCaught', '$exceptionLast', '__cxa_decrement_exception_refcount', 'setThrew'],
249172
__cxa_end_catch__sig: 'v',
250173
__cxa_end_catch: function() {
251174
// Clear state flag.
@@ -259,17 +182,18 @@ var LibraryExceptions = {
259182
#if EXCEPTION_DEBUG
260183
dbg('__cxa_end_catch popped ' + [info, exceptionLast, 'stack', exceptionCaught]);
261184
#endif
262-
exception_decRef(info);
185+
___cxa_decrement_exception_refcount(info.excPtr);
263186
exceptionLast = 0; // XXX in decRef?
264187
},
265188

266189
__cxa_get_exception_ptr__deps: ['$ExceptionInfo'],
267190
__cxa_get_exception_ptr__sig: 'pp',
268191
__cxa_get_exception_ptr: function(ptr) {
192+
var rtn = new ExceptionInfo(ptr).get_exception_ptr();
269193
#if EXCEPTION_DEBUG
270-
dbg('__cxa_get_exception_ptr ' + ptrToString(ptr));
194+
err('__cxa_get_exception_ptr ' + ptrToString(ptr) + ' -> ' + ptrToString(rtn));
271195
#endif
272-
return new ExceptionInfo(ptr).get_exception_ptr();
196+
return rtn;
273197
},
274198

275199
__cxa_uncaught_exceptions__deps: ['$uncaughtExceptionCount'],
@@ -285,13 +209,13 @@ var LibraryExceptions = {
285209
throw exception;
286210
},
287211

288-
__cxa_current_primary_exception__deps: ['$exceptionCaught', '$exception_addRef'],
212+
__cxa_current_primary_exception__deps: ['$exceptionCaught', '__cxa_increment_exception_refcount'],
289213
__cxa_current_primary_exception: function() {
290214
if (!exceptionCaught.length) {
291215
return 0;
292216
}
293217
var info = exceptionCaught[exceptionCaught.length - 1];
294-
exception_addRef(info);
218+
___cxa_increment_exception_refcount(info.excPtr);
295219
return info.excPtr;
296220
},
297221

src/library_exceptions_stub.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
var LibraryExceptions = {};
88

99
[
10-
'__cxa_allocate_exception',
11-
'__cxa_free_exception',
12-
'__cxa_increment_exception_refcount',
13-
'__cxa_decrement_exception_refcount',
1410
'__cxa_throw',
1511
'__cxa_rethrow',
1612
'llvm_eh_typeid_for',

0 commit comments

Comments
 (0)