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