1
1
/* A mostly complete implementation of P6opaque, which supports inlining native
2
2
* types, box/unbox of native types where it's declared possible and doing just
3
- * a single memory allocation in addition to the PMC header per object. */
3
+ * a single memory allocation in addition to the PMC header per object. For
4
+ * single inheritance, memory is laid out parent to child, so that the slot
5
+ * given to an attribute with be valid in all SI subclasses. For MI we just
6
+ * go with the MRO to do slot allocations, but we never allow an actual index
7
+ * lookup with a hint to take place and always slow-path it. */
4
8
5
9
#define PARROT_IN_EXTENSION
6
10
#include "parrot/parrot.h"
@@ -17,7 +21,7 @@ static PMC *this_repr;
17
21
#define CLASS_KEY (c ) ((INTVAL)PMC_data(STABLE_PMC(c)))
18
22
19
23
/* Helper to make an introspection call, possibly with :local. */
20
- static PMC * introspection_call (PARROT_INTERP , PMC * WHAT , PMC * HOW , STRING * name ) {
24
+ static PMC * introspection_call (PARROT_INTERP , PMC * WHAT , PMC * HOW , STRING * name , INTVAL local ) {
21
25
PMC * old_ctx , * cappy ;
22
26
23
27
/* Look up method; if there is none hand back a null. */
@@ -30,7 +34,8 @@ static PMC * introspection_call(PARROT_INTERP, PMC *WHAT, PMC *HOW, STRING *name
30
34
cappy = Parrot_pmc_new (interp , enum_class_CallContext );
31
35
VTABLE_push_pmc (interp , cappy , HOW );
32
36
VTABLE_push_pmc (interp , cappy , WHAT );
33
- VTABLE_set_integer_keyed_str (interp , cappy , Parrot_str_new_constant (interp , "local" ), 1 );
37
+ if (local )
38
+ VTABLE_set_integer_keyed_str (interp , cappy , Parrot_str_new_constant (interp , "local" ), 1 );
34
39
35
40
/* Call. */
36
41
Parrot_pcc_invoke_from_sig_object (interp , meth , cappy );
@@ -66,32 +71,37 @@ static PMC * accessor_call(PARROT_INTERP, PMC *obj, STRING *name) {
66
71
67
72
/* Locates all of the attributes. Puts them onto a flattened, ordered
68
73
* list of attributes (populating the passed flat_list). Also builds
69
- * the index mapping for doing named lookups. If there is multiple
70
- * inheritance, returns an empty index mapping, which indicates that
71
- * everything will be looked up in spill. Otherwise returns a
72
- * populated name to index mapping. Note index is not related to the
73
- * storage position. */
74
+ * the index mapping for doing named lookups. Note index is not related
75
+ * to the storage position. */
74
76
P6opaqueNameMap * index_mapping_and_flat_list (PARROT_INTERP , PMC * WHAT , PMC * flat_list ) {
75
77
PMC * class_list = pmc_new (interp , enum_class_ResizablePMCArray );
76
78
PMC * attr_map_list = pmc_new (interp , enum_class_ResizablePMCArray );
77
- PMC * current_class = WHAT ;
78
- INTVAL current_slot = 0 ;
79
79
STRING * attributes_str = Parrot_str_new_constant (interp , "attributes" );
80
80
STRING * parents_str = Parrot_str_new_constant (interp , "parents" );
81
81
STRING * name_str = Parrot_str_new_constant (interp , "name" );
82
- INTVAL i , num_classes ;
83
-
82
+ STRING * mro_str = Parrot_str_new_constant (interp , "mro" );
83
+ INTVAL current_slot = 0 ;
84
+
85
+ INTVAL num_classes , i ;
84
86
P6opaqueNameMap * result = NULL ;
87
+
88
+ /* Get the MRO. */
89
+ PMC * mro = introspection_call (interp , WHAT , STABLE (WHAT )-> HOW , mro_str , 0 );
90
+ INTVAL mro_idx = VTABLE_elements (interp , mro );
85
91
86
92
/* Walk through the parents list. */
87
- while (! PMC_IS_NULL ( current_class ) )
93
+ while (mro_idx )
88
94
{
89
- PMC * parents ;
90
- INTVAL num_parents ;
95
+ /* Get current class in MRO. */
96
+ PMC * current_class = VTABLE_get_pmc_keyed_int (interp , mro , -- mro_idx );
97
+ PMC * HOW = STABLE (current_class )-> HOW ;
98
+
99
+ /* Get its local parents. */
100
+ PMC * parents = introspection_call (interp , current_class , HOW , parents_str , 1 );
101
+ INTVAL num_parents = VTABLE_elements (interp , parents );
91
102
92
103
/* Get attributes and iterate over them. */
93
- PMC * HOW = STABLE (current_class )-> HOW ;
94
- PMC * attributes = introspection_call (interp , current_class , HOW , attributes_str );
104
+ PMC * attributes = introspection_call (interp , current_class , HOW , attributes_str , 1 );
95
105
PMC * attr_map = PMCNULL ;
96
106
PMC * attr_iter = VTABLE_get_iter (interp , attributes );
97
107
while (VTABLE_get_bool (interp , attr_iter )) {
@@ -117,26 +127,9 @@ P6opaqueNameMap * index_mapping_and_flat_list(PARROT_INTERP, PMC *WHAT, PMC *fla
117
127
VTABLE_push_pmc (interp , class_list , current_class );
118
128
VTABLE_push_pmc (interp , attr_map_list , attr_map );
119
129
120
- /* Find the next parent(s). */
121
- parents = introspection_call (interp , current_class , HOW , parents_str );
122
-
123
- /* Check how many parents we have. */
124
- num_parents = VTABLE_elements (interp , parents );
125
- if (num_parents == 0 )
126
- {
127
- /* We're done. \o/ */
128
- break ;
129
- }
130
- else if (num_parents > 1 )
131
- {
132
- /* Multiple inheritnace, so we can't compute this hierarchy. */
133
- return (P6opaqueNameMap * ) mem_sys_allocate_zeroed (sizeof (P6opaqueNameMap ));
134
- }
135
- else
136
- {
137
- /* Just one. Get next parent and work through its attributes. */
138
- current_class = decontainerize (interp , VTABLE_get_pmc_keyed_int (interp , parents , 0 ));
139
- }
130
+ /* If there's more than one parent, flag that we in an
131
+ * MI situation. */
132
+
140
133
}
141
134
142
135
/* We can now form the name map. */
@@ -150,12 +143,9 @@ P6opaqueNameMap * index_mapping_and_flat_list(PARROT_INTERP, PMC *WHAT, PMC *fla
150
143
return result ;
151
144
}
152
145
153
- /* This works out an allocation strategy for the object. It can do best when
154
- * single inheritance is used, in which case it just stores the attributes
155
- * contiguously in memory. It takes care of "inlining" storage of attributes
156
- * that are natively typed, as well as noting unbox targets. One current
157
- * notable limitation is that in the case of multiple inheritance, the box
158
- * and unbox support breaks. */
146
+ /* This works out an allocation strategy for the object. It takes care of
147
+ * "inlining" storage of attributes that are natively typed, as well as
148
+ * noting unbox targets. */
159
149
static void compute_allocation_strategy (PARROT_INTERP , PMC * WHAT , P6opaqueREPRData * repr_data ) {
160
150
STRING * type_str = Parrot_str_new_constant (interp , "type" );
161
151
STRING * box_target_str = Parrot_str_new_constant (interp , "box_target" );
@@ -179,9 +169,7 @@ static void compute_allocation_strategy(PARROT_INTERP, PMC *WHAT, P6opaqueREPRDa
179
169
/* Compute index mapping table and get flat list of attributes. */
180
170
repr_data -> name_to_index_mapping = index_mapping_and_flat_list (interp , WHAT , flat_list );
181
171
182
- /* If we have no attributes in the index mapping, then our allocation stratergy
183
- * is that everything goes into the spill hash. The size to allocate is just
184
- * two pointers - a shared table pointer and one for the spill hash. */
172
+ /* If we have no attributes in the index mapping, then just the header. */
185
173
if (repr_data -> name_to_index_mapping [0 ].class_key == NULL ) {
186
174
repr_data -> allocation_size = sizeof (SixModelObjectCommonalities ) + sizeof (PMC * );
187
175
}
0 commit comments