aboutsummaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
authorChad Austin <chad@imvu.com>2013-05-03 01:11:08 -0700
committerChad Austin <chad@imvu.com>2013-05-17 12:56:16 -0700
commit31d6f4e7bf3b20be1a64ee481398910239174122 (patch)
tree22a4872878c7af383e089170658cf390c643d5dd /system
parenta7c47e66eed5c2db9aac373f9b0d043d9f048703 (diff)
Checkpoint work towards making vtable->JS calls faster.
Diffstat (limited to 'system')
-rw-r--r--system/include/emscripten/bind.h26
-rw-r--r--system/include/emscripten/val.h115
-rw-r--r--system/include/emscripten/wire.h3
3 files changed, 63 insertions, 81 deletions
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 7aa2a55e..d6d4f2c5 100644
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -18,7 +18,6 @@ namespace emscripten {
};
namespace internal {
- typedef void (*GenericFunction)();
typedef long GenericEnumValue;
// Implemented in JavaScript. Don't call these directly.
@@ -749,38 +748,19 @@ namespace emscripten {
template<typename ReturnType, typename... Args>
ReturnType call(const char* name, Args&&... args) const {
- return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...);
+ return wrapped.call<ReturnType>(name, std::forward<Args>(args)...);
}
template<typename ReturnType, typename... Args, typename Default>
ReturnType optional_call(const char* name, Default def, Args&&... args) const {
- if (has_function(name)) {
- return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...);
+ if (wrapped.has_function(name)) {
+ return call<ReturnType>(name, std::forward<Args>(args)...);
} else {
return def();
}
}
private:
- bool has_function(const char* name) const {
- return wrapped.has_function(name);
- }
-
- // this class only exists because you can't partially specialize function templates
- template<typename ReturnType, typename... Args>
- struct Caller {
- static ReturnType call(const val& v, const char* name, Args&&... args) {
- return v.call(name, std::forward<Args>(args)...).template as<ReturnType>();
- }
- };
-
- template<typename... Args>
- struct Caller<void, Args...> {
- static void call(const val& v, const char* name, Args&&... args) {
- v.call_void(name, std::forward<Args>(args)...);
- }
- };
-
val wrapped;
};
diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h
index edd070e3..185cc935 100644
--- a/system/include/emscripten/val.h
+++ b/system/include/emscripten/val.h
@@ -39,34 +39,67 @@ namespace emscripten {
unsigned argCount,
internal::TYPEID argTypes[]
/*, ... */);
- EM_VAL _emval_call_method(
- EM_VAL value,
- const char* methodName,
- unsigned argCount,
- internal::TYPEID argTypes[]
- /*, ... */);
- void _emval_call_void_method(
- EM_VAL value,
- const char* methodName,
- unsigned argCount,
- internal::TYPEID argTypes[]
- /*, ...*/);
+
+ // DO NOT call this more than once per signature. It will leak function pointer offsets!
+ GenericFunction _emval_get_method_caller(
+ unsigned argCount, // including return value
+ internal::TYPEID argTypes[]);
bool _emval_has_function(
EM_VAL value,
const char* methodName);
}
- }
- template<const char* address>
- struct symbol_registrar {
- symbol_registrar() {
- internal::_emval_register_symbol(address);
- }
- };
+ template<const char* address>
+ struct symbol_registrar {
+ symbol_registrar() {
+ internal::_emval_register_symbol(address);
+ }
+ };
+
+ template<typename ReturnType, typename... Args>
+ struct Signature {
+ typedef typename BindingType<ReturnType>::WireType (*MethodCaller)(EM_VAL value, const char* methodName, typename BindingType<Args>::WireType...);
+
+ static MethodCaller get_method_caller() {
+ static MethodCaller fp = reinterpret_cast<MethodCaller>(init_method_caller());
+ return fp;
+ }
+
+ private:
+ static GenericFunction init_method_caller() {
+ WithPolicies<>::ArgTypeList<ReturnType, Args...> args;
+ return _emval_get_method_caller(args.count, args.types);
+ }
+ };
+
+ 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();
+ auto wireType = caller(
+ handle,
+ methodName,
+ toWireType(std::forward<Args>(args))...);
+ WireDeleter<ReturnType> deleter(wireType);
+ return BindingType<ReturnType>::fromWireType(wireType);
+ }
+ };
+
+ template<typename... Args>
+ struct MethodCaller<void, Args...> {
+ static void call(EM_VAL handle, const char* methodName, Args&&... args) {
+ auto caller = Signature<void, Args...>::get_method_caller();
+ return caller(
+ handle,
+ methodName,
+ toWireType(std::forward<Args>(args))...);
+ }
+ };
+ }
#define EMSCRIPTEN_SYMBOL(name) \
static const char name##_symbol[] = #name; \
- static const symbol_registrar<name##_symbol> name##_registrar
+ static const ::emscripten::internal::symbol_registrar<name##_symbol> name##_registrar
class val {
public:
@@ -158,7 +191,7 @@ namespace emscripten {
}
bool hasOwnProperty(const char* key) const {
- return val::global("Object")["prototype"]["hasOwnProperty"].call("call", *this, val(key)).as<bool>();
+ return val::global("Object")["prototype"]["hasOwnProperty"].call<bool>("call", *this, val(key));
}
template<typename... Args>
@@ -211,45 +244,11 @@ namespace emscripten {
toWireType(std::forward<Args>(args))...));
}
- template<typename ...Args>
- val call(const char* name, Args&&... args) const {
+ template<typename ReturnValue, typename... Args>
+ ReturnValue call(const char* name, Args&&... args) const {
using namespace internal;
- WithPolicies<>::ArgTypeList<Args...> argList;
- typedef EM_VAL (*TypedCall)(
- EM_VAL,
- const char* name,
- unsigned,
- TYPEID argTypes[],
- typename BindingType<Args>::WireType...);
- TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_method);
- return val(
- typedCall(
- handle,
- name,
- argList.count,
- argList.types,
- toWireType(std::forward<Args>(args))...));
- }
-
- template<typename ...Args>
- void call_void(const char* name, Args&&... args) const {
- using namespace internal;
-
- WithPolicies<>::ArgTypeList<Args...> argList;
- typedef void (*TypedCall)(
- EM_VAL,
- const char* name,
- unsigned,
- TYPEID argTypes[],
- typename BindingType<Args>::WireType...);
- TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_void_method);
- return typedCall(
- handle,
- name,
- argList.count,
- argList.types,
- toWireType(std::forward<Args>(args))...);
+ return MethodCaller<ReturnValue, Args...>::call(handle, name, std::forward<Args>(args)...);
}
bool has_function(const char* name) const {
diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h
index 6fb15fc7..e4ddfd04 100644
--- a/system/include/emscripten/wire.h
+++ b/system/include/emscripten/wire.h
@@ -13,6 +13,8 @@
namespace emscripten {
namespace internal {
+ typedef void (*GenericFunction)();
+
typedef const struct _TYPEID* TYPEID;
// This implementation is technically not legal, as it's not
@@ -146,6 +148,7 @@ namespace emscripten {
template<>
struct BindingType<void> {
+ typedef void WireType;
};
template<>