Skip to content

Commit 92b0fbc

Browse files
committed
Bring the code object fixup mechanism in line with the one in Rakudo (essentially, it fixes up by setting the $!do rather than mucking round with assign vtable).
1 parent b9e1d10 commit 92b0fbc

File tree

1 file changed

+38
-24
lines changed

1 file changed

+38
-24
lines changed

src/NQP/World.pm

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ class NQP::World is HLL::World {
1111
# to a list of code objects.
1212
has %!code_objects_to_fix_up;
1313

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+
1419
# Creates a new lexical scope and puts it on top of the stack.
1520
method push_lexpad($/) {
1621
# Create pad, link to outer and add to stack.
@@ -214,6 +219,7 @@ class NQP::World is HLL::World {
214219
# list.
215220
if $have_code_type {
216221
%!code_objects_to_fix_up{$past.subid()} := [$dummy];
222+
%!code_object_fixup_list{$past.subid()} := $fixups;
217223
if self.is_precompilation_mode() {
218224
pir::setprop__vPsP($dummy, 'CLONE_CALLBACK', sub ($orig, $clone, $code_obj) {
219225
%!code_objects_to_fix_up{$past.subid()}.push($code_obj);
@@ -222,19 +228,18 @@ class NQP::World is HLL::World {
222228
else {
223229
pir::setprop__vPsP($dummy, 'CLONE_CALLBACK', sub ($orig, $clone, $code_obj) {
224230
# Emit fixup code.
225-
my $clone_idx := self.add_root_code_ref($clone, $past);
226231
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',
233237
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) ) ),
236240
self.get_ref($code_obj)
237-
)));
241+
)
242+
));
238243

239244
# Add to dynamic compilation fixup list.
240245
%!code_objects_to_fix_up{$past.subid()}.push($code_obj);
@@ -243,14 +248,7 @@ class NQP::World is HLL::World {
243248
}
244249
}
245250

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.
254252
self.add_fixup_task(:fixup_past($fixups));
255253

256254
# Provided we have the code type, now wrap what we have up in a
@@ -263,22 +261,38 @@ class NQP::World is HLL::World {
263261
if $is_dispatcher;
264262
my $slot := self.add_object($code_obj);
265263

266-
# Add fixup task.
264+
# Add deserialization fixup task.
267265
self.add_fixup_task(
268266
:deserialize_past(PAST::Op.new(
269267
:pirop('set_sub_code_object vPP'),
270268
PAST::Val.new( :value($past) ),
271269
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)
277270
)));
278271

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+
279286
$code_obj
280287
}
281288
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+
));
282296
return $dummy;
283297
}
284298
}

0 commit comments

Comments
 (0)