diff options
author | dtorilov <dtorilov@yandex-team.com> | 2023-05-24 20:01:25 +0300 |
---|---|---|
committer | dtorilov <dtorilov@yandex-team.com> | 2023-05-24 20:01:25 +0300 |
commit | f14549c83decddd1c8634ce32c8616ebb654c5a3 (patch) | |
tree | 5e016684f9d81eed049e148cf99f6a111410cdef /contrib/libs/cxxsupp/libcxxabi/src | |
parent | 39b4a50f6cc323d60f9cee1b3e3f55e1df2dd9bd (diff) | |
download | ydb-f14549c83decddd1c8634ce32c8616ebb654c5a3.tar.gz |
YT-19142: Add emscripten patches to libcxxabi
Diffstat (limited to 'contrib/libs/cxxsupp/libcxxabi/src')
8 files changed, 196 insertions, 27 deletions
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/abort_message.cpp b/contrib/libs/cxxsupp/libcxxabi/src/abort_message.cpp index 859a5031b93..0cbce088228 100644 --- a/contrib/libs/cxxsupp/libcxxabi/src/abort_message.cpp +++ b/contrib/libs/cxxsupp/libcxxabi/src/abort_message.cpp @@ -33,12 +33,21 @@ void abort_message(const char* format, ...) // formatting into the variable-sized buffer fails. #if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL) { +#if defined(__EMSCRIPTEN__) && defined(NDEBUG) + // Just trap in a non-debug build. These internal libcxxabi assertions are + // very rare, and it's not worth linking in vfprintf stdio support or + // even minimal logging for them, as we'll have a proper call stack, which + // will show a call into "abort_message", and can help debugging. (In a + // debug build that won't be inlined.) + abort(); +#else fprintf(stderr, "libc++abi: "); va_list list; va_start(list, format); vfprintf(stderr, format, list); va_end(list); fprintf(stderr, "\n"); +#endif } #endif diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp b/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp index 36388d50dad..82123825afc 100644 --- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp +++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp @@ -180,7 +180,12 @@ extern "C" { // object. Zero-fill the object. If memory can't be allocated, call // std::terminate. Return a pointer to the memory to be used for the // user's exception object. -void *__cxa_allocate_exception(size_t thrown_size) throw() { +#ifndef __EMSCRIPTEN__ +void *__cxa_allocate_exception(size_t thrown_size) throw() +#else +void *__cxa_allocate_exception(size_t thrown_size) _NOEXCEPT +#endif +{ size_t actual_size = cxa_exception_size_from_exception_thrown_size(thrown_size); // Allocate extra space before the __cxa_exception header to ensure the @@ -198,7 +203,12 @@ void *__cxa_allocate_exception(size_t thrown_size) throw() { // Free a __cxa_exception object allocated with __cxa_allocate_exception. -void __cxa_free_exception(void *thrown_object) throw() { +#ifndef __EMSCRIPTEN__ +void __cxa_free_exception(void *thrown_object) throw() +#else +void __cxa_free_exception(void *thrown_object) _NOEXCEPT +#endif +{ // Compute the size of the padding before the header. size_t header_offset = get_cxa_exception_offset(); char *raw_buffer = @@ -253,8 +263,21 @@ handler, _Unwind_RaiseException may return. In that case, __cxa_throw will call terminate, assuming that there was no handler for the exception. */ + +#if defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG) +extern "C" { +void __throw_exception_with_stack_trace(_Unwind_Exception*); +} // extern "C" +#endif + void -__cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) { +#ifdef __USING_WASM_EXCEPTIONS__ +// In wasm, destructors return their argument +__cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)) +#else +__cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) +#endif +{ __cxa_eh_globals *globals = __cxa_get_globals(); __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object); @@ -273,11 +296,27 @@ __cxa_throw(void *thrown_object, std::type_info *tinfo, void (*dest)(void *)) { __asan_handle_no_return(); #endif +#ifdef __EMSCRIPTEN__ +#ifdef __USING_SJLJ_EXCEPTIONS__ + _Unwind_SjLj_RaiseException(&exception_header->unwindHeader); +#elif __USING_WASM_EXCEPTIONS__ +#ifdef NDEBUG + _Unwind_RaiseException(&exception_header->unwindHeader); +#else + // In debug mode, call a JS library function to use WebAssembly.Exception JS + // API, which enables us to include stack traces + __throw_exception_with_stack_trace(&exception_header->unwindHeader); +#endif +#else + _Unwind_RaiseException(&exception_header->unwindHeader); +#endif +#else // !__EMSCRIPTEN__ #ifdef __USING_SJLJ_EXCEPTIONS__ _Unwind_SjLj_RaiseException(&exception_header->unwindHeader); #else _Unwind_RaiseException(&exception_header->unwindHeader); #endif +#endif // This only happens when there is no handler, or some unexpected unwinding // error happens. failed_throw(exception_header); @@ -292,7 +331,12 @@ The adjusted pointer is computed by the personality routine during phase 1 Requires: exception is native */ -void *__cxa_get_exception_ptr(void *unwind_exception) throw() { +#ifndef __EMSCRIPTEN__ +void *__cxa_get_exception_ptr(void *unwind_exception) throw() +#else +void *__cxa_get_exception_ptr(void *unwind_exception) _NOEXCEPT +#endif +{ #if defined(_LIBCXXABI_ARM_EHABI) return reinterpret_cast<void*>( static_cast<_Unwind_Control_Block*>(unwind_exception)->barrier_cache.bitpattern[0]); @@ -307,7 +351,12 @@ void *__cxa_get_exception_ptr(void *unwind_exception) throw() { The routine to be called before the cleanup. This will save __cxa_exception in __cxa_eh_globals, so that __cxa_end_cleanup() can recover later. */ -bool __cxa_begin_cleanup(void *unwind_arg) throw() { +#ifndef __EMSCRIPTEN__ +bool __cxa_begin_cleanup(void *unwind_arg) throw() +#else +bool __cxa_begin_cleanup(void *unwind_arg) _NOEXCEPT +#endif +{ _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg); __cxa_eh_globals* globals = __cxa_get_globals(); __cxa_exception* exception_header = @@ -425,8 +474,13 @@ to terminate or unexpected during unwinding. * If we haven't terminated, assume the exception object is just past the _Unwind_Exception and return a pointer to that. */ +#ifndef __EMSCRIPTEN__ void* __cxa_begin_catch(void* unwind_arg) throw() +#else +void* +__cxa_begin_catch(void* unwind_arg) _NOEXCEPT +#endif { _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(unwind_arg); bool native_exception = __isOurExceptionClass(unwind_exception); @@ -633,8 +687,14 @@ void __cxa_rethrow() { Requires: If thrown_object is not NULL, it is a native exception. */ +#ifndef __EMSCRIPTEN__ +void +__cxa_increment_exception_refcount(void *thrown_object) throw() +#else void -__cxa_increment_exception_refcount(void *thrown_object) throw() { +__cxa_increment_exception_refcount(void *thrown_object) _NOEXCEPT +#endif +{ if (thrown_object != NULL ) { __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object); @@ -650,8 +710,14 @@ __cxa_increment_exception_refcount(void *thrown_object) throw() { Requires: If thrown_object is not NULL, it is a native exception. */ +#ifndef __EMSCRIPTEN__ +_LIBCXXABI_NO_CFI +void __cxa_decrement_exception_refcount(void *thrown_object) throw() +#else _LIBCXXABI_NO_CFI -void __cxa_decrement_exception_refcount(void *thrown_object) throw() { +void __cxa_decrement_exception_refcount(void *thrown_object) _NOEXCEPT +#endif +{ if (thrown_object != NULL ) { __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object); @@ -674,7 +740,12 @@ void __cxa_decrement_exception_refcount(void *thrown_object) throw() { been no exceptions thrown, ever, on this thread, we can return NULL without the need to allocate the exception-handling globals. */ -void *__cxa_current_primary_exception() throw() { +#ifndef __EMSCRIPTEN__ +void *__cxa_current_primary_exception() throw() +#else +void *__cxa_current_primary_exception() _NOEXCEPT +#endif +{ // get the current exception __cxa_eh_globals* globals = __cxa_get_globals_fast(); if (NULL == globals) @@ -745,11 +816,21 @@ __cxa_rethrow_primary_exception(void* thrown_object) // If we return client will call terminate() } +#ifndef __EMSCRIPTEN__ bool __cxa_uncaught_exception() throw() { return __cxa_uncaught_exceptions() != 0; } +#else +bool +__cxa_uncaught_exception() _NOEXCEPT { return __cxa_uncaught_exceptions() != 0; } +#endif +#ifndef __EMSCRIPTEN__ unsigned int __cxa_uncaught_exceptions() throw() +#else +unsigned int +__cxa_uncaught_exceptions() _NOEXCEPT +#endif { // This does not report foreign exceptions in flight __cxa_eh_globals* globals = __cxa_get_globals_fast(); diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h b/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h index 7a32fb653b0..4d1770c3145 100644 --- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h +++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h @@ -19,6 +19,25 @@ namespace __cxxabiv1 { +#ifdef __USING_EMSCRIPTEN_EXCEPTIONS__ + +struct _LIBCXXABI_HIDDEN __cxa_exception { + size_t referenceCount; + std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + uint8_t caught; + uint8_t rethrown; + void *adjustedPtr; + // Add padding to ensure that the size of __cxa_exception is a multiple of + // the maximum useful alignment for the target machine. This ensures that + // the thrown object that follows has that correct alignment. + void *padding; +}; + +static_assert(sizeof(__cxa_exception) % alignof(max_align_t) == 0, "__cxa_exception must have a size that is multipl of max alignment"); + +#else + static const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC++\0 static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1 static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++ @@ -43,7 +62,12 @@ struct _LIBCXXABI_HIDDEN __cxa_exception { // Manage the exception object itself. std::type_info *exceptionType; +#ifdef __USING_WASM_EXCEPTIONS__ + // In wasm, destructors return their argument + void *(*exceptionDestructor)(void *); +#else void (*exceptionDestructor)(void *); +#endif std::unexpected_handler unexpectedHandler; std::terminate_handler terminateHandler; @@ -159,6 +183,8 @@ extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals_fast (); extern "C" _LIBCXXABI_FUNC_VIS void * __cxa_allocate_dependent_exception (); extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * dependent_exception); +#endif // !__USING_EMSCRIPTEN_EXCEPTIONS__ + } // namespace __cxxabiv1 #endif // _CXA_EXCEPTION_H diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_handlers.cpp b/contrib/libs/cxxsupp/libcxxabi/src/cxa_handlers.cpp index 344250dde0c..07913fba397 100644 --- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_handlers.cpp +++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_handlers.cpp @@ -73,7 +73,7 @@ __attribute__((noreturn)) void terminate() noexcept { -#ifndef _LIBCXXABI_NO_EXCEPTIONS +#if !defined(_LIBCXXABI_NO_EXCEPTIONS) && !defined(__USING_EMSCRIPTEN_EXCEPTIONS__) // If there might be an uncaught exception using namespace __cxxabiv1; __cxa_eh_globals* globals = __cxa_get_globals_fast(); diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp b/contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp index f6e135f137c..12387bd7ad9 100644 --- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp +++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp @@ -32,6 +32,8 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, _Unwind_Personality_Fn); #endif +#define __USING_SJLJ_OR_WASM_EXCEPTIONS__ (__USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__) + /* Exception Header Layout: @@ -61,7 +63,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, +------------------+--+-----+-----+------------------------+--------------------------+ | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table | +---------------------+-----------+---------------------------------------------------+ -#ifndef __USING_SJLJ_EXCEPTIONS__ +#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__ +---------------------+-----------+------------------------------------------------+ | Beginning of Call Site Table The current ip lies within the | | ... (start, length) range of one of these | @@ -75,7 +77,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, | +-------------+---------------------------------+------------------------------+ | | ... | +----------------------------------------------------------------------------------+ -#else // __USING_SJLJ_EXCEPTIONS__ +#else // !__USING_SJLJ_OR_WASM_EXCEPTIONS__ +---------------------+-----------+------------------------------------------------+ | Beginning of Call Site Table The current ip is a 1-based index into | | ... this table. Or it is -1 meaning no | @@ -88,7 +90,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, | +-------------+---------------------------------+------------------------------+ | | ... | +----------------------------------------------------------------------------------+ -#endif // __USING_SJLJ_EXCEPTIONS__ +#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__ +---------------------------------------------------------------------+ | Beginning of Action Table ttypeIndex == 0 : cleanup | | ... ttypeIndex > 0 : catch | @@ -538,7 +540,7 @@ void set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context, const scan_results& results) { -#if defined(__USING_SJLJ_EXCEPTIONS__) +#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__ #define __builtin_eh_return_data_regno(regno) regno #elif defined(__ibmxl__) // IBM xlclang++ compiler does not support __builtin_eh_return_data_regno. @@ -633,7 +635,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Get beginning current frame's code (as defined by the // emitted dwarf code) uintptr_t funcStart = _Unwind_GetRegionStart(context); -#ifdef __USING_SJLJ_EXCEPTIONS__ +#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__ if (ip == uintptr_t(-1)) { // no action @@ -643,9 +645,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, else if (ip == 0) call_terminate(native_exception, unwind_exception); // ip is 1-based index into call site table -#else // !__USING_SJLJ_EXCEPTIONS__ +#else // !__USING_SJLJ_OR_WASM_EXCEPTIONS__ uintptr_t ipOffset = ip - funcStart; -#endif // !defined(_USING_SLJL_EXCEPTIONS__) +#endif // !defined(__USING_SJLJ_OR_WASM_EXCEPTIONS__) const uint8_t* classInfo = NULL; // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding // dwarf emission @@ -667,7 +669,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Walk call-site table looking for range that // includes current PC. uint8_t callSiteEncoding = *lsda++; -#ifdef __USING_SJLJ_EXCEPTIONS__ +#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__ (void)callSiteEncoding; // When using SjLj exceptions, callSiteEncoding is never used #endif uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda)); @@ -678,7 +680,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, while (callSitePtr < callSiteTableEnd) { // There is one entry per call site. -#ifndef __USING_SJLJ_EXCEPTIONS__ +#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__ // The call sites are non-overlapping in [start, start+length) // The call sites are ordered in increasing value of start uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); @@ -686,15 +688,15 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t actionEntry = readULEB128(&callSitePtr); if ((start <= ipOffset) && (ipOffset < (start + length))) -#else // __USING_SJLJ_EXCEPTIONS__ +#else // __USING_SJLJ_OR_WASM_EXCEPTIONS__ // ip is 1-based index into this table uintptr_t landingPad = readULEB128(&callSitePtr); uintptr_t actionEntry = readULEB128(&callSitePtr); if (--ip == 0) -#endif // __USING_SJLJ_EXCEPTIONS__ +#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__ { // Found the call site containing ip. -#ifndef __USING_SJLJ_EXCEPTIONS__ +#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__ if (landingPad == 0) { // No handler here @@ -702,9 +704,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, return; } landingPad = (uintptr_t)lpStart + landingPad; -#else // __USING_SJLJ_EXCEPTIONS__ +#else // __USING_SJLJ_OR_WASM_EXCEPTIONS__ ++landingPad; -#endif // __USING_SJLJ_EXCEPTIONS__ +#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__ results.landingPad = landingPad; if (actionEntry == 0) { @@ -832,7 +834,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, action += actionOffset; } // there is no break out of this loop, only return } -#ifndef __USING_SJLJ_EXCEPTIONS__ +#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__ else if (ipOffset < start) { // There is no call site for this ip @@ -840,7 +842,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // Possible stack corruption. call_terminate(native_exception, unwind_exception); } -#endif // !__USING_SJLJ_EXCEPTIONS__ +#endif // !__USING_SJLJ_OR_WASM_EXCEPTIONS__ } // there might be some tricky cases which break out of this loop // It is possible that no eh table entry specify how to handle @@ -897,7 +899,9 @@ _UA_CLEANUP_PHASE */ #if !defined(_LIBCXXABI_ARM_EHABI) -#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) +#ifdef __USING_WASM_EXCEPTIONS__ +_Unwind_Reason_Code __gxx_personality_wasm0 +#elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) static _Unwind_Reason_Code __gxx_personality_imp #else _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code @@ -962,6 +966,11 @@ __gxx_personality_v0 exc->languageSpecificData = results.languageSpecificData; exc->catchTemp = reinterpret_cast<void*>(results.landingPad); exc->adjustedPtr = results.adjustedPtr; +#ifdef __USING_WASM_EXCEPTIONS__ + // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the + // results here. + set_registers(unwind_exception, context, results); +#endif } return _URC_HANDLER_FOUND; } diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_thread_atexit.cpp b/contrib/libs/cxxsupp/libcxxabi/src/cxa_thread_atexit.cpp index 665f9e55694..bd7677a10ef 100644 --- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_thread_atexit.cpp +++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_thread_atexit.cpp @@ -112,9 +112,14 @@ extern "C" { #ifdef HAVE___CXA_THREAD_ATEXIT_IMPL return __cxa_thread_atexit_impl(dtor, obj, dso_symbol); #else +#ifndef __EMSCRIPTEN__ + // Emscripten doesn't implement __cxa_thread_atexit_impl, so we can simply + // avoid this check. if (__cxa_thread_atexit_impl) { return __cxa_thread_atexit_impl(dtor, obj, dso_symbol); - } else { + } else +#endif + { // Initialize the dtors std::__libcpp_tls_key (uses __cxa_guard_*() for // one-time initialization and __cxa_atexit() for destruction) static DtorsManager manager; diff --git a/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp b/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp index e1086661c01..8ee2e7607c7 100644 --- a/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp +++ b/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp @@ -1323,4 +1323,35 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info, use_strcmp); } +// XXX EMSCRIPTEN + +#ifndef __USING_WASM_EXCEPTIONS__ + +// These functions are used by the emscripten-style exception handling +// mechanism. +// Note that they need to be included even in the `-noexcept` build of +// libc++abi to support the case where some parts of a project are built +// with exception catching enabled, but at link time exception catching +// is disabled. In this case dependencies to these functions (and the JS +// functions which call them) will still exist in the final build. +extern "C" { + +int __cxa_can_catch(__shim_type_info* catchType, __shim_type_info* excpType, void **thrown) { + //std::type_info *t1 = static_cast<std::type_info*>(catchType); + //std::type_info *t2 = static_cast<std::type_info*>(excpType); + //printf("can %s catch %s (%p)?\n", t1->name(), t2->name(), thrown); + + void *temp = *thrown; + int ret = catchType->can_catch(excpType, temp); + if (ret) *thrown = temp; // apply changes only if we are catching + return ret; +} + +int __cxa_is_pointer_type(__shim_type_info* type) { + return !!dynamic_cast<__pointer_type_info*>(type); +} + +} +#endif // __USING_EMSCRIPTEN_EXCEPTIONS__ + } // __cxxabiv1 diff --git a/contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp b/contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp index 4a664e15a50..48e509ba2b3 100644 --- a/contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp +++ b/contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp @@ -37,9 +37,17 @@ operator new(std::size_t size) _THROW_BAD_ALLOC else #ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_alloc(); +#ifdef __EMSCRIPTEN__ + // Abort here so that when exceptions are disabled, we do not just + // return 0 when malloc returns 0. + // We could also do this with set_new_handler, but that adds a + // global constructor and a table entry, overhead that we can avoid + // by doing it this way. + abort(); #else break; #endif +#endif } return p; } |