/** * Returns the ReferentEntry for the specified object or creates one and adds * it to the referents hash if none exists. referentsLock MUST be held. */ static ReferentEntry* getReferentEntryForObject(Env* env, Object* o) { void* key = (void*) GC_HIDE_POINTER(o); // Hide the pointer from the GC so that the key doesn't prevent the object from being GCed. ReferentEntry* referentEntry; HASH_FIND_PTR(referents, &key, referentEntry); if (!referentEntry) { // Object is not in the hashtable. Add it. referentEntry = allocateMemoryOfKind(env, sizeof(ReferentEntry), referentEntryGCKind); if (!referentEntry) return NULL; // OOM thrown referentEntry->key = key; HASH_ADD_PTR(referents, key, referentEntry); } return referentEntry; }
/** * Adds a string to the cache of interned string. The string must not already be * interned. The internedStringsLock MUST be held when calling this function. */ static jboolean addInternedString(Env* env, const char* s, Object* string) { CacheEntry* cacheEntry = allocateMemoryOfKind(env, sizeof(CacheEntry), cacheEntryGCKind); if (!cacheEntry) { return FALSE; } cacheEntry->key = s; cacheEntry->string = string; HASH_ADD_KEYPTR(hh, internedStrings, cacheEntry->key, strlen(cacheEntry->key), cacheEntry); // prune the cache to MAX_CACHE_SIZE if (HASH_COUNT(internedStrings) >= MAX_CACHE_SIZE) { CacheEntry* tmpEntry; HASH_ITER(hh, internedStrings, cacheEntry, tmpEntry) { // prune the first entry (loop is based on insertion order so this deletes the oldest item) HASH_DELETE(hh, internedStrings, cacheEntry); break; }