/home/travis/build/MoarVM/MoarVM/src/6model/6model.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* Boolification mode flags. */ |
2 | | #define MVM_BOOL_MODE_CALL_METHOD 0 |
3 | | #define MVM_BOOL_MODE_UNBOX_INT 1 |
4 | | #define MVM_BOOL_MODE_UNBOX_NUM 2 |
5 | | #define MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY 3 |
6 | | #define MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY_OR_ZERO 4 |
7 | | #define MVM_BOOL_MODE_NOT_TYPE_OBJECT 5 |
8 | | #define MVM_BOOL_MODE_BIGINT 6 |
9 | | #define MVM_BOOL_MODE_ITER 7 |
10 | | #define MVM_BOOL_MODE_HAS_ELEMS 8 |
11 | | |
12 | | /* Controls the way that type checks are performed. By default, if there is |
13 | | * a type check cache we treat it as definitive. However, it's possible to |
14 | | * declare that in the case the type check cache has no entry we should fall |
15 | | * back to asking the .HOW.type_check method (set TYPE_CHECK_CACHE_THEN_METHOD). |
16 | | * While a normal type check asks a value if it supports another type, the |
17 | | * TYPE_CHECK_NEEDS_ACCEPTS flag results in a call to .accepts_type on the |
18 | | * HOW of the thing we're checking the value against, giving it a chance to |
19 | | * decide answer. These are set as the lower bits of mode_flags in MVMSTable. */ |
20 | | #define MVM_TYPE_CHECK_CACHE_DEFINITIVE 0 |
21 | | #define MVM_TYPE_CHECK_CACHE_THEN_METHOD 1 |
22 | | #define MVM_TYPE_CHECK_NEEDS_ACCEPTS 2 |
23 | | #define MVM_TYPE_CHECK_CACHE_FLAG_MASK 3 |
24 | | |
25 | | /* This STable mode flag is set if we consider the method cache authoritative. */ |
26 | | #define MVM_METHOD_CACHE_AUTHORITATIVE 4 |
27 | | |
28 | | /* This STable mode flag is set if the type needs finalization. */ |
29 | | #define MVM_FINALIZE_TYPE 8 |
30 | | |
31 | | /* This STable mode flag is set if the type is parametric (and so can be |
32 | | * parameterized). */ |
33 | | #define MVM_PARAMETRIC_TYPE 16 |
34 | | |
35 | | /* This STable mode flag is set if the type is a parameterization of some |
36 | | * parametric type. */ |
37 | | #define MVM_PARAMETERIZED_TYPE 32 |
38 | | |
39 | | /* HLL type roles. */ |
40 | | #define MVM_HLL_ROLE_NONE 0 |
41 | | #define MVM_HLL_ROLE_INT 1 |
42 | | #define MVM_HLL_ROLE_NUM 2 |
43 | | #define MVM_HLL_ROLE_STR 3 |
44 | | #define MVM_HLL_ROLE_ARRAY 4 |
45 | | #define MVM_HLL_ROLE_HASH 5 |
46 | | #define MVM_HLL_ROLE_CODE 6 |
47 | | |
48 | | /* Hint value to indicate the absence of an attribute lookup or method |
49 | | * dispatch hint. */ |
50 | | #define MVM_NO_HINT -1 |
51 | | |
52 | | /* This data structure describes what storage a given representation |
53 | | * needs if something of that representation is to be embedded in |
54 | | * another place. For any representation that expects to be used |
55 | | * as a kind of reference type, it will just want to be a pointer. |
56 | | * But for other things, they would prefer to be "inlined" into |
57 | | * the object. */ |
58 | | struct MVMStorageSpec { |
59 | | /* 0 if this is to be referenced, anything else otherwise. */ |
60 | | MVMuint16 inlineable; |
61 | | |
62 | | /* For things that want to be inlined, the number of bits of |
63 | | * storage they need and what kind of byte-boundary they want to |
64 | | * be aligned to. Ignored otherwise. */ |
65 | | MVMuint16 bits; |
66 | | MVMuint16 align; |
67 | | |
68 | | /* For things that are inlined, if they are just storage of a |
69 | | * primitive type and can unbox, this says what primitive type |
70 | | * that they unbox to. */ |
71 | | MVMuint16 boxed_primitive; |
72 | | |
73 | | /* The types that this one can box/unbox to. */ |
74 | | MVMuint16 can_box; |
75 | | |
76 | | /* For ints, whether it's an unsigned value. */ |
77 | | MVMuint8 is_unsigned; |
78 | | }; |
79 | | |
80 | | /* Inlined or not. */ |
81 | | #define MVM_STORAGE_SPEC_REFERENCE 0 |
82 | | #define MVM_STORAGE_SPEC_INLINED 1 |
83 | | |
84 | | /* Possible options for boxed primitives. */ |
85 | | #define MVM_STORAGE_SPEC_BP_NONE 0 |
86 | | #define MVM_STORAGE_SPEC_BP_INT 1 |
87 | | #define MVM_STORAGE_SPEC_BP_NUM 2 |
88 | | #define MVM_STORAGE_SPEC_BP_STR 3 |
89 | | #define MVM_STORAGE_SPEC_BP_INT8 4 |
90 | | #define MVM_STORAGE_SPEC_BP_INT16 5 |
91 | | #define MVM_STORAGE_SPEC_BP_INT32 6 |
92 | | #define MVM_STORAGE_SPEC_BP_UINT8 7 |
93 | | #define MVM_STORAGE_SPEC_BP_UINT16 8 |
94 | | #define MVM_STORAGE_SPEC_BP_UINT32 9 |
95 | | #define MVM_STORAGE_SPEC_BP_UINT64 10 |
96 | | |
97 | | /* can_box bit field values. */ |
98 | | #define MVM_STORAGE_SPEC_CAN_BOX_INT 1 |
99 | | #define MVM_STORAGE_SPEC_CAN_BOX_NUM 2 |
100 | | #define MVM_STORAGE_SPEC_CAN_BOX_STR 4 |
101 | | #define MVM_STORAGE_SPEC_CAN_BOX_MASK 7 |
102 | | |
103 | | /* Flags that may be set on any collectable. */ |
104 | | typedef enum { |
105 | | /* Is a type object (and thus not a concrete instance). */ |
106 | | MVM_CF_TYPE_OBJECT = 1, |
107 | | |
108 | | /* Is an STable. */ |
109 | | MVM_CF_STABLE = 2, |
110 | | |
111 | | /* Is a heap-promoted call frame. */ |
112 | | MVM_CF_FRAME = 4, |
113 | | |
114 | | /* Has already been seen once in GC nursery. */ |
115 | | MVM_CF_NURSERY_SEEN = 8, |
116 | | |
117 | | /* Has been promoted to the old generation. */ |
118 | | MVM_CF_SECOND_GEN = 16, |
119 | | |
120 | | /* Is shared - that is, more than one thread knows about it. */ |
121 | | MVM_CF_SHARED = 32, |
122 | | |
123 | | /* Has already been added to the gen2 aggregates pointing to nursery |
124 | | * objects list. */ |
125 | | MVM_CF_IN_GEN2_ROOT_LIST = 64, |
126 | | |
127 | | /* A full GC run has found this object to be live. */ |
128 | | MVM_CF_GEN2_LIVE = 128, |
129 | | |
130 | | /* This object in fromspace is live with a valid forwarder. */ |
131 | | /* TODO - should be possible to use the same bit for this and GEN2_LIVE. */ |
132 | | MVM_CF_FORWARDER_VALID = 256, |
133 | | |
134 | | /* Have we allocated memory to store a serialization index? */ |
135 | | MVM_CF_SERIALZATION_INDEX_ALLOCATED = 512, |
136 | | |
137 | | /* Have we arranged a persistent object ID for this object? */ |
138 | | MVM_CF_HAS_OBJECT_ID = 1024, |
139 | | |
140 | | /* Have we flagged this object as something we must never repossess? */ |
141 | | /* Note: if you're hunting for a flag, some day in the future when we |
142 | | * have used them all, this one is easy enough to eliminate by having the |
143 | | * tiny number of objects marked this way in a remembered set. */ |
144 | | MVM_CF_NEVER_REPOSSESS = 2048, |
145 | | |
146 | | /* Has this item been chained into a gen2 freelist? This is only used in |
147 | | * GC debug more. */ |
148 | | MVM_CF_DEBUG_IN_GEN2_FREE_LIST = 4096, |
149 | | } MVMCollectableFlags; |
150 | | |
151 | | #ifdef MVM_USE_OVERFLOW_SERIALIZATION_INDEX |
152 | | struct MVMSerializationIndex { |
153 | | MVMuint32 sc_idx; |
154 | | MVMuint32 idx; |
155 | | }; |
156 | | #endif |
157 | | |
158 | | /* Things that every GC-collectable entity has. These fall into two |
159 | | * categories: |
160 | | * * MVMObject - objects. Almost everything is one of these. |
161 | | * * MVMSTable - shared tables; one per (HOW, REPR) pairing. |
162 | | * Only the first can vary in size, and even then only if it's not a |
163 | | * type object. |
164 | | */ |
165 | | struct MVMCollectable { |
166 | | /* Put this union first, as these pointers/indexes are relatively "cold", |
167 | | whereas "flags" is accessed relatively frequently, as are the fields |
168 | | that follow in the structures into which MVMCollectable is embedded. |
169 | | Shrinking the size of the active part of the structure slightly |
170 | | increases the chance that it fits into the CPU's L1 cache, which is a |
171 | | "free" performance win. */ |
172 | | union { |
173 | | /* Forwarding pointer, for copying/compacting GC purposes. */ |
174 | | MVMCollectable *forwarder; |
175 | | /* Index of the serialization context this collectable lives in, if |
176 | | * any, and then location within that. */ |
177 | | #ifdef MVM_USE_OVERFLOW_SERIALIZATION_INDEX |
178 | | struct { |
179 | | MVMuint16 sc_idx; |
180 | | MVMuint16 idx; |
181 | | } sc; |
182 | | struct MVMSerializationIndex *sci; |
183 | | #else |
184 | | struct { |
185 | | MVMuint32 sc_idx; |
186 | | MVMuint32 idx; |
187 | | } sc; |
188 | | #endif |
189 | | /* Used to chain STables queued to be freed. */ |
190 | | MVMSTable *st; |
191 | | } sc_forward_u; |
192 | | |
193 | | /* Identifier of the thread that currently owns the object, if any. If the |
194 | | * object is unshared, then this is always the creating thread. If it is |
195 | | * shared then it's whoever currently holds the mutex on it, or 0 if there |
196 | | * is no held mutex. */ |
197 | | MVMuint32 owner; |
198 | | |
199 | | /* Collectable flags (see MVMCollectableFlags). */ |
200 | | MVMuint16 flags; |
201 | | |
202 | | /* Object size, in bytes. */ |
203 | | MVMuint16 size; |
204 | | }; |
205 | | #ifdef MVM_USE_OVERFLOW_SERIALIZATION_INDEX |
206 | | # define MVM_DIRECT_SC_IDX_SENTINEL 0xFFFF |
207 | | #else |
208 | | # define MVM_DIRECT_SC_IDX_SENTINEL ~0 |
209 | | #endif |
210 | | |
211 | | /* The common things every object has. |
212 | | * |
213 | | * NB - the assumption that MVMObject* can be safely cast into |
214 | | * MVMCollectable* is spread throughout the codebase, as well |
215 | | * as used directly in JIT. Thus, nothing may preceed the header! |
216 | | */ |
217 | | struct MVMObject { |
218 | | /* Commonalities that all collectable entities have. */ |
219 | | MVMCollectable header; |
220 | | |
221 | | /* The s-table for the object. */ |
222 | | MVMSTable *st; |
223 | | }; |
224 | | |
225 | | /* An dummy object, mostly used to compute the offset of the data part of |
226 | | * a 6model object. */ |
227 | | struct MVMObjectStooge { |
228 | | MVMObject common; |
229 | | void *data; |
230 | | }; |
231 | | |
232 | | /* This is used to identify an attribute for various types of cache. */ |
233 | | struct MVMAttributeIdentifier { |
234 | | MVMObject *class_handle; /* Class handle */ |
235 | | MVMString *attr_name; /* Name of the attribute. */ |
236 | | MVMint64 hint; /* Hint for use in static/gradual typing. */ |
237 | | }; |
238 | | |
239 | | /* How do we turn something of this type into a boolean? */ |
240 | | struct MVMBoolificationSpec { |
241 | | MVMObject *method; |
242 | | MVMuint32 mode; |
243 | | }; |
244 | | |
245 | | /* Constant for incrementing the type cache ID for new STables. This leaves |
246 | | * the lowest bits free for caches to attach flags (of note, the multi |
247 | | * dispatch cache). */ |
248 | | #define MVM_TYPE_CACHE_ID_INCR 256 |
249 | | |
250 | | /* S-table, representing a meta-object/representation pairing. Note that the |
251 | | * items are grouped in hope that it will pack decently and do decently in |
252 | | * terms of cache lines. */ |
253 | | struct MVMSTable { |
254 | | /* Commonalities that all collectable entities have. */ |
255 | | MVMCollectable header; |
256 | | |
257 | | /* The representation operation table. */ |
258 | | const MVMREPROps *REPR; |
259 | | |
260 | | /* Any data specific to this type that the REPR wants to keep. */ |
261 | | void *REPR_data; |
262 | | |
263 | | /* The size of an object of this type in bytes, including the |
264 | | * header. */ |
265 | | MVMuint32 size; |
266 | | |
267 | | /* The length of the type check cache. */ |
268 | | MVMuint16 type_check_cache_length; |
269 | | |
270 | | /* The type checking mode and method cache mode (see flags for this |
271 | | * above). */ |
272 | | MVMuint16 mode_flags; |
273 | | |
274 | | /* Array of type objects. If this is set, then it is expected to contain |
275 | | * the type objects of all types that this type is equivalent to (e.g. |
276 | | * all the things it isa and all the things it does). */ |
277 | | MVMObject **type_check_cache; |
278 | | |
279 | | /* By-name method dispatch cache. */ |
280 | | MVMObject *method_cache; |
281 | | |
282 | | /* An ID solely for use in caches that last a VM instance. Thus it |
283 | | * should never, ever be serialized and you should NEVER make a |
284 | | * type directory based upon this ID. Otherwise you'll create memory |
285 | | * leaks for anonymous types, and other such screwups. */ |
286 | | MVMuint64 type_cache_id; |
287 | | |
288 | | /* If this is a container, then this contains information needed in |
289 | | * order to fetch the value in it. If not, it'll be null, which can |
290 | | * be taken as a "not a container" indication. */ |
291 | | const MVMContainerSpec *container_spec; |
292 | | |
293 | | /* Data that the container spec may need to function. */ |
294 | | /* Any data specific to this type that the REPR wants to keep. */ |
295 | | void *container_data; |
296 | | |
297 | | /* Information - if any - about how we can turn something of this type |
298 | | * into a boolean. */ |
299 | | MVMBoolificationSpec *boolification_spec; |
300 | | |
301 | | /* The HLL that this type is owned by, if any. */ |
302 | | MVMHLLConfig *hll_owner; |
303 | | |
304 | | /* The role that the type plays in the HLL, if any. */ |
305 | | MVMint64 hll_role; |
306 | | |
307 | | /* Invocation handler. If something tries to invoke this object, |
308 | | * whatever hangs off this function pointer gets invoked to handle |
309 | | * the invocation. If it's a call into C code it may do stuff right |
310 | | * off the bat. However, normally it will do whatever is needed to |
311 | | * arrange for setting up a callframe, twiddle the interpreter's |
312 | | * PC as needed and return. */ |
313 | | void (*invoke) (MVMThreadContext *tc, MVMObject *invokee, |
314 | | MVMCallsite *callsite, MVMRegister *args); |
315 | | |
316 | | /* |
317 | | * If this is invokable, then this contains information needed to |
318 | | * figure out how to invoke it. If not, it'll be null. |
319 | | */ |
320 | | MVMInvocationSpec *invocation_spec; |
321 | | |
322 | | /* The type-object. */ |
323 | | MVMObject *WHAT; |
324 | | |
325 | | /* The underlying package stash. */ |
326 | | MVMObject *WHO; |
327 | | |
328 | | /* The meta-object. */ |
329 | | MVMObject *HOW; |
330 | | |
331 | | /* Parametricity. Mode flags indicate what, if any, of this union is valid. */ |
332 | | union { |
333 | | struct { |
334 | | /* The code object to use to produce a new parameterization. */ |
335 | | MVMObject *parameterizer; |
336 | | |
337 | | /* Lookup table of existing parameterizations. For now, just a VM |
338 | | * array with alternating pairs of [arg array], object. Could in |
339 | | * the future we something lower level or hashy; we've yet to see |
340 | | * how hot-path lookups end up being in reality. */ |
341 | | MVMObject *lookup; |
342 | | } ric; |
343 | | struct { |
344 | | /* The type that we are a parameterization of. */ |
345 | | MVMObject *parametric_type; |
346 | | |
347 | | /* Our type parameters. */ |
348 | | MVMObject *parameters; |
349 | | } erized; |
350 | | } paramet; |
351 | | |
352 | | /* We lazily deserialize HOW; this is the SC and index if needed. */ |
353 | | MVMSerializationContext *HOW_sc; |
354 | | MVMuint32 HOW_idx; |
355 | | |
356 | | /* Also info we need to lazily deserialize the method cache. */ |
357 | | MVMuint32 method_cache_offset; |
358 | | MVMSerializationContext *method_cache_sc; |
359 | | |
360 | | /* A string associated with this STable for debugging purposes. |
361 | | * Usually the name of the class this belongs to. */ |
362 | | char *debug_name; |
363 | | |
364 | | /* If this STable is currently in the process of being repossessed. Used |
365 | | * to trigger clearup of memory pre-repossession. */ |
366 | | MVMuint8 being_repossessed; |
367 | | }; |
368 | | |
369 | | /* The representation operations table. Note that representations are not |
370 | | * classes - there's no inheritance, so there's no polymorphism. If you know |
371 | | * a representation statically, you can statically dereference the call to |
372 | | * the representation op in question. In the dynamic case, you have to go |
373 | | * following the pointer, however. */ |
374 | | struct MVMREPROps_Attribute { |
375 | | /* Gets the current value for an attribute and places it in the passed |
376 | | * location (specified as a register). Expects to be passed a kind flag |
377 | | * that matches the kind of the attribute that is being fetched. */ |
378 | | void (*get_attribute) (MVMThreadContext *tc, MVMSTable *st, |
379 | | MVMObject *root, void *data, MVMObject *class_handle, MVMString *name, |
380 | | MVMint64 hint, MVMRegister *result, MVMuint16 kind); |
381 | | |
382 | | /* Binds the given object or value to the specified attribute. The |
383 | | * kind flag specifies the type of value being passed to be bound.*/ |
384 | | void (*bind_attribute) (MVMThreadContext *tc, MVMSTable *st, |
385 | | MVMObject *root, void *data, MVMObject *class_handle, MVMString *name, |
386 | | MVMint64 hint, MVMRegister value, MVMuint16 kind); |
387 | | |
388 | | /* Gets the hint for the given attribute ID. */ |
389 | | MVMint64 (*hint_for) (MVMThreadContext *tc, MVMSTable *st, |
390 | | MVMObject *class_handle, MVMString *name); |
391 | | |
392 | | /* Checks if an attribute has been initialized. */ |
393 | | MVMint64 (*is_attribute_initialized) (MVMThreadContext *tc, MVMSTable *st, |
394 | | void *data, MVMObject *class_handle, MVMString *name, |
395 | | MVMint64 hint); |
396 | | |
397 | | /* Provided the attribute is a native integer of the architecture's atomic |
398 | | * size or an object pointer, returns an AO_t * referencing it. This is only |
399 | | * valid until the next safepoint. If rebless is called on the object, |
400 | | * updates may be lost although memory safety must not be violated. */ |
401 | | AO_t * (*attribute_as_atomic) (MVMThreadContext *tc, MVMSTable *st, |
402 | | void *data, MVMObject *class_handle, MVMString *name, MVMuint16 kind); |
403 | | }; |
404 | | struct MVMREPROps_Boxing { |
405 | | /* Used with boxing. Sets an integer value, for representations that |
406 | | * can hold one. */ |
407 | | void (*set_int) (MVMThreadContext *tc, MVMSTable *st, |
408 | | MVMObject *root, void *data, MVMint64 value); |
409 | | |
410 | | /* Used with boxing. Gets an integer value, for representations that |
411 | | * can hold one. */ |
412 | | MVMint64 (*get_int) (MVMThreadContext *tc, MVMSTable *st, |
413 | | MVMObject *root, void *data); |
414 | | |
415 | | /* Used with boxing. Sets a floating point value, for representations that |
416 | | * can hold one. */ |
417 | | void (*set_num) (MVMThreadContext *tc, MVMSTable *st, |
418 | | MVMObject *root, void *data, MVMnum64 value); |
419 | | |
420 | | /* Used with boxing. Gets a floating point value, for representations that |
421 | | * can hold one. */ |
422 | | MVMnum64 (*get_num) (MVMThreadContext *tc, MVMSTable *st, |
423 | | MVMObject *root, void *data); |
424 | | |
425 | | /* Used with boxing. Sets a string value, for representations that |
426 | | * can hold one. */ |
427 | | void (*set_str) (MVMThreadContext *tc, MVMSTable *st, |
428 | | MVMObject *root, void *data, MVMString *value); |
429 | | |
430 | | /* Used with boxing. Gets a string value, for representations that |
431 | | * can hold one. */ |
432 | | MVMString * (*get_str) (MVMThreadContext *tc, MVMSTable *st, |
433 | | MVMObject *root, void *data); |
434 | | |
435 | | /* Used with boxing. Sets an unsinged integer value, for representations |
436 | | * that can hold one. */ |
437 | | void (*set_uint) (MVMThreadContext *tc, MVMSTable *st, |
438 | | MVMObject *root, void *data, MVMuint64 value); |
439 | | |
440 | | /* Used with boxing. Gets an unsigned integer value, for representations |
441 | | * that can hold one. */ |
442 | | MVMuint64 (*get_uint) (MVMThreadContext *tc, MVMSTable *st, |
443 | | MVMObject *root, void *data); |
444 | | |
445 | | /* Some objects serve primarily as boxes of others, inlining them. This gets |
446 | | * gets the reference to such things, using the representation ID to distinguish |
447 | | * them. */ |
448 | | void * (*get_boxed_ref) (MVMThreadContext *tc, MVMSTable *st, |
449 | | MVMObject *root, void *data, MVMuint32 repr_id); |
450 | | }; |
451 | | struct MVMREPROps_Positional { |
452 | | /* Gets the element and the specified index and places it in the passed |
453 | | * location (specified as a register). Expects to be passed a kind flag |
454 | | * that matches the kind of the attribute that is being fetched. */ |
455 | | void (*at_pos) (MVMThreadContext *tc, MVMSTable *st, |
456 | | MVMObject *root, void *data, MVMint64 index, |
457 | | MVMRegister *result, MVMuint16 kind); |
458 | | |
459 | | /* Binds the given object or value to the specified index. The |
460 | | * kind flag specifies the type of value being passed to be bound.*/ |
461 | | void (*bind_pos) (MVMThreadContext *tc, MVMSTable *st, |
462 | | MVMObject *root, void *data, MVMint64 index, |
463 | | MVMRegister value, MVMuint16 kind); |
464 | | |
465 | | /* Sets the element count of the array, expanding or shrinking |
466 | | * it as needed. */ |
467 | | void (*set_elems) (MVMThreadContext *tc, MVMSTable *st, |
468 | | MVMObject *root, void *data, MVMuint64 count); |
469 | | |
470 | | /* Pushes the specified value onto the array. */ |
471 | | void (*push) (MVMThreadContext *tc, MVMSTable *st, |
472 | | MVMObject *root, void *data, MVMRegister value, MVMuint16 kind); |
473 | | |
474 | | /* Pops the value at the end of the array off it. */ |
475 | | void (*pop) (MVMThreadContext *tc, MVMSTable *st, |
476 | | MVMObject *root, void *data, MVMRegister *value, MVMuint16 kind); |
477 | | |
478 | | /* Unshifts the value onto the array. */ |
479 | | void (*unshift) (MVMThreadContext *tc, MVMSTable *st, |
480 | | MVMObject *root, void *data, MVMRegister value, MVMuint16 kind); |
481 | | |
482 | | /* Gets the value at the start of the array, and moves the starting point of |
483 | | * the array so that the next element is element zero. */ |
484 | | void (*shift) (MVMThreadContext *tc, MVMSTable *st, |
485 | | MVMObject *root, void *data, MVMRegister *value, MVMuint16 kind); |
486 | | |
487 | | /* Creates a slice of the source array (from start to end) and stores it |
488 | | * within the destination array. If start or end is "-n", it will be |
489 | | * translated into the nth position relative to the end of the array. */ |
490 | | void (*slice) (MVMThreadContext *tc, MVMSTable *st, |
491 | | MVMObject *src, void *data, MVMObject *dest, |
492 | | MVMint64 start, MVMint64 end); |
493 | | |
494 | | /* Splices the specified array into this one. Representations may optimize if |
495 | | * they know the type of the passed array, otherwise they should use the REPR |
496 | | * API. */ |
497 | | void (*splice) (MVMThreadContext *tc, MVMSTable *st, |
498 | | MVMObject *root, void *data, MVMObject *target_array, |
499 | | MVMint64 offset, MVMuint64 elems); |
500 | | |
501 | | /* Multi-dimensional array read. */ |
502 | | void (*at_pos_multidim) (MVMThreadContext *tc, MVMSTable *st, |
503 | | MVMObject *root, void *data, MVMint64 num_indices, |
504 | | MVMint64 *indices, MVMRegister *result, MVMuint16 kind); |
505 | | |
506 | | /* Multi-dimensional array write. */ |
507 | | void (*bind_pos_multidim) (MVMThreadContext *tc, MVMSTable *st, |
508 | | MVMObject *root, void *data, MVMint64 num_indices, |
509 | | MVMint64 *indices, MVMRegister value, MVMuint16 kind); |
510 | | |
511 | | /* Gets the number of dimensions along with a C-level array of them. The |
512 | | * second two parameters are "out"s. The caller must not mutate dimensions, |
513 | | * nor persist it such that it lasts longer than the next VM safepoint. */ |
514 | | void (*dimensions) (MVMThreadContext *tc, MVMSTable *st, |
515 | | MVMObject *root, void *data, MVMint64 *num_dimensions, |
516 | | MVMint64 **dimensions); |
517 | | |
518 | | /* Sets the number of dimensions. The caller is responsible for freeing |
519 | | * the array passed in dimensions. */ |
520 | | void (*set_dimensions) (MVMThreadContext *tc, MVMSTable *st, |
521 | | MVMObject *root, void *data, MVMint64 num_dimensions, |
522 | | MVMint64 *dimensions); |
523 | | |
524 | | /* Gets the STable representing the declared element type. */ |
525 | | MVMStorageSpec (*get_elem_storage_spec) (MVMThreadContext *tc, MVMSTable *st); |
526 | | |
527 | | /* Provided the array consists of integers of the architecture's atomic |
528 | | * size, gets an AO_t * pointing to that element and valid until the next |
529 | | * safepoint. */ |
530 | | AO_t * (*pos_as_atomic) (MVMThreadContext *tc, MVMSTable *st, MVMObject *root, |
531 | | void *data, MVMint64 index); |
532 | | |
533 | | /* Multi-dim version of as_atomic. */ |
534 | | AO_t * (*pos_as_atomic_multidim) (MVMThreadContext *tc, MVMSTable *st, MVMObject *root, |
535 | | void *data, MVMint64 num_indices, MVMint64 *indices); |
536 | | }; |
537 | | struct MVMREPROps_Associative { |
538 | | /* Gets the value at the specified key and places it in the passed |
539 | | * location (specified as a register). Expects to be passed a kind flag |
540 | | * that matches the kind of the attribute that is being fetched. */ |
541 | | void (*at_key) (MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, |
542 | | MVMObject *key, MVMRegister *result, MVMuint16 kind); |
543 | | |
544 | | /* Binds the object at the specified address into the hash at the specified |
545 | | * key. */ |
546 | | void (*bind_key) (MVMThreadContext *tc, MVMSTable *st, MVMObject *root, |
547 | | void *data, MVMObject *key, MVMRegister value, MVMuint16 kind); |
548 | | |
549 | | /* Returns a true value of the key exists, and a false one if not. */ |
550 | | MVMint64 (*exists_key) (MVMThreadContext *tc, MVMSTable *st, |
551 | | MVMObject *root, void *data, MVMObject *key); |
552 | | |
553 | | /* Deletes the specified key. */ |
554 | | void (*delete_key) (MVMThreadContext *tc, MVMSTable *st, |
555 | | MVMObject *root, void *data, MVMObject *key); |
556 | | |
557 | | /* Gets the storage spec of the hash value type. */ |
558 | | MVMStorageSpec (*get_value_storage_spec) (MVMThreadContext *tc, MVMSTable *st); |
559 | | }; |
560 | | struct MVMREPROps { |
561 | | /* Creates a new type object of this representation, and |
562 | | * associates it with the given HOW. Also sets up a new |
563 | | * representation instance if needed. */ |
564 | | MVMObject * (*type_object_for) (MVMThreadContext *tc, MVMObject *HOW); |
565 | | |
566 | | /* Allocates a new, but uninitialized object, based on the |
567 | | * specified s-table. */ |
568 | | MVMObject * (*allocate) (MVMThreadContext *tc, MVMSTable *st); |
569 | | |
570 | | /* Used to initialize the body of an object representing the type |
571 | | * describe by the specified s-table. DATA points to the body. It |
572 | | * may recursively call initialize for any flattened objects. */ |
573 | | void (*initialize) (MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data); |
574 | | |
575 | | /* For the given type, copies the object data from the source memory |
576 | | * location to the destination one. Note that it may actually be more |
577 | | * involved than a straightforward bit of copying; what's important is |
578 | | * that the representation knows about that. Note that it may have to |
579 | | * call copy_to recursively on representations of any flattened objects |
580 | | * within its body. */ |
581 | | void (*copy_to) (MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest); |
582 | | |
583 | | /* Attribute access REPR function table. */ |
584 | | MVMREPROps_Attribute attr_funcs; |
585 | | |
586 | | /* Boxing REPR function table. */ |
587 | | MVMREPROps_Boxing box_funcs; |
588 | | |
589 | | /* Positional indexing REPR function table. */ |
590 | | MVMREPROps_Positional pos_funcs; |
591 | | |
592 | | /* Associative indexing REPR function table. */ |
593 | | MVMREPROps_Associative ass_funcs; |
594 | | |
595 | | /* Gets the number of elements, for any aggregate types. */ |
596 | | MVMuint64 (*elems) (MVMThreadContext *tc, MVMSTable *st, |
597 | | MVMObject *root, void *data); |
598 | | |
599 | | /* Gets the storage specification for this representation. */ |
600 | | const MVMStorageSpec * (*get_storage_spec) (MVMThreadContext *tc, MVMSTable *st); |
601 | | |
602 | | /* Handles an object changing its type. The representation is responsible |
603 | | * for doing any changes to the underlying data structure, and may reject |
604 | | * changes that it's not willing to do (for example, a representation may |
605 | | * choose to only handle switching to a subclass). It is also left to update |
606 | | * the S-Table pointer as needed; while in theory this could be factored |
607 | | * out, the representation probably knows more about timing issues and |
608 | | * thread safety requirements. */ |
609 | | void (*change_type) (MVMThreadContext *tc, MVMObject *object, MVMObject *new_type); |
610 | | |
611 | | /* Object serialization. Writes the object's body out using the passed |
612 | | * serialization writer. */ |
613 | | void (*serialize) (MVMThreadContext *tc, MVMSTable *st, void *data, MVMSerializationWriter *writer); |
614 | | |
615 | | /* Object deserialization. Reads the object's body in using the passed |
616 | | * serialization reader. */ |
617 | | void (*deserialize) (MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, MVMSerializationReader *reader); |
618 | | |
619 | | /* REPR data serialization. Serializes the per-type representation data that |
620 | | * is attached to the supplied STable. */ |
621 | | void (*serialize_repr_data) (MVMThreadContext *tc, MVMSTable *st, MVMSerializationWriter *writer); |
622 | | |
623 | | /* REPR data deserialization. Deserializes the per-type representation data and |
624 | | * attaches it to the supplied STable. */ |
625 | | void (*deserialize_repr_data) (MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader); |
626 | | |
627 | | /* Deserialization of STable size. */ |
628 | | void (*deserialize_stable_size) (MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader); |
629 | | |
630 | | /* MoarVM-specific REPR API addition used to mark an object. This involves |
631 | | * adding all pointers it contains to the worklist. */ |
632 | | void (*gc_mark) (MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist); |
633 | | |
634 | | /* MoarVM-specific REPR API addition used to free an object. */ |
635 | | void (*gc_free) (MVMThreadContext *tc, MVMObject *object); |
636 | | |
637 | | /* This is called to do any cleanup of resources when an object gets |
638 | | * embedded inside another one. Never called on a top-level object. */ |
639 | | void (*gc_cleanup) (MVMThreadContext *tc, MVMSTable *st, void *data); |
640 | | |
641 | | /* MoarVM-specific REPR API addition used to mark a REPR instance. */ |
642 | | void (*gc_mark_repr_data) (MVMThreadContext *tc, MVMSTable *st, MVMGCWorklist *worklist); |
643 | | |
644 | | /* MoarVM-specific REPR API addition used to free a REPR instance. */ |
645 | | void (*gc_free_repr_data) (MVMThreadContext *tc, MVMSTable *st); |
646 | | |
647 | | /* Causes the representation to be composed. Composition involves |
648 | | * passing the representation information that it needs in order |
649 | | * to compute memory layout. */ |
650 | | void (*compose) (MVMThreadContext *tc, MVMSTable *st, MVMObject *info); |
651 | | |
652 | | /* Allows the REPR to produce specialized bytecode versions of various |
653 | | * instructions, when we know some of the types involved. */ |
654 | | void (*spesh) (MVMThreadContext *tc, MVMSTable *st, MVMSpeshGraph *g, |
655 | | MVMSpeshBB *bb, MVMSpeshIns *ins); |
656 | | |
657 | | /* The representation's name. */ |
658 | | const char *name; |
659 | | |
660 | | /* The representation's ID. */ |
661 | | MVMuint32 ID; |
662 | | |
663 | | /* Optional API, for representations that allocate additonal memory and |
664 | | * want to report its size for debugging purposes. */ |
665 | | MVMuint64 (*unmanaged_size) (MVMThreadContext *tc, MVMSTable *st, void *data); |
666 | | |
667 | | /* Optional API to describe references to other Collectables either by |
668 | | * index or by name, i.E. names of attributes or lexicals. */ |
669 | | void (*describe_refs) (MVMThreadContext *tc, MVMHeapSnapshotState *ss, MVMSTable *st, void *data); |
670 | | }; |
671 | | |
672 | | /* Various handy macros for getting at important stuff. */ |
673 | | #define STABLE(o) (((MVMObject *)(o))->st) |
674 | | #define REPR(o) (STABLE((o))->REPR) |
675 | | #define OBJECT_BODY(o) (&(((MVMObjectStooge *)(o))->data)) |
676 | | |
677 | | /* Macros for getting/setting type-objectness. */ |
678 | | #define IS_CONCRETE(o) (!(((MVMObject *)o)->header.flags & MVM_CF_TYPE_OBJECT)) |
679 | | |
680 | | /* Some functions related to 6model core functionality. */ |
681 | | MVM_PUBLIC MVMObject * MVM_6model_get_how(MVMThreadContext *tc, MVMSTable *st); |
682 | | MVM_PUBLIC MVMObject * MVM_6model_get_how_obj(MVMThreadContext *tc, MVMObject *obj); |
683 | | void MVM_6model_find_method(MVMThreadContext *tc, MVMObject *obj, MVMString *name, |
684 | | MVMRegister *res, MVMint64 throw_if_not_found); |
685 | | MVM_PUBLIC MVMObject * MVM_6model_find_method_cache_only(MVMThreadContext *tc, MVMObject *obj, MVMString *name); |
686 | | MVMint32 MVM_6model_find_method_spesh(MVMThreadContext *tc, MVMObject *obj, MVMString *name, |
687 | | MVMint32 ss_idx, MVMRegister *res); |
688 | | MVMint64 MVM_6model_can_method_cache_only(MVMThreadContext *tc, MVMObject *obj, MVMString *name); |
689 | | void MVM_6model_can_method(MVMThreadContext *tc, MVMObject *obj, MVMString *name, MVMRegister *res); |
690 | | void MVM_6model_istype(MVMThreadContext *tc, MVMObject *obj, MVMObject *type, MVMRegister *res); |
691 | | MVM_PUBLIC MVMint64 MVM_6model_istype_cache_only(MVMThreadContext *tc, MVMObject *obj, MVMObject *type); |
692 | | MVMint64 MVM_6model_try_cache_type_check(MVMThreadContext *tc, MVMObject *obj, MVMObject *type, MVMint32 *result); |
693 | | void MVM_6model_invoke_default(MVMThreadContext *tc, MVMObject *invokee, MVMCallsite *callsite, MVMRegister *args); |
694 | | void MVM_6model_stable_gc_free(MVMThreadContext *tc, MVMSTable *st); |
695 | | MVMuint64 MVM_6model_next_type_cache_id(MVMThreadContext *tc); |
696 | | void MVM_6model_never_repossess(MVMThreadContext *tc, MVMObject *obj); |
697 | | |
698 | 0 | MVM_STATIC_INLINE char *MVM_6model_get_debug_name(MVMThreadContext *tc, MVMObject *obj) { |
699 | 0 | return STABLE(obj)->debug_name ? STABLE(obj)->debug_name : ""; |
700 | 0 | } |
701 | 0 | MVM_STATIC_INLINE char *MVM_6model_get_stable_debug_name(MVMThreadContext *tc, MVMSTable *stable) { |
702 | 0 | return stable->debug_name ? stable->debug_name : ""; |
703 | 0 | } |