Skip to content
This repository was archived by the owner on Feb 3, 2021. It is now read-only.

Commit 26ac097

Browse files
committed
Get P6opaque most of the way to consuming the storage spec provided by a REPR. In theory, this means it can allocate storage for natively typed attributes. In practice, there's no way to test this just yet.
1 parent 4d75922 commit 26ac097

File tree

1 file changed

+71
-12
lines changed

1 file changed

+71
-12
lines changed

src/metamodel/reprs/P6opaque.c

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,18 @@ static PMC * repr_instance(PARROT_INTERP);
1717
* never move, and is unique per type object too. */
1818
#define CLASS_KEY(c) ((INTVAL)PMC_data(STABLE_PMC(c)))
1919

20-
/* Helper to make a :local introspection call. */
20+
/* Helper to make an introspection call, possibly with :local. */
2121
static PMC * introspection_call(PARROT_INTERP, PMC *WHAT, PMC *HOW, STRING *name) {
22-
/* Look up method. */
22+
PMC *old_ctx, *cappy;
23+
24+
/* Look up method; if there is none hand back a null. */
2325
PMC *meth = VTABLE_find_method(interp, HOW, name);
26+
if (PMC_IS_NULL(meth))
27+
return meth;
2428

2529
/* Set up call capture. */
26-
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
27-
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
30+
old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
31+
cappy = Parrot_pmc_new(interp, enum_class_CallContext);
2832
VTABLE_push_pmc(interp, cappy, HOW);
2933
VTABLE_push_pmc(interp, cappy, WHAT);
3034
VTABLE_set_integer_keyed_str(interp, cappy, Parrot_str_new_constant(interp, "local"), 1);
@@ -40,12 +44,16 @@ static PMC * introspection_call(PARROT_INTERP, PMC *WHAT, PMC *HOW, STRING *name
4044

4145
/* Helper to make an accessor call. */
4246
static PMC * accessor_call(PARROT_INTERP, PMC *obj, STRING *name) {
43-
/* Look up method. */
47+
PMC *old_ctx, *cappy;
48+
49+
/* Look up method; if there is none hand back a null. */
4450
PMC *meth = VTABLE_find_method(interp, obj, name);
51+
if (PMC_IS_NULL(meth))
52+
return meth;
4553

4654
/* Set up call capture. */
47-
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
48-
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
55+
old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
56+
cappy = Parrot_pmc_new(interp, enum_class_CallContext);
4957
VTABLE_push_pmc(interp, cappy, obj);
5058

5159
/* Call. */
@@ -136,6 +144,9 @@ static PMC * index_mapping_and_flat_list(PARROT_INTERP, PMC *WHAT, PMC *flat_lis
136144
* notable limitation is that in the case of multiple inheritance, the box
137145
* and unbox support breaks. */
138146
static void compute_allocation_strategy(PARROT_INTERP, PMC *WHAT, REPRP6opaque *repr) {
147+
STRING *type_str = Parrot_str_new_constant(interp, "type");
148+
STRING *box_target_str = Parrot_str_new_constant(interp, "box_target");
149+
139150
/* Create flat list that we'll analyze to determine allocation info. */
140151
PMC *flat_list = pmc_new(interp, enum_class_ResizablePMCArray);
141152

@@ -170,12 +181,60 @@ static void compute_allocation_strategy(PARROT_INTERP, PMC *WHAT, REPRP6opaque *
170181
/* Go over the attributes and arrange their allocation. */
171182
for (i = 0; i < num_attrs; i++) {
172183
PMC *attr = VTABLE_get_pmc_keyed_int(interp, flat_list, i);
173-
/* XXX TODO: Here's where we'll deal with the native stuff. For
174-
* now it's always an object attr, though. */
184+
185+
/* Fetch its type and box target flag, if available. */
186+
PMC *type = accessor_call(interp, attr, type_str);
187+
PMC *box_target = accessor_call(interp, attr, box_target_str);
188+
189+
/* Work out what unboxed type it is, if any. Default to a boxed. */
190+
INTVAL unboxed_type = STORAGE_SPEC_BP_NONE;
191+
INTVAL bits = sizeof(PMC *) * 8;
192+
if (!PMC_IS_NULL(type)) {
193+
/* Get the storage spec of the type and see what it wants. */
194+
storage_spec spec = REPR(type)->get_storage_spec(interp, REPR_PMC(type));
195+
if (spec.inlineable == STORAGE_SPEC_INLINED) {
196+
/* Yes, it's something we'll inline. */
197+
unboxed_type = spec.boxed_primitive;
198+
bits = spec.bits;
199+
200+
/* Is it a target for box/unbox operations? */
201+
if (VTABLE_get_bool(interp, box_target)) {
202+
switch (unboxed_type) {
203+
case STORAGE_SPEC_BP_INT:
204+
if (repr->unbox_int_offset)
205+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
206+
"Duplicate box_target for native int");
207+
repr->unbox_int_offset = cur_size;
208+
break;
209+
case STORAGE_SPEC_BP_NUM:
210+
if (repr->unbox_num_offset)
211+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
212+
"Duplicate box_target for native num");
213+
repr->unbox_num_offset = cur_size;
214+
break;
215+
case STORAGE_SPEC_BP_STR:
216+
if (repr->unbox_str_offset)
217+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
218+
"Duplicate box_target for native str");
219+
repr->unbox_str_offset = cur_size;
220+
break;
221+
}
222+
}
223+
}
224+
}
225+
226+
/* Do allocation. */
175227
repr->attribute_offsets[i] = cur_size;
176-
repr->gc_pmc_mark_offsets[cur_pmc_attr] = cur_size;
177-
cur_size += sizeof(PMC *);
178-
cur_pmc_attr++;
228+
if (unboxed_type == STORAGE_SPEC_BP_NONE) {
229+
repr->gc_pmc_mark_offsets[cur_pmc_attr] = cur_size;
230+
cur_pmc_attr++;
231+
}
232+
if (unboxed_type == STORAGE_SPEC_BP_STR) {
233+
repr->gc_str_mark_offsets[cur_str_attr] = cur_size;
234+
cur_str_attr++;
235+
}
236+
/* XXX TODO Alignment! Important when we get int1, int8, etc. */
237+
cur_size += bits / 8;
179238
}
180239

181240
/* Finally, put computed allocation size in place. */

0 commit comments

Comments
 (0)