/home/travis/build/MoarVM/MoarVM/src/6model/reprs/MVMStaticFrame.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 MVMStaticFrame_this_repr; |
5 | | |
6 | | /* Creates a new type object of this representation, and associates it with |
7 | | * the given HOW. Also sets the invocation protocol handler in the STable. */ |
8 | 144 | static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) { |
9 | 144 | MVMSTable *st = MVM_gc_allocate_stable(tc, &MVMStaticFrame_this_repr, HOW); |
10 | 144 | |
11 | 144 | MVMROOT(tc, st, { |
12 | 144 | MVMObject *obj = MVM_gc_allocate_type_object(tc, st); |
13 | 144 | MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj); |
14 | 144 | st->size = sizeof(MVMStaticFrame); |
15 | 144 | }); |
16 | 144 | |
17 | 144 | return st->WHAT; |
18 | 144 | } |
19 | | |
20 | | /* Copies the body of one object to another. */ |
21 | 1.53k | static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest) { |
22 | 1.53k | MVMStaticFrameBody *src_body = (MVMStaticFrameBody *)src; |
23 | 1.53k | MVMStaticFrameBody *dest_body = (MVMStaticFrameBody *)dest; |
24 | 1.53k | |
25 | 1.53k | if (!src_body->fully_deserialized) |
26 | 0 | MVM_exception_throw_adhoc(tc, "Can only clone a fully deserialized MVMFrame"); |
27 | 1.53k | |
28 | 1.53k | dest_body->orig_bytecode = src_body->orig_bytecode; |
29 | 1.53k | dest_body->bytecode_size = src_body->bytecode_size; |
30 | 1.53k | if (src_body->bytecode == src_body->orig_bytecode) { |
31 | 1.53k | /* Easy - the source MVMStaticFrameBody doesn't own the memory. */ |
32 | 1.53k | dest_body->bytecode = src_body->bytecode; |
33 | 1.53k | } |
34 | 0 | else { |
35 | 0 | /* We're going to need to make a copy, in case the source object gets |
36 | 0 | GC'd before we do, and so they free memory we point to. */ |
37 | 0 | /* If this gets to be a resource hog, then implement something more |
38 | 0 | sophisticated. The easiest thing would be to bump the allocated size |
39 | 0 | and value stored in bytecode by sizeof(MVMuint64), and use the extra |
40 | 0 | space to store a reference count. */ |
41 | 0 | dest_body->bytecode = MVM_malloc(src_body->bytecode_size); |
42 | 0 | memcpy(dest_body->bytecode, src_body->bytecode, src_body->bytecode_size); |
43 | 0 | } |
44 | 1.53k | |
45 | 1.53k | MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->cu, src_body->cu); |
46 | 1.53k | MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->cuuid, src_body->cuuid); |
47 | 1.53k | MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->name, src_body->name); |
48 | 1.53k | MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->static_code, src_body->static_code); |
49 | 1.53k | |
50 | 1.53k | dest_body->num_locals = src_body->num_locals; |
51 | 1.53k | dest_body->num_lexicals = src_body->num_lexicals; |
52 | 1.53k | { |
53 | 1.53k | MVMuint16 *local_types = MVM_malloc(sizeof(MVMuint16) * src_body->num_locals); |
54 | 1.53k | MVMuint16 *lexical_types = MVM_malloc(sizeof(MVMuint16) * src_body->num_lexicals); |
55 | 1.53k | memcpy(local_types, src_body->local_types, sizeof(MVMuint16) * src_body->num_locals); |
56 | 1.53k | if (src_body->num_lexicals) |
57 | 0 | memcpy(lexical_types, src_body->lexical_types, |
58 | 0 | sizeof(MVMuint16) * src_body->num_lexicals); |
59 | 1.53k | dest_body->local_types = local_types; |
60 | 1.53k | dest_body->lexical_types = lexical_types; |
61 | 1.53k | } |
62 | 1.53k | { |
63 | 1.53k | MVMLexicalRegistry *current, *tmp; |
64 | 1.53k | unsigned bucket_tmp; |
65 | 1.53k | |
66 | 1.53k | /* NOTE: if we really wanted to, we could avoid rehashing... */ |
67 | 1.53k | HASH_ITER(hash_handle, src_body->lexical_names, current, tmp, bucket_tmp) { |
68 | 0 | MVMLexicalRegistry *new_entry = MVM_malloc(sizeof(MVMLexicalRegistry)); |
69 | 0 | /* don't need to clone the string */ |
70 | 0 | MVM_ASSIGN_REF(tc, &(dest_root->header), new_entry->key, current->key); |
71 | 0 | new_entry->value = current->value; |
72 | 0 | MVM_HASH_BIND(tc, dest_body->lexical_names, current->key, new_entry); |
73 | 0 | } |
74 | 1.53k | } |
75 | 1.53k | |
76 | 1.53k | /* Static environment needs to be copied, and any objects WB'd. */ |
77 | 1.53k | if (src_body->env_size) { |
78 | 0 | MVMuint16 *type_map = src_body->lexical_types; |
79 | 0 | MVMuint16 count = src_body->num_lexicals; |
80 | 0 | MVMuint16 i; |
81 | 0 |
|
82 | 0 | dest_body->static_env = MVM_malloc(src_body->env_size); |
83 | 0 | memcpy(dest_body->static_env, src_body->static_env, src_body->env_size); |
84 | 0 | dest_body->static_env_flags = MVM_malloc(src_body->num_lexicals); |
85 | 0 | memcpy(dest_body->static_env_flags, src_body->static_env_flags, src_body->num_lexicals); |
86 | 0 |
|
87 | 0 | for (i = 0; i < count; i++) { |
88 | 0 | if (type_map[i] == MVM_reg_str) { |
89 | 0 | MVM_gc_write_barrier(tc, (MVMCollectable *)dest_root, (MVMCollectable *)dest_body->static_env[i].s); |
90 | 0 | } |
91 | 0 | else if (type_map[i] == MVM_reg_obj) { |
92 | 0 | MVM_gc_write_barrier(tc, (MVMCollectable *)dest_root, (MVMCollectable *)dest_body->static_env[i].o); |
93 | 0 | } |
94 | 0 | } |
95 | 0 | } |
96 | 1.53k | dest_body->env_size = src_body->env_size; |
97 | 1.53k | dest_body->work_size = src_body->work_size; |
98 | 1.53k | |
99 | 1.53k | if (src_body->outer) |
100 | 1.53k | MVM_ASSIGN_REF(tc, &(dest_root->header), dest_body->outer, src_body->outer); |
101 | 1.53k | |
102 | 1.53k | dest_body->num_handlers = src_body->num_handlers; |
103 | 1.53k | dest_body->handlers = MVM_malloc(src_body->num_handlers * sizeof(MVMFrameHandler)); |
104 | 1.53k | if (src_body->num_handlers) |
105 | 425 | memcpy(dest_body->handlers, src_body->handlers, |
106 | 425 | src_body->num_handlers * sizeof(MVMFrameHandler)); |
107 | 1.53k | dest_body->instrumentation_level = 0; |
108 | 1.53k | dest_body->num_annotations = src_body->num_annotations; |
109 | 1.53k | dest_body->annotations_data = src_body->annotations_data; |
110 | 1.53k | dest_body->fully_deserialized = 1; |
111 | 1.53k | } |
112 | | |
113 | | /* Adds held objects to the GC worklist. */ |
114 | 3.62k | static void gc_mark(MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist) { |
115 | 3.62k | MVMStaticFrameBody *body = (MVMStaticFrameBody *)data; |
116 | 3.62k | MVMLexicalRegistry *current, *tmp; |
117 | 3.62k | unsigned bucket_tmp; |
118 | 3.62k | |
119 | 3.62k | /* mvmobjects */ |
120 | 3.62k | MVM_gc_worklist_add(tc, worklist, &body->cu); |
121 | 3.62k | MVM_gc_worklist_add(tc, worklist, &body->cuuid); |
122 | 3.62k | MVM_gc_worklist_add(tc, worklist, &body->name); |
123 | 3.62k | MVM_gc_worklist_add(tc, worklist, &body->outer); |
124 | 3.62k | MVM_gc_worklist_add(tc, worklist, &body->static_code); |
125 | 3.62k | |
126 | 3.62k | /* If it's not fully deserialized, none of the following can apply. */ |
127 | 3.62k | if (!body->fully_deserialized) |
128 | 0 | return; |
129 | 3.62k | |
130 | 3.62k | /* lexical names hash keys */ |
131 | 3.62k | HASH_ITER(hash_handle, body->lexical_names, current, tmp, bucket_tmp) { |
132 | 0 | MVM_gc_worklist_add(tc, worklist, ¤t->hash_handle.key); |
133 | 0 | MVM_gc_worklist_add(tc, worklist, ¤t->key); |
134 | 0 | } |
135 | 3.62k | |
136 | 3.62k | /* static env */ |
137 | 3.62k | if (body->static_env) { |
138 | 0 | MVMuint16 *type_map = body->lexical_types; |
139 | 0 | MVMuint16 count = body->num_lexicals; |
140 | 0 | MVMuint16 i; |
141 | 0 | for (i = 0; i < count; i++) |
142 | 0 | if (type_map[i] == MVM_reg_str || type_map[i] == MVM_reg_obj) |
143 | 0 | MVM_gc_worklist_add(tc, worklist, &body->static_env[i].o); |
144 | 0 | } |
145 | 3.62k | |
146 | 3.62k | /* Spesh. */ |
147 | 3.62k | MVM_gc_worklist_add(tc, worklist, &body->spesh); |
148 | 3.62k | } |
149 | | |
150 | | /* Called by the VM in order to free memory associated with this object. */ |
151 | 0 | static void gc_free(MVMThreadContext *tc, MVMObject *obj) { |
152 | 0 | MVMStaticFrame *sf = (MVMStaticFrame *)obj; |
153 | 0 | MVMStaticFrameBody *body = &sf->body; |
154 | 0 | if (body->orig_bytecode != body->bytecode) { |
155 | 0 | MVM_free(body->bytecode); |
156 | 0 | body->bytecode = body->orig_bytecode; |
157 | 0 | } |
158 | 0 |
|
159 | 0 |
|
160 | 0 | /* If it's not fully deserialized, none of the following can apply. */ |
161 | 0 | if (!body->fully_deserialized) |
162 | 0 | return; |
163 | 0 | MVM_free(body->handlers); |
164 | 0 | MVM_free(body->work_initial); |
165 | 0 | MVM_free(body->static_env); |
166 | 0 | MVM_free(body->static_env_flags); |
167 | 0 | MVM_free(body->local_types); |
168 | 0 | MVM_free(body->lexical_types); |
169 | 0 | MVM_free(body->lexical_names_list); |
170 | 0 | MVM_HASH_DESTROY(tc, hash_handle, MVMLexicalRegistry, body->lexical_names); |
171 | 0 | } |
172 | | |
173 | | static const MVMStorageSpec storage_spec = { |
174 | | MVM_STORAGE_SPEC_REFERENCE, /* inlineable */ |
175 | | 0, /* bits */ |
176 | | 0, /* align */ |
177 | | MVM_STORAGE_SPEC_BP_NONE, /* boxed_primitive */ |
178 | | 0, /* can_box */ |
179 | | 0, /* is_unsigned */ |
180 | | }; |
181 | | |
182 | | |
183 | | /* Gets the storage specification for this representation. */ |
184 | 0 | static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) { |
185 | 0 | /* XXX in the end we'll support inlining of this... */ |
186 | 0 | return &storage_spec; |
187 | 0 | } |
188 | | |
189 | | /* Compose the representation. */ |
190 | 0 | static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info) { |
191 | 0 | /* Nothing to do for this REPR. */ |
192 | 0 | } |
193 | | |
194 | | /* Calculates the non-GC-managed memory we hold on to. */ |
195 | 1.17k | static MVMuint64 unmanaged_size(MVMThreadContext *tc, MVMSTable *st, void *data) { |
196 | 1.17k | MVMStaticFrameBody *body = (MVMStaticFrameBody *)data; |
197 | 1.17k | MVMuint64 size = 0; |
198 | 1.17k | |
199 | 1.17k | if (body->fully_deserialized) { |
200 | 1.17k | size += sizeof(MVMuint16) * body->num_locals; |
201 | 1.17k | size += sizeof(MVMuint16) * body->num_lexicals; |
202 | 1.17k | |
203 | 1.17k | if (body->bytecode != body->orig_bytecode) |
204 | 0 | size += body->bytecode_size; |
205 | 1.17k | |
206 | 1.17k | size += sizeof(MVMLexicalRegistry *) * body->num_lexicals; |
207 | 1.17k | |
208 | 1.17k | size += sizeof(MVMLexicalRegistry) * HASH_CNT(hash_handle, body->lexical_names); |
209 | 1.17k | |
210 | 1.17k | size += sizeof(MVMFrameHandler) * body->num_handlers; |
211 | 1.17k | |
212 | 1.17k | /* XXX i *think* the annotations are just a pointer into the serialized |
213 | 1.17k | * blob, so don't actually count it towards the unmanaged size. */ |
214 | 1.17k | /* |
215 | 1.17k | size += sizeof(MVMuint8) * body->num_annotations |
216 | 1.17k | */ |
217 | 1.17k | size += body->env_size; /* static_env */ |
218 | 1.17k | size += body->num_lexicals; /* static_env_flags */ |
219 | 1.17k | |
220 | 1.17k | if (body->instrumentation) { |
221 | 0 | size += body->instrumentation->uninstrumented_bytecode_size; |
222 | 0 | size += body->instrumentation->instrumented_bytecode_size; |
223 | 0 |
|
224 | 0 | /* XXX not 100% sure if num_handlers from the body is also the |
225 | 0 | * number of handlers in instrumented version. should be, though. */ |
226 | 0 | size += sizeof(MVMFrameHandler) * body->num_handlers * 2; |
227 | 0 | } |
228 | 1.17k | } |
229 | 1.17k | |
230 | 1.17k | return size; |
231 | 1.17k | } |
232 | | |
233 | 0 | static void describe_refs(MVMThreadContext *tc, MVMHeapSnapshotState *ss, MVMSTable *st, void *data) { |
234 | 0 | MVMStaticFrameBody *body = (MVMStaticFrameBody *)data; |
235 | 0 | MVMLexicalRegistry *current, *tmp; |
236 | 0 | unsigned bucket_tmp; |
237 | 0 |
|
238 | 0 | MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, |
239 | 0 | (MVMCollectable *)body->cu, "Compilation Unit"); |
240 | 0 | MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, |
241 | 0 | (MVMCollectable *)body->cuuid, "Compilation Unit Unique ID"); |
242 | 0 | MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, |
243 | 0 | (MVMCollectable *)body->name, "Name"); |
244 | 0 | MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, |
245 | 0 | (MVMCollectable *)body->outer, "Outer static frame"); |
246 | 0 | MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, |
247 | 0 | (MVMCollectable *)body->static_code, "Static code object"); |
248 | 0 |
|
249 | 0 | /* If it's not fully deserialized, none of the following can apply. */ |
250 | 0 | if (!body->fully_deserialized) |
251 | 0 | return; |
252 | 0 |
|
253 | 0 | /* lexical names hash keys */ |
254 | 0 | HASH_ITER(hash_handle, body->lexical_names, current, tmp, bucket_tmp) { |
255 | 0 | MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, |
256 | 0 | (MVMCollectable *)current->key, "Lexical name"); |
257 | 0 | } |
258 | 0 |
|
259 | 0 | /* static env */ |
260 | 0 | if (body->static_env) { |
261 | 0 | MVMuint16 *type_map = body->lexical_types; |
262 | 0 | MVMuint16 count = body->num_lexicals; |
263 | 0 | MVMuint16 i; |
264 | 0 | for (i = 0; i < count; i++) |
265 | 0 | if (type_map[i] == MVM_reg_str || type_map[i] == MVM_reg_obj) |
266 | 0 | MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, |
267 | 0 | (MVMCollectable *)body->static_env[i].o, "Static Environment Entry"); |
268 | 0 | } |
269 | 0 |
|
270 | 0 | /* Spesh data */ |
271 | 0 | MVM_profile_heap_add_collectable_rel_const_cstr(tc, ss, |
272 | 0 | (MVMCollectable *)body->spesh, "Specializer Data"); |
273 | 0 | } |
274 | | |
275 | | /* Initializes the representation. */ |
276 | 144 | const MVMREPROps * MVMStaticFrame_initialize(MVMThreadContext *tc) { |
277 | 144 | return &MVMStaticFrame_this_repr; |
278 | 144 | } |
279 | | |
280 | | static const MVMREPROps MVMStaticFrame_this_repr = { |
281 | | type_object_for, |
282 | | MVM_gc_allocate_object, |
283 | | NULL, /* initialize */ |
284 | | copy_to, |
285 | | MVM_REPR_DEFAULT_ATTR_FUNCS, |
286 | | MVM_REPR_DEFAULT_BOX_FUNCS, |
287 | | MVM_REPR_DEFAULT_POS_FUNCS, |
288 | | MVM_REPR_DEFAULT_ASS_FUNCS, |
289 | | MVM_REPR_DEFAULT_ELEMS, |
290 | | get_storage_spec, |
291 | | NULL, /* change_type */ |
292 | | NULL, /* serialize */ |
293 | | NULL, /* deserialize */ |
294 | | NULL, /* serialize_repr_data */ |
295 | | NULL, /* deserialize_repr_data */ |
296 | | NULL, /* deserialize_stable_size */ |
297 | | gc_mark, |
298 | | gc_free, |
299 | | NULL, /* gc_cleanup */ |
300 | | NULL, /* gc_mark_repr_data */ |
301 | | NULL, /* gc_free_repr_data */ |
302 | | compose, |
303 | | NULL, /* spesh */ |
304 | | "MVMStaticFrame", /* name */ |
305 | | MVM_REPR_ID_MVMStaticFrame, |
306 | | unmanaged_size, /* unmanaged_size */ |
307 | | describe_refs, |
308 | | }; |