diff options
Diffstat (limited to 'system')
-rw-r--r-- | system/include/EGL/eglplatform.h | 2 | ||||
-rw-r--r-- | system/include/SDL/SDL_config_minimal.h | 2 | ||||
-rw-r--r-- | system/include/SDL/SDL_stdinc.h | 2 | ||||
-rw-r--r-- | system/include/emscripten/bind.h | 15 | ||||
-rw-r--r-- | system/include/emscripten/emscripten.h | 124 | ||||
-rw-r--r-- | system/include/emscripten/html5.h | 25 | ||||
-rw-r--r-- | system/include/emscripten/val.h | 200 | ||||
-rw-r--r-- | system/include/emscripten/wire.h | 2 | ||||
-rw-r--r-- | system/include/execinfo.h | 44 | ||||
-rw-r--r-- | system/include/gc.h | 2 | ||||
-rw-r--r-- | system/include/jansson.h | 2 | ||||
-rw-r--r-- | system/include/unwind.h | 154 | ||||
-rw-r--r-- | system/lib/compiler-rt/int_endianness.h | 2 | ||||
-rw-r--r-- | system/lib/dlmalloc.c | 2 | ||||
-rw-r--r-- | system/lib/embind/bind.cpp | 41 | ||||
-rw-r--r-- | system/lib/gl.c | 4 |
16 files changed, 318 insertions, 305 deletions
diff --git a/system/include/EGL/eglplatform.h b/system/include/EGL/eglplatform.h index 2db2cc47..77e885a8 100644 --- a/system/include/EGL/eglplatform.h +++ b/system/include/EGL/eglplatform.h @@ -75,7 +75,7 @@ typedef HDC EGLNativeDisplayType; typedef HBITMAP EGLNativePixmapType; typedef HWND EGLNativeWindowType; -#elif defined(EMSCRIPTEN) +#elif defined(__EMSCRIPTEN__) typedef int EGLNativeDisplayType; typedef int EGLNativeWindowType; diff --git a/system/include/SDL/SDL_config_minimal.h b/system/include/SDL/SDL_config_minimal.h index ea0cec10..18951f18 100644 --- a/system/include/SDL/SDL_config_minimal.h +++ b/system/include/SDL/SDL_config_minimal.h @@ -33,7 +33,7 @@ #include <stddef.h> #include <stdarg.h> -#if !defined(EMSCRIPTEN) && !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H) +#if !defined(__EMSCRIPTEN__) && !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H) typedef unsigned int size_t; typedef signed char int8_t; typedef unsigned char uint8_t; diff --git a/system/include/SDL/SDL_stdinc.h b/system/include/SDL/SDL_stdinc.h index c4ce7ccd..508ecdb4 100644 --- a/system/include/SDL/SDL_stdinc.h +++ b/system/include/SDL/SDL_stdinc.h @@ -65,7 +65,7 @@ #endif #if defined(HAVE_INTTYPES_H) # include <inttypes.h> -#elif defined(EMSCRIPTEN) || defined(HAVE_STDINT_H) +#elif defined(__EMSCRIPTEN__) || defined(HAVE_STDINT_H) # include <stdint.h> #endif #ifdef HAVE_CTYPE_H diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 390533f3..872f279b 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -17,8 +17,6 @@ namespace emscripten { BY_EMVAL = 2, }; -#define EMSCRIPTEN_ALWAYS_INLINE __attribute__((always_inline)) - namespace internal { typedef long GenericEnumValue; @@ -35,18 +33,21 @@ namespace emscripten { void _embind_register_bool( TYPEID boolType, const char* name, + size_t size, bool trueValue, bool falseValue); void _embind_register_integer( TYPEID integerType, const char* name, + size_t size, long minRange, unsigned long maxRange); void _embind_register_float( TYPEID floatType, - const char* name); + const char* name, + size_t size); void _embind_register_std_string( TYPEID stringType, @@ -163,7 +164,9 @@ namespace emscripten { void _embind_register_enum( TYPEID enumType, - const char* name); + const char* name, + size_t size, + bool isSigned); void _embind_register_enum_value( TYPEID enumType, @@ -1182,7 +1185,9 @@ namespace emscripten { enum_(const char* name) { _embind_register_enum( internal::TypeID<EnumType>::get(), - name); + name, + sizeof(EnumType), + std::is_signed<typename std::underlying_type<EnumType>::type>::value); } enum_& value(const char* name, EnumType value) { diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index eb5ded91..73836018 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -14,7 +14,7 @@ extern "C" { #endif -#if !EMSCRIPTEN +#if !__EMSCRIPTEN__ #include <SDL/SDL.h> /* for SDL_Delay in async_call */ #endif @@ -40,10 +40,15 @@ extern "C" { #define EM_ASM(...) emscripten_asm_const(#__VA_ARGS__) /* - * Input-output versions of EM_ASM. EM_ASM_INT receives arguments of - * either int or double type and returns an int; EM_ASM_DOUBLE - * receives similar arguments (int or double) but returns a double. - * Arguments arrive as $0, $1 etc; output value should be returned: + * Input-output versions of EM_ASM. + * + * EM_ASM_ (an extra _ is added) or EM_ASM_ARGS allow sending values + * (ints or doubles) into the code. If you also want a return value, + * EM_ASM_INT receives arguments (of int or double type) + * and returns an int; EM_ASM_DOUBLE does the same and returns + * a double. + * + * Arguments arrive as $0, $1 etc. The output value should be returned: * * int x = EM_ASM_INT({ * console.log('I received: ' + [$0, $1]); @@ -54,18 +59,16 @@ extern "C" { * (int or double) but *not* to pass any values, you can use * EM_ASM_INT_V and EM_ASM_DOUBLE_V respectively. */ +#define EM_ASM_(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) +#define EM_ASM_ARGS(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) #define EM_ASM_INT(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) #define EM_ASM_DOUBLE(code, ...) emscripten_asm_const_double(#code, __VA_ARGS__) #define EM_ASM_INT_V(code) emscripten_asm_const_int(#code) #define EM_ASM_DOUBLE_V(code) emscripten_asm_const_double(#code) /* - * Forces LLVM to not dead-code-eliminate a function. Note that - * you still need to use EXPORTED_FUNCTIONS so it stays alive - * in JS, e.g. - * emcc -s EXPORTED_FUNCTIONS=["_main", "_myfunc"] - * and in the source file - * void EMSCRIPTEN_KEEPALIVE myfunc() {..} + * Forces LLVM to not dead-code-eliminate a function. This also + * exports the function, as if you added it to EXPORTED_FUNCTIONS. */ #define EMSCRIPTEN_KEEPALIVE __attribute__((used)) @@ -94,7 +97,7 @@ extern void emscripten_async_run_script(const char *script, int millis); * for this is to load an asset module, that is, the output of the * file packager. */ -extern void emscripten_async_load_script(const char *script, void (*onload)(), void (*onerror)()); +extern void emscripten_async_load_script(const char *script, void (*onload)(void), void (*onerror)(void)); /* * Set a C function as the main event loop. The JS environment @@ -116,6 +119,9 @@ extern void emscripten_async_load_script(const char *script, void (*onload)(), v * asynchronous callbacks, but you must pause the main * loop until they complete. * + * If you want your main loop function to receive a void* + * argument, use emscripten_set_main_loop_arg. + * @simulate_infinite_loop If true, this function will throw an * exception in order to stop execution of the caller. This * will lead to the main loop being entered instead of code @@ -132,11 +138,12 @@ extern void emscripten_async_load_script(const char *script, void (*onload)(), v * you created an object on the stack, it will be cleaned up * before the main loop will be called the first time. */ -#if EMSCRIPTEN -extern void emscripten_set_main_loop(void (*func)(), int fps, int simulate_infinite_loop); -extern void emscripten_pause_main_loop(); -extern void emscripten_resume_main_loop(); -extern void emscripten_cancel_main_loop(); +#if __EMSCRIPTEN__ +extern void emscripten_set_main_loop(void (*func)(void), int fps, int simulate_infinite_loop); +extern void emscripten_set_main_loop_arg(void (*func)(void*), void *arg, int fps, int simulate_infinite_loop); +extern void emscripten_pause_main_loop(void); +extern void emscripten_resume_main_loop(void); +extern void emscripten_cancel_main_loop(void); #else #define emscripten_set_main_loop(func, fps, simulateInfiniteLoop) \ while (1) { func(); usleep(1000000/fps); } @@ -156,7 +163,7 @@ extern void emscripten_cancel_main_loop(); * are not counted, do not block the main loop, and can fire * at specific time in the future. */ -#if EMSCRIPTEN +#if __EMSCRIPTEN__ extern void _emscripten_push_main_loop_blocker(void (*func)(void *), void *arg, const char *name); extern void _emscripten_push_uncounted_main_loop_blocker(void (*func)(void *), void *arg, const char *name); #else @@ -178,7 +185,7 @@ inline void _emscripten_push_uncounted_main_loop_blocker(void (*func)(void *), v * to 10, then push 10 blockers, as they complete the user will * see x/10 and so forth. */ -#if EMSCRIPTEN +#if __EMSCRIPTEN__ extern void emscripten_set_main_loop_expected_blockers(int num); #else inline void emscripten_set_main_loop_expected_blockers(int num) {} @@ -193,7 +200,7 @@ inline void emscripten_set_main_loop_expected_blockers(int num) {} * If millis is negative, the browser's requestAnimationFrame * mechanism is used. */ -#if EMSCRIPTEN +#if __EMSCRIPTEN__ extern void emscripten_async_call(void (*func)(void *), void *arg, int millis); #else inline void emscripten_async_call(void (*func)(void *), void *arg, int millis) { @@ -208,7 +215,7 @@ inline void emscripten_async_call(void (*func)(void *), void *arg, int millis) { * etc. are not run). This is implicitly performed when you do * an asynchronous operation like emscripten_async_call. */ -extern void emscripten_exit_with_live_runtime(); +extern void emscripten_exit_with_live_runtime(void); /* * Hide the OS mouse cursor over the canvas. Note that SDL's @@ -216,7 +223,7 @@ extern void emscripten_exit_with_live_runtime(); * the OS one. This command is useful to hide the OS cursor * if your app draws its own cursor. */ -void emscripten_hide_mouse(); +void emscripten_hide_mouse(void); /* * Resizes the pixel width and height of the <canvas> element @@ -237,11 +244,11 @@ void emscripten_get_canvas_size(int *width, int *height, int *isFullscreen); * absolute time, and is only meaningful in comparison to * other calls to this function. The unit is ms. */ -#if EMSCRIPTEN -double emscripten_get_now(); +#if __EMSCRIPTEN__ +double emscripten_get_now(void); #else #include <time.h> -double emscripten_get_now() { +double emscripten_get_now(void) { return (1000*clock())/(double)CLOCKS_PER_SEC; } #endif @@ -249,7 +256,7 @@ double emscripten_get_now() { /* * Simple random number generation in [0, 1), maps to Math.random(). */ -float emscripten_random(); +float emscripten_random(void); /* * This macro-looking function will cause Emscripten to @@ -317,6 +324,28 @@ void emscripten_async_wget_data(const char* url, void *arg, void (*onload)(void* void emscripten_async_wget2(const char* url, const char* file, const char* requesttype, const char* param, void *arg, void (*onload)(void*, const char*), void (*onerror)(void*, int), void (*onprogress)(void*, int)); /* + * More feature-complete version of emscripten_async_wget_data. Note: + * this version is experimental. + * + * The requesttype is 'GET' or 'POST', + * If is post request, param is the post parameter + * like key=value&key2=value2. + * The param 'arg' is a pointer will be pass to the callback + * The free param tells the runtime whether to free the returned buffer + after onload is complete. If false freeing the buffer is the receiver's + responsibility. + * The callbacks are called with an object pointer give in parameter. + * When file is ready then 'onload' callback will called with a pointer to + the buffer in memory and the size in bytes. + * During the download 'onprogress' callback will called. The first argument is + the number of bytes loaded. The second argument is the total size in bytes, + or zero if the size is unavailable. + * If any error occurred 'onerror' will called with the HTTP status code + and a string with the status description. + */ +void emscripten_async_wget2_data(const char* url, const char* requesttype, const char* param, void *arg, int free, void (*onload)(void*, void*, unsigned), void (*onerror)(void*, int, const char*), void (*onprogress)(void*, int, int)); + +/* * Prepare a file in asynchronous way. This does just the * preparation part of emscripten_async_wget, that is, it * works on file data already present, and asynchronously @@ -394,10 +423,17 @@ void emscripten_destroy_worker(worker_handle worker); void emscripten_call_worker(worker_handle worker, const char *funcname, char *data, int size, void (*callback)(char *, int, void*), void *arg); /* - * Sends a response when in a worker call. Should only be - * called once in each call. + * Sends a response when in a worker call. Both functions post a message + * back to the thread which called the worker. The _respond_provisionally + * variant can be invoked multiple times, which will queue up messages to + * be posted to the worker's creator. Eventually, the _respond variant must + * be invoked, which will disallow further messages and free framework + * resources previously allocated for this worker call. (Calling the + * provisional version is optional, but you must call the non-provisional + * one to avoid leaks.) */ void emscripten_worker_respond(char *data, int size); +void emscripten_worker_respond_provisionally(char *data, int size); /* * Checks how many responses are being waited for from a worker. This @@ -420,7 +456,39 @@ int emscripten_get_worker_queue_size(worker_handle worker); #define EMSCRIPTEN_NETWORK_WEBRTC 1 void emscripten_set_network_backend(int backend); +/* + * Returns the value of a compiler setting. For example + * + * emscripten_get_compiler_setting("PRECISE_F32") + * + * will return an integer representing the value of + * PRECISE_F32 during compilation. For values containing + * anything other than an integer, a string is returned + * (you will need to cast the int return value to a char*). + * + * Some useful things this can do is provide the + * version of emscripten ("EMSCRIPTEN_VERSION"), the optimization + * level ("OPT_LEVEL"), debug level ("DEBUG_LEVEL"), etc. + * + * For this command to work, you must build with + * -s RETAIN_COMPILER_SETTINGS=1 + * as otherwise we do not want to increase the build size + * with this metadata. + */ +int emscripten_get_compiler_setting(const char *name); + +/* + * Emits + * debugger; + * inline in the code, which tells the JS engine to invoke + * the debugger if it gets there. + */ +void emscripten_debugger(); + + +/* ===================================== */ /* Internal APIs. Be careful with these. */ +/* ===================================== */ /* * Profiling tools. diff --git a/system/include/emscripten/html5.h b/system/include/emscripten/html5.h index 06c647bf..db81725a 100644 --- a/system/include/emscripten/html5.h +++ b/system/include/emscripten/html5.h @@ -123,6 +123,10 @@ extern "C" { /* * The event structure passed in keyboard events keypress, keydown and keyup. * https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#keys + * + * Note that since the DOM Level 3 Events spec is very recent at the time of writing (2014-03), uniform + * support for the different fields in the spec is still in flux. Be sure to check the results in multiple + * browsers. See the unmerged pull request #2222 for an example way on how to interpret the legacy key events. */ typedef struct EmscriptenKeyboardEvent { // The printed representation of the pressed key. @@ -144,14 +148,18 @@ typedef struct EmscriptenKeyboardEvent { EM_UTF8 locale[32]; // The following fields are values from previous versions of the DOM key events specifications. // See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent?redirectlocale=en-US&redirectslug=DOM%2FKeyboardEvent - // The character representation of the key. + // The character representation of the key. This is the field 'char' from the docs, but renamed to charValue to avoid a C reserved word. + // Warning: This attribute has been dropped from DOM Level 3 events. EM_UTF8 charValue[32]; // The Unicode reference number of the key; this attribute is used only by the keypress event. For keys whose char attribute // contains multiple characters, this is the Unicode value of the first character in that attribute. + // Warning: This attribute is deprecated, you should use the field 'key' instead, if available. unsigned long charCode; // A system and implementation dependent numerical code identifying the unmodified value of the pressed key. + // Warning: This attribute is deprecated, you should use the field 'key' instead, if available. unsigned long keyCode; // A system and implementation dependent numeric code identifying the unmodified value of the pressed key; this is usually the same as keyCode. + // Warning: This attribute is deprecated, you should use the field 'key' instead, if available. unsigned long which; } EmscriptenKeyboardEvent; @@ -376,7 +384,7 @@ extern EMSCRIPTEN_RESULT emscripten_lock_orientation(int allowedOrientations); /* * Allows the screen to turn again into any orientation. */ -extern EMSCRIPTEN_RESULT emscripten_unlock_orientation(); +extern EMSCRIPTEN_RESULT emscripten_unlock_orientation(void); /* * The event structure passed in the fullscreenchange event. @@ -388,9 +396,16 @@ typedef struct EmscriptenFullscreenChangeEvent { // Specifies if the current page has the ability to display elements fullscreen. EM_BOOL fullscreenEnabled; // The nodeName of the target HTML Element that is in full screen mode. See https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeName + // If isFullscreen is false, then nodeName, id and elementWidth/Height specify information about the element that just exited fullscreen mode. EM_UTF8 nodeName[128]; // The HTML Element ID of the target HTML element that is in full screen mode. EM_UTF8 id[128]; + // The new pixel size of the element that changed fullscreen status. + int elementWidth; + int elementHeight; + // The size of the whole screen, in pixels. + int screenWidth; + int screenHeight; } EmscriptenFullscreenChangeEvent; /* @@ -413,7 +428,7 @@ extern EMSCRIPTEN_RESULT emscripten_request_fullscreen(const char *target, int d /* * Returns back to windowed browsing mode. */ -extern EMSCRIPTEN_RESULT emscripten_exit_fullscreen(); +extern EMSCRIPTEN_RESULT emscripten_exit_fullscreen(void); /* * The event structure passed in the pointerlockchange event. @@ -449,7 +464,7 @@ extern EMSCRIPTEN_RESULT emscripten_request_pointerlock(const char *target, int /* * Exits pointer lock state and restores the mouse cursor to be visible again. */ -extern EMSCRIPTEN_RESULT emscripten_exit_pointerlock(); +extern EMSCRIPTEN_RESULT emscripten_exit_pointerlock(void); #define EMSCRIPTEN_VISIBILITY_HIDDEN 0 #define EMSCRIPTEN_VISIBILITY_VISIBLE 1 @@ -566,7 +581,7 @@ extern EMSCRIPTEN_RESULT emscripten_set_gamepaddisconnected_callback(void *userD * Returns the number of gamepads connected to the system or EMSCRIPTEN_RESULT_NOT_SUPPORTED if the current browser does not support gamepads. * Note: A gamepad does not show up as connected until a button on it is pressed. */ -extern int emscripten_get_num_gamepads(); +extern int emscripten_get_num_gamepads(void); /* * Returns a snapshot of the current gamepad state. */ diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h index 19b1beb1..e217c959 100644 --- a/system/include/emscripten/val.h +++ b/system/include/emscripten/val.h @@ -2,6 +2,7 @@ #include <stdint.h> // uintptr_t #include <emscripten/wire.h> +#include <array> #include <vector> namespace emscripten { @@ -12,12 +13,10 @@ namespace emscripten { typedef struct _EM_VAL* EM_VAL; typedef struct _EM_DESTRUCTORS* EM_DESTRUCTORS; + typedef struct _EM_METHOD_CALLER* EM_METHOD_CALLER; + typedef double EM_GENERIC_WIRE_TYPE; + typedef const void* EM_VAR_ARGS; - // TODO: functions returning this are reinterpret_cast - // into the correct return type. this needs some thought - // for asm.js. - typedef void _POLYMORPHIC_RESULT; - void _emval_incref(EM_VAL value); void _emval_decref(EM_VAL value); @@ -28,37 +27,45 @@ namespace emscripten { EM_VAL _emval_undefined(); EM_VAL _emval_null(); EM_VAL _emval_new_cstring(const char*); - void _emval_take_value(TYPEID type/*, ...*/); + + EM_VAL _emval_take_value(TYPEID type, EM_VAR_ARGS argv); EM_VAL _emval_new( EM_VAL value, unsigned argCount, - internal::TYPEID argTypes[] - /*, ... */); + internal::TYPEID argTypes[], + EM_VAR_ARGS argv); EM_VAL _emval_get_global(const char* name); EM_VAL _emval_get_module_property(const char* name); EM_VAL _emval_get_property(EM_VAL object, EM_VAL key); void _emval_set_property(EM_VAL object, EM_VAL key, EM_VAL value); - _POLYMORPHIC_RESULT _emval_as(EM_VAL value, TYPEID returnType, EM_DESTRUCTORS* runDestructors); + EM_GENERIC_WIRE_TYPE _emval_as(EM_VAL value, TYPEID returnType, EM_DESTRUCTORS* destructors); EM_VAL _emval_call( EM_VAL value, unsigned argCount, - internal::TYPEID argTypes[] - /*, ... */); + internal::TYPEID argTypes[], + EM_VAR_ARGS argv); - // DO NOT call this more than once per signature. It will leak function pointer offsets! - GenericFunction _emval_get_method_caller( + // DO NOT call this more than once per signature. It will + // leak generated function objects! + EM_METHOD_CALLER _emval_get_method_caller( unsigned argCount, // including return value internal::TYPEID argTypes[]); + EM_GENERIC_WIRE_TYPE _emval_call_method( + EM_METHOD_CALLER caller, + EM_VAL handle, + const char* methodName, + EM_DESTRUCTORS* destructors, + EM_VAR_ARGS argv); bool _emval_has_function( EM_VAL value, const char* methodName); } template<const char* address> - struct symbol_registrar { + struct symbol_registrar { symbol_registrar() { internal::_emval_register_symbol(address); } @@ -66,19 +73,21 @@ namespace emscripten { template<typename ReturnType, typename... Args> struct Signature { + /* typedef typename BindingType<ReturnType>::WireType (*MethodCaller)( EM_VAL value, const char* methodName, EM_DESTRUCTORS* destructors, typename BindingType<Args>::WireType...); + */ - static MethodCaller get_method_caller() { - static MethodCaller fp = reinterpret_cast<MethodCaller>(init_method_caller()); - return fp; + static EM_METHOD_CALLER get_method_caller() { + static EM_METHOD_CALLER mc = init_method_caller(); + return mc; } private: - static GenericFunction init_method_caller() { + static EM_METHOD_CALLER init_method_caller() { WithPolicies<>::ArgTypeList<ReturnType, Args...> args; return _emval_get_method_caller(args.count, args.types); } @@ -100,19 +109,119 @@ namespace emscripten { EM_DESTRUCTORS destructors; }; + template<typename WireType> + struct GenericWireTypeConverter { + static WireType from(double wt) { + return static_cast<WireType>(wt); + } + }; + + template<typename Pointee> + struct GenericWireTypeConverter<Pointee*> { + static Pointee* from(double wt) { + return reinterpret_cast<Pointee*>(static_cast<uintptr_t>(wt)); + } + }; + + template<typename T> + T fromGenericWireType(double g) { + typedef typename BindingType<T>::WireType WireType; + WireType wt = GenericWireTypeConverter<WireType>::from(g); + return BindingType<T>::fromWireType(wt); + } + + template<typename... Args> + struct PackSize; + + template<> + struct PackSize<> { + static constexpr size_t value = 0; + }; + + template<typename Arg, typename... Args> + struct PackSize<Arg, Args...> { + static constexpr size_t value = (sizeof(typename BindingType<Arg>::WireType) + 7) / 8 + PackSize<Args...>::value; + }; + + union GenericWireType { + union { + unsigned u; + float f; + const void* p; + } w[2]; + double d; + }; + static_assert(sizeof(GenericWireType) == 8, "GenericWireType must be 8 bytes"); + static_assert(alignof(GenericWireType) == 8, "GenericWireType must be 8-byte-aligned"); + + inline void writeGenericWireType(GenericWireType*& cursor, float wt) { + cursor->w[0].f = wt; + ++cursor; + } + + inline void writeGenericWireType(GenericWireType*& cursor, double wt) { + cursor->d = wt; + ++cursor; + } + + template<typename T> + void writeGenericWireType(GenericWireType*& cursor, T* wt) { + cursor->w[0].p = wt; + ++cursor; + } + + inline void writeGenericWireType(GenericWireType*& cursor, const memory_view& wt) { + cursor[0].w[0].u = static_cast<unsigned>(wt.type); + cursor[0].w[1].u = wt.size; + cursor[1].w[0].p = wt.data; + cursor += 2; + } + + template<typename T> + void writeGenericWireType(GenericWireType*& cursor, T wt) { + cursor->w[0].u = static_cast<unsigned>(wt); + ++cursor; + } + + inline void writeGenericWireTypes(GenericWireType*&) { + } + + template<typename First, typename... Rest> + EMSCRIPTEN_ALWAYS_INLINE void writeGenericWireTypes(GenericWireType*& cursor, First&& first, Rest&&... rest) { + writeGenericWireType(cursor, BindingType<First>::toWireType(std::forward<First>(first))); + writeGenericWireTypes(cursor, std::forward<Rest>(rest)...); + } + + template<typename... Args> + struct WireTypePack { + WireTypePack(Args&&... args) { + GenericWireType* cursor = elements.data(); + writeGenericWireTypes(cursor, std::forward<Args>(args)...); + } + + operator EM_VAR_ARGS() const { + return elements.data(); + } + + private: + std::array<GenericWireType, PackSize<Args...>::value> elements; + }; + template<typename ReturnType, typename... Args> struct MethodCaller { static ReturnType call(EM_VAL handle, const char* methodName, Args&&... args) { auto caller = Signature<ReturnType, Args...>::get_method_caller(); + WireTypePack<Args...> argv(std::forward<Args>(args)...); EM_DESTRUCTORS destructors; - auto wireType = caller( + EM_GENERIC_WIRE_TYPE result = _emval_call_method( + caller, handle, methodName, &destructors, - toWireType(std::forward<Args>(args))...); + argv); DestructorsRunner rd(destructors); - return BindingType<ReturnType>::fromWireType(wireType); + return fromGenericWireType<ReturnType>(result); } }; @@ -121,12 +230,14 @@ namespace emscripten { static void call(EM_VAL handle, const char* methodName, Args&&... args) { auto caller = Signature<void, Args...>::get_method_caller(); + WireTypePack<Args...> argv(std::forward<Args>(args)...); EM_DESTRUCTORS destructors; - caller( + _emval_call_method( + caller, handle, methodName, &destructors, - toWireType(std::forward<Args>(args))...); + argv); DestructorsRunner rd(destructors); // void requires no translation } @@ -185,9 +296,13 @@ namespace emscripten { template<typename T> explicit val(T&& value) { + using namespace internal; + typedef internal::BindingType<T> BT; - auto taker = reinterpret_cast<internal::EM_VAL (*)(internal::TYPEID, typename BT::WireType)>(&internal::_emval_take_value); - handle = taker(internal::TypeID<T>::get(), BT::toWireType(std::forward<T>(value))); + WireTypePack<T> argv(std::forward<T>(value)); + handle = _emval_take_value( + internal::TypeID<T>::get(), + argv); } val() = delete; @@ -235,20 +350,15 @@ namespace emscripten { using namespace internal; WithPolicies<>::ArgTypeList<Args...> argList; + WireTypePack<Args...> argv(std::forward<Args>(args)...); // todo: this is awfully similar to operator(), can we // merge them somehow? - typedef EM_VAL (*TypedNew)( - EM_VAL, - unsigned, - TYPEID argTypes[], - typename BindingType<Args>::WireType...); - TypedNew typedNew = reinterpret_cast<TypedNew>(&_emval_new); return val( - typedNew( + _emval_new( handle, argList.count, argList.types, - toWireType(std::forward<Args>(args))...)); + argv)); } template<typename T> @@ -266,18 +376,13 @@ namespace emscripten { using namespace internal; WithPolicies<>::ArgTypeList<Args...> argList; - typedef EM_VAL (*TypedCall)( - EM_VAL, - unsigned, - TYPEID argTypes[], - typename BindingType<Args>::WireType...); - TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call); + WireTypePack<Args...> argv(std::forward<Args>(args)...); return val( - typedCall( + _emval_call( handle, argList.count, argList.types, - toWireType(std::forward<Args>(args))...)); + argv)); } template<typename ReturnValue, typename... Args> @@ -297,16 +402,13 @@ namespace emscripten { typedef BindingType<T> BT; - typedef typename BT::WireType (*TypedAs)( - EM_VAL value, - TYPEID returnType, - EM_DESTRUCTORS* runDestructors); - TypedAs typedAs = reinterpret_cast<TypedAs>(&_emval_as); - EM_DESTRUCTORS destructors; - typename BT::WireType wt = typedAs(handle, TypeID<T>::get(), &destructors); + EM_GENERIC_WIRE_TYPE result = _emval_as( + handle, + TypeID<T>::get(), + &destructors); DestructorsRunner dr(destructors); - return BT::fromWireType(wt); + return fromGenericWireType<T>(result); } private: diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h index c3ce8dd0..05b3ac33 100644 --- a/system/include/emscripten/wire.h +++ b/system/include/emscripten/wire.h @@ -12,6 +12,8 @@ #include <memory> #include <string> +#define EMSCRIPTEN_ALWAYS_INLINE __attribute__((always_inline)) + namespace emscripten { namespace internal { typedef void (*GenericFunction)(); diff --git a/system/include/execinfo.h b/system/include/execinfo.h deleted file mode 100644 index 17cda148..00000000 --- a/system/include/execinfo.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2003 Maxim Sobolev <sobomax@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |