rts: Handle SMALL_MUT_ARR_PTRS in checkClosure
[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 "Stable.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 key[2]) {
80 if (spt) {
81 ACQUIRE_LOCK(&spt_lock);
82 const StgStablePtr * entry = lookupHashTable(spt, (StgWord)key);
83 const StgPtr ret = entry ? deRefStablePtr(*entry) : NULL;
84 RELEASE_LOCK(&spt_lock);
85 return ret;
86 } else
87 return NULL;
88 }
89
90 int hs_spt_keys(StgPtr keys[], int szKeys) {
91 if (spt) {
92 ACQUIRE_LOCK(&spt_lock);
93 const int ret = keysHashTable(spt, (StgWord*)keys, szKeys);
94 RELEASE_LOCK(&spt_lock);
95 return ret;
96 } else
97 return 0;
98 }
99
100 int hs_spt_key_count() {
101 return spt ? keyCountHashTable(spt) : 0;
102 }
103
104 void exitStaticPtrTable() {
105 if (spt) {
106 freeHashTable(spt, freeSptEntry);
107 spt = NULL;
108 #if defined(THREADED_RTS)
109 closeMutex(&spt_lock);
110 #endif
111 }
112 }