aboutsummaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/include/EGL/eglplatform.h2
-rw-r--r--system/include/SDL/SDL_config_minimal.h2
-rw-r--r--system/include/SDL/SDL_stdinc.h2
-rw-r--r--system/include/emscripten/bind.h15
-rw-r--r--system/include/emscripten/emscripten.h124
-rw-r--r--system/include/emscripten/html5.h25
-rw-r--r--system/include/emscripten/val.h200
-rw-r--r--system/include/emscripten/wire.h2
-rw-r--r--system/include/execinfo.h44
-rw-r--r--system/include/gc.h2
-rw-r--r--system/include/jansson.h2
-rw-r--r--system/include/unwind.h154
-rw-r--r--system/lib/compiler-rt/int_endianness.h2
-rw-r--r--system/lib/dlmalloc.c2
-rw-r--r--system/lib/embind/bind.cpp41
-rw-r--r--system/lib/gl.c4
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