@@ -17,14 +17,18 @@ static PMC * repr_instance(PARROT_INTERP);
17
17
* never move, and is unique per type object too. */
18
18
#define CLASS_KEY (c ) ((INTVAL)PMC_data(STABLE_PMC(c)))
19
19
20
- /* Helper to make a :local introspection call. */
20
+ /* Helper to make an introspection call, possibly with :local . */
21
21
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. */
23
25
PMC * meth = VTABLE_find_method (interp , HOW , name );
26
+ if (PMC_IS_NULL (meth ))
27
+ return meth ;
24
28
25
29
/* 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 );
28
32
VTABLE_push_pmc (interp , cappy , HOW );
29
33
VTABLE_push_pmc (interp , cappy , WHAT );
30
34
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
40
44
41
45
/* Helper to make an accessor call. */
42
46
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. */
44
50
PMC * meth = VTABLE_find_method (interp , obj , name );
51
+ if (PMC_IS_NULL (meth ))
52
+ return meth ;
45
53
46
54
/* 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 );
49
57
VTABLE_push_pmc (interp , cappy , obj );
50
58
51
59
/* Call. */
@@ -136,6 +144,9 @@ static PMC * index_mapping_and_flat_list(PARROT_INTERP, PMC *WHAT, PMC *flat_lis
136
144
* notable limitation is that in the case of multiple inheritance, the box
137
145
* and unbox support breaks. */
138
146
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
+
139
150
/* Create flat list that we'll analyze to determine allocation info. */
140
151
PMC * flat_list = pmc_new (interp , enum_class_ResizablePMCArray );
141
152
@@ -170,12 +181,60 @@ static void compute_allocation_strategy(PARROT_INTERP, PMC *WHAT, REPRP6opaque *
170
181
/* Go over the attributes and arrange their allocation. */
171
182
for (i = 0 ; i < num_attrs ; i ++ ) {
172
183
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. */
175
227
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 ;
179
238
}
180
239
181
240
/* Finally, put computed allocation size in place. */
0 commit comments