File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/XS/libpanda.x/i/panda/cast.h
Criterion Covered Total %
statement 15 16 93.7
branch 12 22 54.5
condition n/a
subroutine n/a
pod n/a
total 27 38 71.0


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 316           DynCastCacheMap& get_map () {
15             thread_local DynCastCacheMap* map;
16 316 100         if (!map) {
17 85 50         thread_local struct { DynCastCacheMap map; } wrp;
18 17           map = &wrp.map;
19             }
20 316           return *map;
21             }
22              
23             constexpr const ptrdiff_t INCORRECT_PTRDIFF = PTRDIFF_MAX;
24             }}
25              
26             template
27 632           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 316 50         if (!obj) return NULL;
33              
34 316 50         intptr_t key = (intptr_t)typeid(*obj).name();
35 316           auto& map = get_map();
36             //auto& map = DynCastCache::map;
37 316 50         DynCastCacheMap::iterator it = map.find(key);
38 316 100         if (it != map.end())
39 299 50         return it->second != INCORRECT_PTRDIFF ? reinterpret_cast((char*)obj - it->second) : NULL;
40 17 50         DERIVED* ret = dynamic_cast(obj);
41 17 50         if (ret) map[key] = (char*)obj - (char*)ret;
    50          
42 0 0         else map[key] = INCORRECT_PTRDIFF;
43 316           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             }