Skip to content

Commit 1c216a2

Browse files
committed
Start to refactor the multi method handling in NQP::World to not rely on DispatcherSub. Not completely done yet; breaks multi-method tests. However, it's enough to get compilation further with the new serializer.
1 parent b103371 commit 1c216a2

File tree

1 file changed

+40
-18
lines changed

1 file changed

+40
-18
lines changed

src/NQP/World.pm

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class NQP::World is HLL::World {
215215
# Registers a code object, and gives it a dynamic compilation thunk.
216216
# Makes a real code object if it's a dispatcher.
217217
method create_code($past, $name, $is_dispatcher) {
218-
# For methods, we need a "stub" that we'll clone and use for the
218+
# For code refs, we need a "stub" that we'll clone and use for the
219219
# compile-time representation. If it ever gets invoked it'll go
220220
# and compile the code and run it.
221221
# XXX Lexical environment.
@@ -233,13 +233,7 @@ class NQP::World is HLL::World {
233233
$dummy := $past<compile_time_dummy>;
234234
}
235235
else {
236-
# What we create depends on whether it's a dispatcher or not.
237-
# If it is a dispatcher, set the PMC type it uses and then use
238-
# that for the dummy.
239-
if $is_dispatcher {
240-
$past.pirflags(':instanceof("DispatcherSub")');
241-
$dummy := pir::assign__0PP(pir::new__Ps('DispatcherSub'), $stub_code);
242-
236+
if $is_dispatcher && !$NEW_SER {
243237
# The dispatcher will get cloned if more candidates are added in
244238
# a subclass; this makes sure that we fix up the clone also.
245239
pir::setprop__vPsP($dummy, 'CLONE_CALLBACK', sub ($orig, $clone) {
@@ -251,9 +245,7 @@ class NQP::World is HLL::World {
251245
));
252246
});
253247
}
254-
else {
255-
$dummy := pir::clone__PP($stub_code);
256-
}
248+
$dummy := pir::clone__PP($stub_code);
257249
pir::assign__vPS($dummy, $name);
258250
if $NEW_SER {
259251
pir::setprop__vPsP($dummy, 'STATIC_CODE_REF', $dummy);
@@ -269,8 +261,7 @@ class NQP::World is HLL::World {
269261
pir::setprop__vPsP($dummy, 'PAST', $past);
270262

271263
# For fixup, need to assign the method body we actually compiled
272-
# onto the one that went into the SC. Deserializing is easier -
273-
# just the straight meta-method call.
264+
# onto the one that went into the SC.
274265
if $NEW_SER {
275266
$fixups.push(PAST::Op.new(
276267
:pirop('assign vPP'),
@@ -286,8 +277,39 @@ class NQP::World is HLL::World {
286277
self.add_fixup_task(:fixup_past($fixups));
287278
}
288279

289-
# Hand back the code object.
290-
return $dummy;
280+
# If it's a dispatcher, now need to wrap it in a code object,
281+
# so we have a place to store the dispatch list.
282+
if $is_dispatcher {
283+
# Create it now.
284+
my $code_type := self.find_sym(['NQPRoutine']);
285+
my $code_obj := nqp::create($code_type);
286+
nqp::bindattr($code_obj, $code_type, '$!do', $dummy);
287+
nqp::bindattr($code_obj, $code_type, '$!dispatchees', nqp::list());
288+
my $slot := self.add_object($code_obj);
289+
290+
# Deserialization code.
291+
unless $NEW_SER {
292+
self.add_fixup_task(:deserialize_past(PAST::Stmts.new(
293+
self.add_object_to_cur_sc_past($slot,
294+
PAST::Op.new( :pirop('repr_instance_of__PP'), self.get_ref($code_type) )),
295+
PAST::Op.new( :pirop('setattribute__vPPsP'),
296+
self.get_ref($code_obj),
297+
self.get_ref($code_type),
298+
'$!do',
299+
PAST::Val.new( :value($past) )),
300+
PAST::Op.new( :pirop('setattribute__vPPsP'),
301+
self.get_ref($code_obj),
302+
self.get_ref($code_type),
303+
'$!dispatchees',
304+
PAST::Op.new( :pasttype('list') ))
305+
)));
306+
}
307+
308+
$code_obj
309+
}
310+
else {
311+
return $dummy;
312+
}
291313
}
292314

293315
# Creates a meta-object for a package, adds it to the root objects and
@@ -365,9 +387,9 @@ class NQP::World is HLL::World {
365387
# Deserialization code - goes away with new serializer.
366388
unless $NEW_SER {
367389
my $slot_past := self.get_slot_past_for_object($obj);
368-
my $code_past := pir::getprop__PsP('PAST', $code) ??
369-
PAST::Val.new( :value(pir::getprop__PsP('PAST', $code)) ) !!
370-
self.get_slot_past_for_object($code);
390+
my $code_past := nqp::isnull(pir::getprop__PsP('PAST', $code)) ??
391+
self.get_slot_past_for_object($code) !!
392+
PAST::Val.new( :value(pir::getprop__PsP('PAST', $code)) );
371393
self.add_fixup_task(
372394
:deserialize_past(PAST::Op.new(
373395
:pasttype('callmethod'), :name($meta_method_name),

0 commit comments

Comments
 (0)