/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 | 4.31k | MVMuint64 MVM_gc_object_id(MVMThreadContext *tc, MVMObject *obj) { |
6 | 4.31k | MVMuint64 id; |
7 | 4.31k | |
8 | 4.31k | /* If it's already in the old generation, just use memory address, as |
9 | 4.31k | * gen2 objects never move. */ |
10 | 4.31k | if (obj->header.flags & MVM_CF_SECOND_GEN) { |
11 | 230 | id = (MVMuint64)obj; |
12 | 230 | } |
13 | 4.31k | |
14 | 4.31k | /* Otherwise, see if we already have a persistent object ID. */ |
15 | 4.08k | else { |
16 | 4.08k | MVMObjectId *entry; |
17 | 4.08k | uv_mutex_lock(&tc->instance->mutex_object_ids); |
18 | 4.08k | if (obj->header.flags & MVM_CF_HAS_OBJECT_ID) { |
19 | 3.73k | /* Has one, so just look up by address in the hash ID hash. */ |
20 | 3.73k | HASH_FIND(hash_handle, tc->instance->object_ids, (void *)&obj, |
21 | 3.73k | sizeof(MVMObject *), entry); |
22 | 3.73k | } |
23 | 349 | else { |
24 | 349 | /* Hasn't got one; allocate it a place in gen2 and make an entry |
25 | 349 | * in the persistent object ID hash. */ |
26 | 349 | entry = MVM_calloc(1, sizeof(MVMObjectId)); |
27 | 349 | entry->current = obj; |
28 | 349 | entry->gen2_addr = MVM_gc_gen2_allocate_zeroed(tc->gen2, obj->header.size); |
29 | 349 | HASH_ADD_KEYPTR(hash_handle, tc->instance->object_ids, &(entry->current), |
30 | 349 | sizeof(MVMObject *), entry); |
31 | 349 | obj->header.flags |= MVM_CF_HAS_OBJECT_ID; |
32 | 349 | } |
33 | 4.08k | id = (MVMuint64)entry->gen2_addr; |
34 | 4.08k | uv_mutex_unlock(&tc->instance->mutex_object_ids); |
35 | 4.08k | } |
36 | 4.31k | |
37 | 4.31k | return id; |
38 | 4.31k | } |
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 | 145 | void * MVM_gc_object_id_use_allocation(MVMThreadContext *tc, MVMCollectable *item) { |
44 | 145 | MVMObjectId *entry; |
45 | 145 | void *addr; |
46 | 145 | uv_mutex_lock(&tc->instance->mutex_object_ids); |
47 | 145 | HASH_FIND(hash_handle, tc->instance->object_ids, (void *)&item, sizeof(MVMObject *), entry); |
48 | 145 | addr = entry->gen2_addr; |
49 | 145 | HASH_DELETE(hash_handle, tc->instance->object_ids, entry); |
50 | 145 | MVM_free(entry); |
51 | 145 | item->flags ^= MVM_CF_HAS_OBJECT_ID; |
52 | 145 | uv_mutex_unlock(&tc->instance->mutex_object_ids); |
53 | 145 | return addr; |
54 | 145 | } |
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 | } |