From 2bbdb0cd396d785a9587bc776d699283c1902ff7 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Mon, 31 Mar 2014 22:43:28 -0700 Subject: embind doesn't always need the full std::type_info record. if EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0, then use a lighter type identifier. This shaves 175 KB off of our engine's minified JavaScript. --- system/include/emscripten/bind.h | 2 +- system/include/emscripten/wire.h | 64 +++++++++++++++++++++++++++++++++------- system/lib/embind/bind.cpp | 38 ++++++++++++++---------- 3 files changed, 77 insertions(+), 27 deletions(-) (limited to 'system') diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 872f279b..b4c5004e 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -813,7 +813,7 @@ namespace emscripten { // NOTE: this returns the class type, not the pointer type template inline TYPEID getActualType(T* ptr) { - return reinterpret_cast(&typeid(*ptr)); + return getLightTypeID(*ptr); }; } diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h index 05b3ac33..c20e2f55 100644 --- a/system/include/emscripten/wire.h +++ b/system/include/emscripten/wire.h @@ -15,22 +15,66 @@ #define EMSCRIPTEN_ALWAYS_INLINE __attribute__((always_inline)) namespace emscripten { + #ifndef EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES + #define EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES 1 + #endif + + + #if EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES + constexpr bool has_unbound_type_names = true; + #else + constexpr bool has_unbound_type_names = false; + #endif + namespace internal { typedef void (*GenericFunction)(); - typedef const struct _TYPEID* TYPEID; + typedef const struct _TYPEID {}* TYPEID; + + + // We don't need the full std::type_info implementation. We + // just need a unique identifier per type and polymorphic type + // identification. + + template + struct CanonicalizedID { + static TYPEID get() { + static _TYPEID c; + return &c; + } + }; + + template + struct Canonicalized { + typedef typename std::remove_cv::type>::type type; + }; + + template + struct LightTypeID { + static TYPEID get() { + typedef typename Canonicalized::type C; + if (has_unbound_type_names || std::is_polymorphic::value) { + return reinterpret_cast(&typeid(C)); + } else { + return CanonicalizedID::get(); + } + } + }; + + template + const TYPEID getLightTypeID(const T& value) { + typedef typename Canonicalized::type C; + if (has_unbound_type_names || std::is_polymorphic::value) { + return reinterpret_cast(&typeid(value)); + } else { + return LightTypeID::get(); + } + } - // This implementation is technically not legal, as it's not - // required that two calls to typeid produce the same exact - // std::type_info instance. That said, it's likely to work - // given Emscripten compiles everything into one binary. - // Should it not work in the future: replace TypeID with an - // int, and store all TypeInfo we see in a map, allocating new - // TypeIDs as we add new items to the map. template struct TypeID { static TYPEID get() { - return reinterpret_cast(&typeid(T)); + return LightTypeID::get(); } }; @@ -53,7 +97,7 @@ namespace emscripten { template struct TypeID> { static TYPEID get() { - return reinterpret_cast(&typeid(T*)); + return LightTypeID::get(); } }; diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp index f43d1ea1..37918050 100644 --- a/system/lib/embind/bind.cpp +++ b/system/lib/embind/bind.cpp @@ -14,26 +14,32 @@ using namespace emscripten; extern "C" { const char* __attribute__((used)) __getTypeName(const std::type_info* ti) { + if (has_unbound_type_names) { #ifdef USE_CXA_DEMANGLE - int stat; - char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat); - if (stat == 0 && demangled) { - return demangled; - } + int stat; + char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat); + if (stat == 0 && demangled) { + return demangled; + } - switch (stat) { - case -1: - return strdup(""); - case -2: - return strdup(""); - case -3: - return strdup(""); - default: - return strdup(""); - } + switch (stat) { + case -1: + return strdup(""); + case -2: + return strdup(""); + case -3: + return strdup(""); + default: + return strdup(""); + } #else - return strdup(ti->name()); + return strdup(ti->name()); #endif + } else { + char str[80]; + sprintf(str, "%p", ti); + return strdup(str); + } } } -- cgit v1.2.3-70-g09d2