hadrian: eliminate most of the remaining big rule enumerations
[ghc.git] / rts / StaticPtrTable.c
1 /*
2 * (c)2014 Tweag I/O
3 *
4 * The Static Pointer Table implementation.
5 *
6 * https://ghc.haskell.org/trac/ghc/wiki/StaticPointers
7 * https://ghc.haskell.org/trac/ghc/wiki/StaticPointers/ImplementationPlan
8 *
9 */
10
11 #include "StaticPtrTable.h"
12 #include "Rts.h"
13 #include "RtsUtils.h"
14 #include "Hash.h"
15 #include "StablePtr.h"
16
17 static HashTable * spt = NULL;
18
19 #if defined(THREADED_RTS)
20 static Mutex spt_lock;
21 #endif
22
23 /// Hash function for the SPT.
24 static int hashFingerprint(const HashTable *table, StgWord key) {
25 const StgWord64* ptr = (StgWord64*) key;
26 // Take half of the key to compute the hash.
27 return hashWord(table, *(ptr + 1));
28 }
29
30 /// Comparison function for the SPT.
31 static int compareFingerprint(StgWord a, StgWord b) {
32 const StgWord64* ptra = (StgWord64*) a;
33 const StgWord64* ptrb = (StgWord64*) b;
34 return *ptra == *ptrb && *(ptra + 1) == *(ptrb + 1);
35 }
36
37 void hs_spt_insert_stableptr(StgWord64 key[2], StgStablePtr *entry) {
38 // hs_spt_insert is called from constructor functions, so
39 // the SPT needs to be initialized here.
40 if (spt == NULL) {
41 spt = allocHashTable_(hashFingerprint, compareFingerprint);
42 #if defined(THREADED_RTS)
43 initMutex(&spt_lock);
44 #endif
45 }
46
47 ACQUIRE_LOCK(&spt_lock);
48 insertHashTable(spt, (StgWord)key, entry);
49 RELEASE_LOCK(&spt_lock);
50 }
51
52 void hs_spt_insert(StgWord64 key[2], void *spe_closure) {
53 // Cannot remove this indirection yet because getStablePtr()
54 // might return NULL, in which case hs_spt_lookup() returns NULL
55 // instead of the actual closure pointer.
56 StgStablePtr * entry = stgMallocBytes( sizeof(StgStablePtr)
57 , "hs_spt_insert: entry"
58 );
59 *entry = getStablePtr(spe_closure);
60 hs_spt_insert_stableptr(key, entry);
61 }
62
63 static void freeSptEntry(void* entry) {
64 freeStablePtr(*(StgStablePtr*)entry);
65 stgFree(entry);
66 }
67
68 void hs_spt_remove(StgWord64 key[2]) {
69 if (spt) {
70 ACQUIRE_LOCK(&spt_lock);
71 StgStablePtr* entry = removeHashTable(spt, (StgWord)key, NULL);
72 RELEASE_LOCK(&spt_lock);
73
74 if (entry)
75 freeSptEntry(entry);
76 }
77 }
78
79 StgPtr hs_spt_lookup(StgWord64 key1, StgWord64 key2) {
80 if (spt) {
81 ACQUIRE_LOCK(&spt_lock);
82 StgWord64 key[2] = { key1, key2 };
83 const StgStablePtr * entry = lookupHashTable(spt, (StgWord)key);
84 const StgPtr ret = entry ? deRefStablePtr(*entry) : NULL;
85 RELEASE_LOCK(&spt_lock);
86 return ret;
87 } else
88 return NULL;
89 }
90
91 int hs_spt_keys(StgPtr keys[], int szKeys) {
92 if (spt) {
93 ACQUIRE_LOCK(&spt_lock);
94 const int ret = keysHashTable(spt, (StgWord*)keys, szKeys);
95 RELEASE_LOCK(&spt_lock);
96 return ret;
97 } else
98 return 0;
99 }
100
101 int hs_spt_key_count() {
102 return spt ? keyCountHashTable(spt) : 0;
103 }
104
105 void exitStaticPtrTable() {
106 if (spt) {
107 freeHashTable(spt, freeSptEntry);
108 spt = NULL;
109 #if defined(THREADED_RTS)
110 closeMutex(&spt_lock);
111 #endif
112 }
113 }