@@ -11,6 +11,11 @@ class NQP::World is HLL::World {
11
11
# to a list of code objects.
12
12
has % ! code_objects_to_fix_up ;
13
13
14
+ # Mapping of PAST::Stmts node containing fixups, keyed by sub ID. If
15
+ # we do dynamic compilation then we do the fixups immediately and
16
+ # then clear this list.
17
+ has % ! code_object_fixup_list ;
18
+
14
19
# Creates a new lexical scope and puts it on top of the stack.
15
20
method push_lexpad ($/ ) {
16
21
# Create pad, link to outer and add to stack.
@@ -214,6 +219,7 @@ class NQP::World is HLL::World {
214
219
# list.
215
220
if $ have_code_type {
216
221
% ! code_objects_to_fix_up {$ past . subid()} := [$ dummy ];
222
+ % ! code_object_fixup_list {$ past . subid()} := $ fixups ;
217
223
if self . is_precompilation_mode() {
218
224
pir::setprop__vPsP($ dummy , ' CLONE_CALLBACK' , sub ($ orig , $ clone , $ code_obj ) {
219
225
% ! code_objects_to_fix_up {$ past . subid()}. push ($ code_obj );
@@ -222,19 +228,18 @@ class NQP::World is HLL::World {
222
228
else {
223
229
pir::setprop__vPsP($ dummy , ' CLONE_CALLBACK' , sub ($ orig , $ clone , $ code_obj ) {
224
230
# Emit fixup code.
225
- my $ clone_idx := self . add_root_code_ref($ clone , $ past );
226
231
self . add_object($ code_obj );
227
- $ fixups . push (PAST::Stmts. new (
228
- PAST::Op. new (
229
- : pirop(' assign vPP' ),
230
- self . get_slot_past_for_code_ref_at($ clone_idx ),
231
- PAST::Val. new ( : value(pir::getprop__PsP(' PAST' , $ orig )) )
232
- ),
232
+ $ fixups . push (PAST::Op. new (
233
+ : pirop(' setattribute vPPsP' ),
234
+ self . get_ref($ code_obj ),
235
+ self . get_ref($ code_type ),
236
+ ' $!do' ,
233
237
PAST::Op. new (
234
- : pirop(' set_sub_code_object vPP ' ),
235
- self . get_slot_past_for_code_ref_at( $ clone_idx ),
238
+ : pirop(' set_sub_code_object 0PP ' ),
239
+ PAST::Op . new ( : pirop( ' clone PP ' ), PAST::Val . new ( : value( $ past ) ) ),
236
240
self . get_ref($ code_obj )
237
- )));
241
+ )
242
+ ));
238
243
239
244
# Add to dynamic compilation fixup list.
240
245
% ! code_objects_to_fix_up {$ past . subid()}. push ($ code_obj );
@@ -243,14 +248,7 @@ class NQP::World is HLL::World {
243
248
}
244
249
}
245
250
246
- # For fixup, need to assign the method body we actually compiled
247
- # onto the one that went into the SC.
248
- $ fixups . push (PAST::Op. new (
249
- : pirop(' assign vPP' ),
250
- self . get_slot_past_for_code_ref_at($ code_ref_idx ),
251
- PAST::Val. new ( : value($ past ) )
252
- ));
253
-
251
+ # Add fixups task node; it'll get populated or cleared during the compile.
254
252
self . add_fixup_task(: fixup_past($ fixups ));
255
253
256
254
# Provided we have the code type, now wrap what we have up in a
@@ -263,22 +261,38 @@ class NQP::World is HLL::World {
263
261
if $ is_dispatcher ;
264
262
my $ slot := self . add_object($ code_obj );
265
263
266
- # Add fixup task.
264
+ # Add deserialization fixup task.
267
265
self . add_fixup_task(
268
266
: deserialize_past(PAST::Op. new (
269
267
: pirop(' set_sub_code_object vPP' ),
270
268
PAST::Val. new ( : value($ past ) ),
271
269
self . get_ref($ code_obj )
272
- )),
273
- : fixup_past(PAST::Op. new (
274
- : pirop(' set_sub_code_object vPP' ),
275
- self . get_slot_past_for_code_ref_at($ code_ref_idx ),
276
- self . get_ref($ code_obj )
277
270
)));
278
271
272
+ # Add fixup of the code object and the $!do attribute.
273
+ $ fixups . push (PAST::Op. new (
274
+ : pirop(' setattribute vPPsP' ),
275
+ self . get_ref($ code_obj ),
276
+ self . get_ref($ code_type ),
277
+ ' $!do' ,
278
+ PAST::Val. new ( : value($ past ) )
279
+ ));
280
+ $ fixups . push (PAST::Op. new (
281
+ : pirop(' set_sub_code_object vPP' ),
282
+ PAST::Val. new ( : value($ past ) ),
283
+ self . get_ref($ code_obj )
284
+ ));
285
+
279
286
$ code_obj
280
287
}
281
288
else {
289
+ # For fixup, if we have no code body, we need to assign the method body
290
+ # we actually compiled into the one that went into the SC.
291
+ $ fixups . push (PAST::Op. new (
292
+ : pirop(' assign vPP' ),
293
+ self . get_slot_past_for_code_ref_at($ code_ref_idx ),
294
+ PAST::Val. new ( : value($ past ) )
295
+ ));
282
296
return $ dummy ;
283
297
}
284
298
}
0 commit comments