/
P6opaque.h
126 lines (104 loc) · 5.05 KB
/
P6opaque.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* This is how an instance with the P6opaque representation starts. However, what
* follows on from this depends on the declaration. For object attributes, it will
* be a pointer size and point to another MVMObject. For native integers and
* numbers, it will be the appropriate sized piece of memory to store them
* right there in the object. Note that P6opaque does not do packed storage, so
* an int2 gets as much space as an int. */
struct MVMP6opaqueBody {
/* If we get mixed into, we may change size. If so, we can't really resize
* the object, so instead we hang its post-resize form off this pointer.
* In the future, more clever things are possible (like only putting the
* new fields into this object). */
void *replaced;
};
struct MVMP6opaque {
MVMObject common;
MVMP6opaqueBody body;
};
/* This is used in the name to slot mapping. Indicates the class key that
* we have the mappings for, followed by arrays of names and slots. (Yeah,
* could use a hash, but much code will resolve these statically to the
* slots). */
struct MVMP6opaqueNameMap {
MVMObject *class_key;
MVMString **names;
MVMuint16 *slots;
MVMuint32 num_attrs;
};
/* The P6opaque REPR data has the slot mapping, allocation size and
* various other bits of info. It hangs off the REPR_data pointer
* in the s-table. */
struct MVMP6opaqueREPRData {
/* The number of attributes we have allocated slots for. Note that
* slots can vary in size. */
MVMuint16 num_attributes;
/* Slot containing object to delegate for positional things. */
MVMint16 pos_del_slot;
/* Slot containing object to delegate for associative things. */
MVMint16 ass_del_slot;
/* Flags if we are MI or not. */
MVMuint16 mi;
/* Slot to delegate to when we need to unbox to a native integer. */
MVMint16 unbox_int_slot;
/* Slot to delegate to when we need to unbox to a native number. */
MVMint16 unbox_num_slot;
/* Slot to delegate to when we need to unbox to a native string. */
MVMint16 unbox_str_slot;
/* Offsets into the object that are eligible for GC marking, and how
* many of them we have. */
MVMuint16 gc_obj_mark_offsets_count;
MVMuint16 *gc_obj_mark_offsets;
/* Maps attribute position numbers to the byte offset in the object. */
MVMuint16 *attribute_offsets;
/* If the attribute was actually flattened in to this object from another
* representation, this is the s-table of the type of that attribute. NULL
* for attributes that are just reference types. */
MVMSTable **flattened_stables;
/* Instantiated objects are just a blank piece of memory that needs to
* be set up. However, in some cases we'd like them to magically turn in
* to some container type. */
MVMObject **auto_viv_values;
/* If we have any other flattened boxings, this array can be indexed by
* REPR ID to find the slot in the object where it is embedded. */
MVMuint16 *unbox_slots;
/* A table mapping attribute names to indexes (which can then be looked
* up in the offset table). Uses a final null entry as a sentinel. */
MVMP6opaqueNameMap *name_to_index_mapping;
/* Slots holding flattened objects that need another REPR to initialize
* them; terminated with -1. */
MVMint16 *initialize_slots;
/* Slots holding flattened objects that need another REPR to mark them;
* terminated with -1. */
MVMint16 *gc_mark_slots;
/* Slots holding flattened objects that need another REPR to clean them;
* terminated with -1. */
MVMint16 *gc_cleanup_slots;
/* Hold the storage spec */
MVMStorageSpec storage_spec;
};
/* Function for REPR setup. */
const MVMREPROps * MVMP6opaque_initialize(MVMThreadContext *tc);
/* If an object gets mixed in to, we need to be sure we look at its real body,
* which may have been moved to hang off the specified pointer.
*
* NB: This has been hardcoded into the jit compilation. Thus, consider it
* set into stone :-). That is the price you pay for disintermediation. */
MVM_STATIC_INLINE void * MVM_p6opaque_real_data(MVMThreadContext *tc, void *data) {
MVMP6opaqueBody *body = (MVMP6opaqueBody *)data;
return body->replaced ? body->replaced : data;
}
/* Reads an attribute using an offset. This is only safe on an exact type
* match. */
MVM_STATIC_INLINE MVMObject * MVM_p6opaque_read_object(MVMThreadContext *tc,
MVMObject *o, size_t offset) {
char *data = MVM_p6opaque_real_data(tc, OBJECT_BODY(o));
return *((MVMObject **)(data + offset));
}
MVM_STATIC_INLINE MVMint64 MVM_p6opaque_read_int64(MVMThreadContext *tc,
MVMObject *o, size_t offset) {
char *data = MVM_p6opaque_real_data(tc, OBJECT_BODY(o));
return *((MVMint64 *)(data + offset));
}
size_t MVM_p6opaque_attr_offset(MVMThreadContext *tc, MVMObject *type,
MVMObject *class_handle, MVMString *name);
void MVM_P6opaque_at_pos(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, MVMint64 index, MVMRegister *value, MVMuint16 kind);