/home/travis/build/MoarVM/MoarVM/src/gc/objectid.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "moar.h" |
2 | | |
3 | | /* Gets a stable identifier for an object, which will not change even if the |
4 | | * GC moves the object. */ |
5 | 3.67k | MVMuint64 MVM_gc_object_id(MVMThreadContext *tc, MVMObject *obj) { |
6 | 3.67k | MVMuint64 id; |
7 | 3.67k | |
8 | 3.67k | /* If it's already in the old generation, just use memory address, as |
9 | 3.67k | * gen2 objects never move. */ |
10 | 3.67k | if (obj->header.flags & MVM_CF_SECOND_GEN) { |
11 | 252 | id = (MVMuint64)obj; |
12 | 252 | } |
13 | 3.67k | |
14 | 3.67k | /* Otherwise, see if we already have a persistent object ID. */ |
15 | 3.42k | else { |
16 | 3.42k | MVMObjectId *entry; |
17 | 3.42k | uv_mutex_lock(&tc->instance->mutex_object_ids); |
18 | 3.42k | if (obj->header.flags & MVM_CF_HAS_OBJECT_ID) { |
19 | 3.12k | /* Has one, so just look up by address in the hash ID hash. */ |
20 | 3.12k | HASH_FIND(hash_handle, tc->instance->object_ids, (void *)&obj, |
21 | 3.12k | sizeof(MVMObject *), entry); |
22 | 3.12k | } |
23 | 298 | else { |
24 | 298 | /* Hasn't got one; allocate it a place in gen2 and make an entry |
25 | 298 | * in the persistent object ID hash. */ |
26 | 298 | entry = MVM_calloc(1, sizeof(MVMObjectId)); |
27 | 298 | entry->current = obj; |
28 | 298 | entry->gen2_addr = MVM_gc_gen2_allocate_zeroed(tc->gen2, obj->header.size); |
29 | 298 | HASH_ADD_KEYPTR(hash_handle, tc->instance->object_ids, &(entry->current), |
30 | 298 | sizeof(MVMObject *), entry); |
31 | 298 | obj->header.flags |= MVM_CF_HAS_OBJECT_ID; |
32 | 298 | } |
33 | 3.42k | id = (MVMuint64)entry->gen2_addr; |
34 | 3.42k | uv_mutex_unlock(&tc->instance->mutex_object_ids); |
35 | 3.42k | } |
36 | 3.67k | |
37 | 3.67k | return id; |
38 | 3.67k | } |
39 | | |
40 | | /* If an object with an entry here lives long enough to be promoted to gen2, |
41 | | * this removes the hash entry for it and returns the pre-allocated gen2 |
42 | | * address. */ |
43 | 108 | void * MVM_gc_object_id_use_allocation(MVMThreadContext *tc, MVMCollectable *item) { |
44 | 108 | MVMObjectId *entry; |
45 | 108 | void *addr; |
46 | 108 | uv_mutex_lock(&tc->instance->mutex_object_ids); |
47 | 108 | HASH_FIND(hash_handle, tc->instance->object_ids, (void *)&item, sizeof(MVMObject *), entry); |
48 | 108 | addr = entry->gen2_addr; |
49 | 108 | HASH_DELETE(hash_handle, tc->instance->object_ids, entry); |
50 | 108 | MVM_free(entry); |
51 | 108 | item->flags ^= MVM_CF_HAS_OBJECT_ID; |
52 | 108 | uv_mutex_unlock(&tc->instance->mutex_object_ids); |
53 | 108 | return addr; |
54 | 108 | } |
55 | | |
56 | | /* Clears hash entry for a persistent object ID when an object dies in the |
57 | | * nursery. */ |
58 | 0 | void MVM_gc_object_id_clear(MVMThreadContext *tc, MVMCollectable *item) { |
59 | 0 | MVMObjectId *entry; |
60 | 0 | uv_mutex_lock(&tc->instance->mutex_object_ids); |
61 | 0 | HASH_FIND(hash_handle, tc->instance->object_ids, (void *)&item, sizeof(MVMObject *), entry); |
62 | 0 | HASH_DELETE(hash_handle, tc->instance->object_ids, entry); |
63 | 0 | MVM_free(entry); |
64 | 0 | uv_mutex_unlock(&tc->instance->mutex_object_ids); |
65 | 0 | } |