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 16 17 94.1
branch 96 176 54.5
condition n/a
subroutine n/a
pod n/a
total 112 193 58.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 437           DynCastCacheMap& get_map () {
15             thread_local DynCastCacheMap* map;
16 437 100         if (!map) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
17 380 50         thread_local struct { DynCastCacheMap map; } wrp;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
18 76           map = &wrp.map;
19             }
20 437           return *map;
21             }
22              
23             constexpr const ptrdiff_t INCORRECT_PTRDIFF = PTRDIFF_MAX;
24             }}
25              
26             template
27 1774           DERIVED_PTR dyn_cast (BASE* obj) {
28             using namespace detail::cast;
29             using DERIVED = typename std::remove_pointer::type;
30              
31 900           if (std::is_same::value) return (DERIVED_PTR)((void*)obj);
32 437 50         if (!obj) return NULL;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
33              
34 437 50         intptr_t key = (intptr_t)typeid(*obj).name();
    50          
    50          
    50          
    50          
    50          
    50          
    50          
35 437           auto& map = get_map();
36             //auto& map = DynCastCache::map;
37 437 50         DynCastCacheMap::iterator it = map.find(key);
    50          
    50          
    50          
    50          
    50          
    50          
    50          
38 437 100         if (it != map.end())
    100          
    100          
    100          
    100          
    100          
    100          
    100          
39 361 50         return it->second != INCORRECT_PTRDIFF ? reinterpret_cast((char*)obj - it->second) : NULL;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
40 76 50         DERIVED* ret = dynamic_cast(obj);
    50          
    50          
    50          
    50          
    50          
    50          
    50          
41 76 50         if (ret) map[key] = (char*)obj - (char*)ret;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
42 0 0         else map[key] = INCORRECT_PTRDIFF;
    0          
    0          
    0          
    0          
    0          
    0          
    0          
43 437           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             }