Coverage Report

Created: 2018-07-03 15:31

/home/travis/build/MoarVM/MoarVM/src/6model/reprs/MVMMultiCache.h
Line
Count
Source
1
/* The multi-dispatch cache is a set of trees keyed on the address of
2
 * an interned callsite. The tree is represented as  an array of triples,
3
 * each having the form (action, match, no-match). The match and no-match
4
 * are either:
5
 *   * Positive, and an index into the array for what to check next
6
 *   * Zero, meaning we failed to find a match
7
 *   * Negative, meaning we found a match, and should negate the index
8
 *     to get a the resulting candidate
9
 *
10
 * The first MVM_MULTICACHE_HASH_SIZE entries in the array are tree roots.
11
 * They are all set to have a NULL callsite matcher when there's no tree
12
 * there, implying an immediate match failure.
13
 *
14
 * The matcher starts in callsite match mode, meaning that the matcher is
15
 * the memory address of a callsite. This naturally handles hash collisions.
16
 *
17
 * Once we have a matching callsite, it flips into argument matching mode.
18
 * The lowermost bits of the action represent the index into the arguments
19
 * buffer for the argument we need to test. The next bit is for concrete or
20
 * not. The bit after it is rw or not. The remaining bits correspond to the
21
 * STable's type cache ID.
22
 *
23
 * The construction of the tree is such that we only have to test the first
24
 * argument until we get a match, then the second, etc. This means that common
25
 * prefixes are factored out, keeping the tree smaller. The use of a single
26
 * block of memory is also aimed at getting good CPU cache hit rates.
27
 *
28
 * The tree array is immutable, and so can safely be read by many threads, and
29
 * kept in thier CPU caches. Upon a new entry, the cache will be copied, and the
30
 * tweaks made. The cache head pointer will then be set to the new cache, and the
31
 * old cache memory scheduled for freeeing at the next safepoint.
32
 */
33
34
/* A node in the cache. */
35
struct MVMMultiCacheNode {
36
    union {
37
        MVMCallsite *cs;
38
        MVMuint64 arg_match;
39
    } action;
40
    MVMint32 match;
41
    MVMint32 no_match;
42
};
43
44
/* Body of a multi-dispatch cache. */
45
struct MVMMultiCacheBody {
46
    /* Pointer to the an array of nodes, which we can initially index
47
     * into using a hahsed calsite. Replaced in whole whenever there is
48
     * a change. */
49
    MVMMultiCacheNode *node_hash_head;
50
51
    /* Array of results we may return from the cache. Note that this is
52
     * replaced entirely whenever we update the cache. It is append only,
53
     * and so will be valid for older versions of the cache too. We must
54
     * replace this and do a memory barrier before replacing node_hash_head
55
     * with its new version on update. Conversely, readers must read the
56
     * node_hash_head and *then* read results here, so it will always have
57
     * been udpated in time. */
58
    MVMObject **results;
59
60
    /* The number of results, so we can GC mark and free. */
61
    size_t num_results;
62
63
    /* The amount of memory the cache uses. Used for freeing with the fixed
64
     * size allocator. */
65
    size_t cache_memory_size;
66
};
67
68
/* Hash table size. Must be a power of 2. */
69
160k
#define MVM_MULTICACHE_HASH_SIZE    8
70
155k
#define MVM_MULTICACHE_HASH_FILTER  (MVM_MULTICACHE_HASH_SIZE - 1)
71
72
struct MVMMultiCache {
73
    MVMObject common;
74
    MVMMultiCacheBody body;
75
};
76
77
/* Function for REPR setup. */
78
const MVMREPROps * MVMMultiCache_initialize(MVMThreadContext *tc);
79
80
/* Functions relating to multi-dispatch cache usage. */
81
MVMObject * MVM_multi_cache_add(MVMThreadContext *tc, MVMObject *cache, MVMObject *capture, MVMObject *result);
82
MVMObject * MVM_multi_cache_find(MVMThreadContext *tc, MVMObject *cache, MVMObject *capture);
83
MVMObject * MVM_multi_cache_find_callsite_args(MVMThreadContext *tc, MVMObject *cache,
84
    MVMCallsite *cs, MVMRegister *args);
85
MVMObject * MVM_multi_cache_find_spesh(MVMThreadContext *tc, MVMObject *cache, MVMSpeshCallInfo *arg_info, MVMSpeshStatsType *type_tuple);