/home/travis/build/MoarVM/MoarVM/src/6model/reprs/HashAttrStore.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "moar.h" |
2 | | |
3 | | /* This representation's function pointer table. */ |
4 | | static const MVMREPROps HashAttrStore_this_repr; |
5 | | |
6 | | /* Creates a new type object of this representation, and associates it with |
7 | | * the given HOW. */ |
8 | 0 | static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) { |
9 | 0 | MVMSTable *st = MVM_gc_allocate_stable(tc, &HashAttrStore_this_repr, HOW); |
10 | 0 |
|
11 | 0 | MVMROOT(tc, st, { |
12 | 0 | MVMObject *obj = MVM_gc_allocate_type_object(tc, st); |
13 | 0 | MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj); |
14 | 0 | st->size = sizeof(MVMHashAttrStore); |
15 | 0 | }); |
16 | 0 |
|
17 | 0 | return st->WHAT; |
18 | 0 | } |
19 | | |
20 | | /* Copies the body of one object to another. */ |
21 | 0 | static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest) { |
22 | 0 | MVMHashAttrStoreBody *src_body = (MVMHashAttrStoreBody *)src; |
23 | 0 | MVMHashAttrStoreBody *dest_body = (MVMHashAttrStoreBody *)dest; |
24 | 0 | MVMHashEntry *current, *tmp; |
25 | 0 | unsigned bucket_tmp; |
26 | 0 |
|
27 | 0 | /* NOTE: if we really wanted to, we could avoid rehashing... */ |
28 | 0 | HASH_ITER(hash_handle, src_body->hash_head, current, tmp, bucket_tmp) { |
29 | 0 | MVMHashEntry *new_entry = MVM_malloc(sizeof(MVMHashEntry)); |
30 | 0 | MVM_ASSIGN_REF(tc, &(dest_root->header), new_entry->value, current->value); |
31 | 0 | MVM_HASH_BIND(tc, dest_body->hash_head, MVM_HASH_KEY(current), new_entry); |
32 | 0 | } |
33 | 0 | } |
34 | | |
35 | | /* Adds held objects to the GC worklist. */ |
36 | 0 | static void gc_mark(MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist) { |
37 | 0 | MVMHashAttrStoreBody *body = (MVMHashAttrStoreBody *)data; |
38 | 0 | MVMHashEntry *current, *tmp; |
39 | 0 | unsigned bucket_tmp; |
40 | 0 |
|
41 | 0 | HASH_ITER(hash_handle, body->hash_head, current, tmp, bucket_tmp) { |
42 | 0 | MVM_gc_worklist_add(tc, worklist, ¤t->hash_handle.key); |
43 | 0 | MVM_gc_worklist_add(tc, worklist, ¤t->value); |
44 | 0 | } |
45 | 0 | } |
46 | | |
47 | | /* Called by the VM in order to free memory associated with this object. */ |
48 | 0 | static void gc_free(MVMThreadContext *tc, MVMObject *obj) { |
49 | 0 | MVMHashAttrStore *h = (MVMHashAttrStore *)obj; |
50 | 0 | MVM_HASH_DESTROY(tc, hash_handle, MVMHashEntry, h->body.hash_head); |
51 | 0 | } |
52 | | |
53 | | static void get_attribute(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, |
54 | | void *data, MVMObject *class_handle, MVMString *name, MVMint64 hint, |
55 | 0 | MVMRegister *result_reg, MVMuint16 kind) { |
56 | 0 | MVMHashAttrStoreBody *body = (MVMHashAttrStoreBody *)data; |
57 | 0 | if (kind == MVM_reg_obj) { |
58 | 0 | MVMHashEntry *entry; |
59 | 0 | MVM_HASH_GET(tc, body->hash_head, name, entry); |
60 | 0 | result_reg->o = entry != NULL ? entry->value : tc->instance->VMNull; |
61 | 0 | } |
62 | 0 | else { |
63 | 0 | MVM_exception_throw_adhoc(tc, |
64 | 0 | "HashAttrStore representation does not support native attribute storage"); |
65 | 0 | } |
66 | 0 | } |
67 | | |
68 | | static void bind_attribute(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, |
69 | | void *data, MVMObject *class_handle, MVMString *name, MVMint64 hint, |
70 | 0 | MVMRegister value_reg, MVMuint16 kind) { |
71 | 0 | MVMHashAttrStoreBody *body = (MVMHashAttrStoreBody *)data; |
72 | 0 | if (kind == MVM_reg_obj) { |
73 | 0 | MVMHashEntry *entry; |
74 | 0 | MVM_HASH_GET(tc, body->hash_head, name, entry); |
75 | 0 | if (!entry) { |
76 | 0 | entry = MVM_malloc(sizeof(MVMHashEntry)); |
77 | 0 | MVM_ASSIGN_REF(tc, &(root->header), entry->value, value_reg.o); |
78 | 0 | MVM_HASH_BIND(tc, body->hash_head, name, entry); |
79 | 0 | MVM_gc_write_barrier(tc, &(root->header), &(name->common.header)); |
80 | 0 | } |
81 | 0 | else { |
82 | 0 | MVM_ASSIGN_REF(tc, &(root->header), entry->value, value_reg.o); |
83 | 0 | } |
84 | 0 | } |
85 | 0 | else { |
86 | 0 | MVM_exception_throw_adhoc(tc, |
87 | 0 | "HashAttrStore representation does not support native attribute storage"); |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | 0 | static MVMint64 is_attribute_initialized(MVMThreadContext *tc, MVMSTable *st, void *data, MVMObject *class_handle, MVMString *name, MVMint64 hint) { |
92 | 0 | MVMHashAttrStoreBody *body = (MVMHashAttrStoreBody *)data; |
93 | 0 | MVMHashEntry *entry; |
94 | 0 | MVM_HASH_GET(tc, body->hash_head, name, entry); |
95 | 0 | return entry != NULL; |
96 | 0 | } |
97 | | |
98 | 0 | static MVMint64 hint_for(MVMThreadContext *tc, MVMSTable *st, MVMObject *class_handle, MVMString *name) { |
99 | 0 | return MVM_NO_HINT; |
100 | 0 | } |
101 | | |
102 | | |
103 | | static const MVMStorageSpec storage_spec = { |
104 | | MVM_STORAGE_SPEC_REFERENCE, /* inlineable */ |
105 | | 0, /* bits */ |
106 | | 0, /* align */ |
107 | | MVM_STORAGE_SPEC_BP_NONE, /* boxed_primitive */ |
108 | | 0, /* can_box */ |
109 | | 0, /* is_unsigned */ |
110 | | }; |
111 | | |
112 | | |
113 | | /* Gets the storage specification for this representation. */ |
114 | 0 | static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) { |
115 | 0 | return &storage_spec; |
116 | 0 | } |
117 | | |
118 | | /* Compose the representation. */ |
119 | 0 | static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info) { |
120 | 0 | /* Nothing to do for this REPR. */ |
121 | 0 | } |
122 | | |
123 | | /* Set the size of the STable. */ |
124 | 0 | static void deserialize_stable_size(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) { |
125 | 0 | st->size = sizeof(MVMHashAttrStore); |
126 | 0 | } |
127 | | |
128 | | /* Initializes the representation. */ |
129 | 144 | const MVMREPROps * MVMHashAttrStore_initialize(MVMThreadContext *tc) { |
130 | 144 | return &HashAttrStore_this_repr; |
131 | 144 | } |
132 | | |
133 | | static const MVMREPROps HashAttrStore_this_repr = { |
134 | | type_object_for, |
135 | | MVM_gc_allocate_object, |
136 | | NULL, /* initialize */ |
137 | | copy_to, |
138 | | { |
139 | | get_attribute, |
140 | | bind_attribute, |
141 | | hint_for, |
142 | | is_attribute_initialized, |
143 | | MVM_REPR_DEFAULT_ATTRIBUTE_AS_ATOMIC |
144 | | }, /* attr_funcs */ |
145 | | MVM_REPR_DEFAULT_BOX_FUNCS, |
146 | | MVM_REPR_DEFAULT_POS_FUNCS, |
147 | | MVM_REPR_DEFAULT_ASS_FUNCS, |
148 | | MVM_REPR_DEFAULT_ELEMS, |
149 | | get_storage_spec, |
150 | | NULL, /* change_type */ |
151 | | NULL, /* serialize */ |
152 | | NULL, /* deserialize */ |
153 | | NULL, /* serialize_repr_data */ |
154 | | NULL, /* deserialize_repr_data */ |
155 | | deserialize_stable_size, |
156 | | gc_mark, |
157 | | gc_free, |
158 | | NULL, /* gc_cleanup */ |
159 | | NULL, /* gc_mark_repr_data */ |
160 | | NULL, /* gc_free_repr_data */ |
161 | | compose, |
162 | | NULL, /* spesh */ |
163 | | "HashAttrStore", /* name */ |
164 | | MVM_REPR_ID_HashAttrStore, |
165 | | NULL, /* unmanaged_size */ |
166 | | NULL, /* describe_refs */ |
167 | | }; |