Skip to content

Commit f14f5b6

Browse files
committed
Refactor P6opaque a bit so that we can handle multiple inheritance.
1 parent 26c3c1c commit f14f5b6

File tree

1 file changed

+34
-46
lines changed

1 file changed

+34
-46
lines changed

src/6model/reprs/P6opaque.c

Lines changed: 34 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
/* A mostly complete implementation of P6opaque, which supports inlining native
22
* 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. */
48

59
#define PARROT_IN_EXTENSION
610
#include "parrot/parrot.h"
@@ -17,7 +21,7 @@ static PMC *this_repr;
1721
#define CLASS_KEY(c) ((INTVAL)PMC_data(STABLE_PMC(c)))
1822

1923
/* 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) {
2125
PMC *old_ctx, *cappy;
2226

2327
/* 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
3034
cappy = Parrot_pmc_new(interp, enum_class_CallContext);
3135
VTABLE_push_pmc(interp, cappy, HOW);
3236
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);
3439

3540
/* Call. */
3641
Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
@@ -66,32 +71,37 @@ static PMC * accessor_call(PARROT_INTERP, PMC *obj, STRING *name) {
6671

6772
/* Locates all of the attributes. Puts them onto a flattened, ordered
6873
* 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. */
7476
P6opaqueNameMap * index_mapping_and_flat_list(PARROT_INTERP, PMC *WHAT, PMC *flat_list) {
7577
PMC *class_list = pmc_new(interp, enum_class_ResizablePMCArray);
7678
PMC *attr_map_list = pmc_new(interp, enum_class_ResizablePMCArray);
77-
PMC *current_class = WHAT;
78-
INTVAL current_slot = 0;
7979
STRING *attributes_str = Parrot_str_new_constant(interp, "attributes");
8080
STRING *parents_str = Parrot_str_new_constant(interp, "parents");
8181
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;
8486
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);
8591

8692
/* Walk through the parents list. */
87-
while (!PMC_IS_NULL(current_class))
93+
while (mro_idx)
8894
{
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);
91102

92103
/* 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);
95105
PMC *attr_map = PMCNULL;
96106
PMC *attr_iter = VTABLE_get_iter(interp, attributes);
97107
while (VTABLE_get_bool(interp, attr_iter)) {
@@ -117,26 +127,9 @@ P6opaqueNameMap * index_mapping_and_flat_list(PARROT_INTERP, PMC *WHAT, PMC *fla
117127
VTABLE_push_pmc(interp, class_list, current_class);
118128
VTABLE_push_pmc(interp, attr_map_list, attr_map);
119129

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+
140133
}
141134

142135
/* We can now form the name map. */
@@ -150,12 +143,9 @@ P6opaqueNameMap * index_mapping_and_flat_list(PARROT_INTERP, PMC *WHAT, PMC *fla
150143
return result;
151144
}
152145

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. */
159149
static void compute_allocation_strategy(PARROT_INTERP, PMC *WHAT, P6opaqueREPRData *repr_data) {
160150
STRING *type_str = Parrot_str_new_constant(interp, "type");
161151
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
179169
/* Compute index mapping table and get flat list of attributes. */
180170
repr_data->name_to_index_mapping = index_mapping_and_flat_list(interp, WHAT, flat_list);
181171

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. */
185173
if (repr_data->name_to_index_mapping[0].class_key == NULL) {
186174
repr_data->allocation_size = sizeof(SixModelObjectCommonalities) + sizeof(PMC *);
187175
}

0 commit comments

Comments
 (0)