/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); |