| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #pragma once | 
| 2 |  |  |  |  |  |  | #include | 
| 3 |  |  |  |  |  |  | #include | 
| 4 |  |  |  |  |  |  | #include | 
| 5 |  |  |  |  |  |  | #include | 
| 6 |  |  |  |  |  |  | #include | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | namespace panda { | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | namespace detail { namespace cast { | 
| 11 |  |  |  |  |  |  | typedef std::map DynCastCacheMap; | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | template | 
| 14 | 0 |  |  |  |  |  | DynCastCacheMap& get_map () { | 
| 15 |  |  |  |  |  |  | thread_local DynCastCacheMap* map; | 
| 16 | 0 | 0 |  |  |  |  | if (!map) { | 
| 17 | 0 | 0 |  |  |  |  | thread_local DynCastCacheMap _map; | 
| 18 | 0 |  |  |  |  |  | map = &_map; | 
| 19 |  |  |  |  |  |  | } | 
| 20 | 0 |  |  |  |  |  | return *map; | 
| 21 |  |  |  |  |  |  | } | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | constexpr const ptrdiff_t INCORRECT_PTRDIFF = PTRDIFF_MAX; | 
| 24 |  |  |  |  |  |  | }} | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | template | 
| 27 | 0 |  |  |  |  |  | DERIVED_PTR dyn_cast (BASE* obj) { | 
| 28 |  |  |  |  |  |  | using namespace detail::cast; | 
| 29 |  |  |  |  |  |  | using DERIVED = typename std::remove_pointer::type; | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | if (std::is_same::value) return (DERIVED_PTR)((void*)obj); | 
| 32 | 0 | 0 |  |  |  |  | if (!obj) return NULL; | 
| 33 |  |  |  |  |  |  |  | 
| 34 | 0 | 0 |  |  |  |  | intptr_t key = (intptr_t)typeid(*obj).name(); | 
| 35 | 0 |  |  |  |  |  | auto&    map = get_map(); | 
| 36 |  |  |  |  |  |  | //auto& map = DynCastCache::map; | 
| 37 | 0 | 0 |  |  |  |  | DynCastCacheMap::iterator it = map.find(key); | 
| 38 | 0 | 0 |  |  |  |  | if (it != map.end()) | 
| 39 | 0 | 0 |  |  |  |  | return it->second != INCORRECT_PTRDIFF ? reinterpret_cast((char*)obj - it->second) : NULL; | 
| 40 | 0 | 0 |  |  |  |  | DERIVED* ret = dynamic_cast(obj); | 
| 41 | 0 | 0 |  |  |  |  | if (ret) map[key] = (char*)obj - (char*)ret; | 
|  |  | 0 |  |  |  |  |  | 
| 42 | 0 | 0 |  |  |  |  | else map[key] = INCORRECT_PTRDIFF; | 
| 43 | 0 |  |  |  |  |  | return ret; | 
| 44 |  |  |  |  |  |  | } | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | template | 
| 47 |  |  |  |  |  |  | DERIVED_REF dyn_cast (BASE& obj) { | 
| 48 |  |  |  |  |  |  | using namespace detail::cast; | 
| 49 |  |  |  |  |  |  | using DERIVED = typename std::remove_reference::type; | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | if (std::is_same::value) return reinterpret_cast(obj); | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | intptr_t key = (intptr_t)typeid(obj).name(); | 
| 54 |  |  |  |  |  |  | auto&    map = get_map(); | 
| 55 |  |  |  |  |  |  | DynCastCacheMap::iterator it = map.find(key); | 
| 56 |  |  |  |  |  |  | if (it != map.end() && it->second != INCORRECT_PTRDIFF) | 
| 57 |  |  |  |  |  |  | return *(reinterpret_cast((char*)&obj - it->second)); | 
| 58 |  |  |  |  |  |  | // dont cache fails, as exceptions are much slower than dynamic_cast, let it always fall here | 
| 59 |  |  |  |  |  |  | DERIVED& ret = dynamic_cast(obj); | 
| 60 |  |  |  |  |  |  | map[key] = (char*)&obj - (char*)&ret; | 
| 61 |  |  |  |  |  |  | return ret; | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | } |