Skip to content

Commit 86a9537

Browse files
committed
[truffle] Stub things up for deserialization
More deserialization will be filled in later
1 parent d8d27a8 commit 86a9537

16 files changed

+1287
-35
lines changed

src/NQP/World.nqp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ class NQP::World is HLL::World {
101101
QAST::VM.new(
102102
:jvm(QAST::SVal.new( :value('ModuleLoader.class') )),
103103
:moar(QAST::SVal.new( :value('ModuleLoader.moarvm') )),
104-
:js(QAST::SVal.new( :value('ModuleLoader') ))
104+
:truffle(QAST::SVal.new( :value('ModuleLoader.truffle6') )),
105+
:js(QAST::SVal.new( :value('ModuleLoader') )),
105106
)
106107
),
107108
),

src/vm/jvm/QAST/Compiler.nqp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3617,10 +3617,19 @@ class QAST::CompilerJAST {
36173617
return 0;
36183618
}
36193619

3620-
method deserialization_code($sc, @code_ref_blocks, $repo_conf_res) {
3621-
# Serialize it.
3620+
# This method is a hook point so that we can override serialization when cross-compiling
3621+
method serialize_sc($sc) {
36223622
my $sh := nqp::list_s();
36233623
my $serialized := nqp::serialize($sc, $sh);
3624+
[$serialized, $sh];
3625+
}
3626+
3627+
method deserialization_code($sc, @code_ref_blocks, $repo_conf_res) {
3628+
# Serialize it.
3629+
3630+
my $sc_tuple := self.serialize_sc($sc);
3631+
my $serialized := $sc_tuple[0];
3632+
my $sh := $sc_tuple[1];
36243633

36253634
if %*COMPILING<%?OPTIONS><target> eq 'jar' {
36263635
$*JCLASS.serialized($serialized);

src/vm/jvm/Truffle.nqp

Lines changed: 190 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ class QAST::OperationsTruffle {
135135
});
136136
}
137137

138+
add_simple_op('createsc', $OBJ, [$STR]);
139+
add_simple_op('scsetdesc', $STR, [$OBJ, $STR]);
140+
add_simple_op('deserialize', $STR, [$STR, $OBJ, $OBJ, $OBJ, $OBJ]);
141+
138142
add_simple_op('die', $VOID, [$STR]);
139143
%ops<die_s> := %ops<die>;
140144

@@ -146,6 +150,9 @@ class QAST::OperationsTruffle {
146150
add_simple_op('gethllsym', $OBJ, [$STR, $STR]);
147151
add_simple_op('bindhllsym', $OBJ, [$STR, $STR, $OBJ]);
148152

153+
add_simple_op('loadbytecode', $STR, [$STR]);
154+
add_simple_op('forceouterctx', $OBJ, [$OBJ, $OBJ]);
155+
149156
add_simple_op('say', $STR, [$STR], :side_effects);
150157
add_simple_op('print', $STR, [$STR], :side_effects);
151158

@@ -398,25 +405,10 @@ class QAST::OperationsTruffle {
398405
$comp.as_truffle($node[0], :want($want));
399406
});
400407

401-
402-
# TODO :$want
403-
add_op('call', :!inlinable, sub ($comp, $node, :$want) {
408+
my sub compile_args($comp, @args, @trees, @flags, @names) {
404409
my int $NAMED := 1;
405410
my int $FLAT := 2;
406411

407-
my $ret := ['call'];
408-
409-
my @args := $node.list;
410-
411-
if $node.name {
412-
nqp::push($ret, ['get-lexical', $node.name]);
413-
}
414-
else {
415-
nqp::push($ret, $comp.as_truffle(nqp::shift(@args), :want($OBJ)).tree);
416-
}
417-
418-
my @names;
419-
my @flags;
420412
for @args -> $arg {
421413
my int $flags := 0;
422414

@@ -430,24 +422,60 @@ class QAST::OperationsTruffle {
430422

431423
nqp::push(@flags, $flags);
432424

433-
nqp::push($ret, $comp.as_truffle($arg, :want($CALL_ARG)).tree);
425+
nqp::push(@trees, $comp.as_truffle($arg, :want($CALL_ARG)).tree);
434426
}
435-
nqp::splice($ret, [@flags, @names], 2, 0);
427+
}
436428

437-
TAST.new($OBJ, $ret);
429+
add_op('callmethod', :!inlinable, sub ($comp, $node, :$want) {
430+
my $call := ['callmethod'];
431+
432+
my @args := nqp::clone($node.list);
433+
434+
nqp::push($call, $comp.as_truffle(@args.shift, :want($OBJ)).tree);
435+
436+
if $node.name {
437+
nqp::push($call, ['sval', $node.name]);
438+
}
439+
else {
440+
nqp::push($call, $comp.as_truffle(@args.shift, :want($STR)).tree);
441+
}
442+
443+
my @flags;
444+
my @names;
445+
446+
compile_args($comp, @args, $call, @flags, @names);
447+
448+
nqp::splice($call, [@flags, @names], 3, 0);
449+
450+
TAST.new($OBJ, $call);
438451
});
439452

440-
%ops<callstatic> := %ops<call>;
441453

442-
add_op('callmethod', :!inlinable, sub ($comp, $node, :$want) {
443-
# HACK till we get proper callmethod
444-
if $node.name eq 'name' && nqp::istype($node[0], QAST::Op) && $node[0].op eq 'callmethod' && $node[0].name eq 'backend' && nqp::istype($node[0][0], QAST::Op) && $node[0][0].op eq 'getcomp' {
445-
TAST.new($STR, ['sval', 'truffle'])
446-
} else {
447-
$comp.NYI("unimplemented QAST::Op {$node.op}");
454+
# TODO :$want
455+
add_op('call', :!inlinable, sub ($comp, $node, :$want) {
456+
my $ret := ['call'];
457+
458+
my @args := $node.list;
459+
460+
if $node.name {
461+
nqp::push($ret, ['get-lexical', $node.name]);
462+
}
463+
else {
464+
nqp::push($ret, $comp.as_truffle(nqp::shift(@args), :want($OBJ)).tree);
448465
}
466+
467+
my @flags;
468+
my @names;
469+
470+
compile_args($comp, @args, $ret, @flags, @names);
471+
472+
nqp::splice($ret, [@flags, @names], 2, 0);
473+
474+
TAST.new($OBJ, $ret);
449475
});
450476

477+
%ops<callstatic> := %ops<call>;
478+
451479
add_op('bind', sub ($comp, $node, :$want) {
452480
my @children := $node.list;
453481
if +@children != 2 {
@@ -495,7 +523,45 @@ class QAST::OperationsTruffle {
495523
}
496524
}
497525

498-
class QAST::TruffleCompiler {
526+
# It only makes sense to serialize a serialization context once, so when cross compiling we cache the result
527+
role SerializeOnce {
528+
method serialize_sc_without_caching($sc) {
529+
# Serialize it.
530+
531+
# HACK - we are avoiding an MoarVM specific optimalization
532+
# On MoarVM if an sc is on top of the compiling_scs stackthread the serialized data is stored on the thread context
533+
# We have no way of accessing it, so we try to avoid that
534+
# If we put a fake sc on top of the stack it won't be cached
535+
# we avoid anything that creates a write barrier while it's on top
536+
my $fake_stack_top_sc := nqp::createsc('JS_HACK');
537+
nqp::pushcompsc($fake_stack_top_sc);
538+
539+
my $sh := nqp::list_s();
540+
my $serialized := nqp::serialize($sc, $sh);
541+
542+
# HACK - now we pop our fake sc
543+
nqp::popcompsc();
544+
545+
[$serialized,$sh];
546+
}
547+
548+
method serialize_sc($sc) {
549+
if %*SC_CACHE<enabled> {
550+
my $handle := nqp::scgethandle($sc);
551+
if nqp::existskey(%*SC_CACHE,$handle) {
552+
%*SC_CACHE{$handle};
553+
}
554+
else {
555+
%*SC_CACHE{$handle} := self.serialize_sc_without_caching($sc);
556+
}
557+
}
558+
else {
559+
self.serialize_sc_without_caching($sc);
560+
}
561+
}
562+
}
563+
564+
class QAST::TruffleCompiler does SerializeOnce {
499565
my class BlockInfo {
500566
has $!qast; # The QAST::Block
501567
has $!outer; # Outer block's BlockInfo
@@ -685,6 +751,78 @@ class QAST::TruffleCompiler {
685751
}
686752
}
687753

754+
method deserialization_code($cu) {
755+
# Serialize it.
756+
757+
my $sc_tuple := self.serialize_sc($cu.sc);
758+
my $serialized := $sc_tuple[0];
759+
my $sh := $sc_tuple[1];
760+
761+
# Now it's serialized, pop this SC off the compiling SC stack.
762+
nqp::popcompsc();
763+
764+
# String heap QAST.
765+
my $sh_ast := QAST::Op.new( :op('list_s') );
766+
my $sh_elems := nqp::elems($sh);
767+
my $i := 0;
768+
while $i < $sh_elems {
769+
$sh_ast.push(nqp::isnull_s(nqp::atpos_s($sh, $i))
770+
?? QAST::Op.new( :op('null_s') )
771+
!! QAST::SVal.new( :value(nqp::atpos_s($sh, $i)) ));
772+
$i := $i + 1;
773+
}
774+
$sh_ast := QAST::Block.new( :blocktype('immediate'), $sh_ast );
775+
776+
my $repo_conflict_resolver;
777+
778+
# Handle repossession conflict resolution code, if any.
779+
if $cu.repo_conflict_resolver {
780+
$repo_conflict_resolver := nqp::clone($cu.repo_conflict_resolver);
781+
$repo_conflict_resolver.push(QAST::Var.new( :name('conflicts'), :scope('local') ));
782+
}
783+
else {
784+
$repo_conflict_resolver := QAST::Op.new(
785+
:op('die_s'),
786+
QAST::SVal.new( :value('Repossession conflicts occurred during deserialization') )
787+
);
788+
}
789+
790+
# Overall deserialization QAST.
791+
QAST::Stmts.new(
792+
QAST::Op.new(
793+
:op('bind'),
794+
QAST::Var.new( :name('cur_sc'), :scope('local'), :decl('var') ),
795+
QAST::Op.new( :op('createsc'), QAST::SVal.new( :value(nqp::scgethandle($cu.sc)) ) )
796+
),
797+
QAST::Op.new(
798+
:op('scsetdesc'),
799+
QAST::Var.new( :name('cur_sc'), :scope('local') ),
800+
QAST::SVal.new( :value(nqp::scgetdesc($cu.sc)) )
801+
),
802+
QAST::Op.new(
803+
:op('bind'),
804+
QAST::Var.new( :name('conflicts'), :scope('local'), :decl('var') ),
805+
QAST::Op.new( :op('list') )
806+
),
807+
QAST::Op.new(
808+
:op('deserialize'),
809+
nqp::isnull($serialized) ?? QAST::Op.new( :op('null_s') ) !! QAST::SVal.new( :value($serialized) ),
810+
QAST::Var.new( :name('cur_sc'), :scope('local') ),
811+
$sh_ast,
812+
QAST::Op.new( :op('null') ),
813+
QAST::Var.new( :name('conflicts'), :scope('local') )
814+
),
815+
QAST::Op.new(
816+
:op('if'),
817+
QAST::Op.new(
818+
:op('elems'),
819+
QAST::Var.new( :name('conflicts'), :scope('local') )
820+
),
821+
$repo_conflict_resolver
822+
)
823+
);
824+
}
825+
688826
multi method as_truffle(QAST::CompUnit $node, :$want) {
689827
my $*HLL := '';
690828
if $node.hll {
@@ -693,7 +831,20 @@ class QAST::TruffleCompiler {
693831

694832
my $*BLOCK := BlockInfo.new(NQPMu, NQPMu);
695833

696-
TAST.new($OBJ, ['comp-unit', $node.hll, ['stmts', self.as_truffle($node[0][1], :want($VOID)).tree, self.as_truffle($node[0][3], :want($OBJ)).tree]]);
834+
my $pre_deserialize := ['stmts'];
835+
836+
my $deserialization_code := $node.compilation_mode
837+
?? self.as_truffle(self.deserialization_code($node), :want($VOID)).tree
838+
!! ['stmts'];
839+
840+
841+
if $node.pre_deserialize {
842+
for $node.pre_deserialize -> $pre {
843+
nqp::push($pre_deserialize, self.as_truffle($pre, :want($VOID)).tree);
844+
}
845+
}
846+
847+
TAST.new($OBJ, ['comp-unit', $node.hll, ['stmts', $pre_deserialize, $deserialization_code, self.as_truffle($node[0][1], :want($VOID)).tree, self.as_truffle($node[0][3], :want($OBJ)).tree]]);
697848
}
698849

699850
multi method as_truffle(QAST::VM $node, :$want) {
@@ -879,9 +1030,16 @@ class QAST::TruffleCompiler {
8791030
self.NYI('QAST node: ' ~ $node.HOW.name($node));
8801031
}
8811032

882-
# HACK before we deserialize objects
1033+
multi method as_truffle(QAST::BVal $node, :$want) {
1034+
TAST.new($OBJ, ['bval', $node.value.cuid]);
1035+
}
1036+
8831037
multi method as_truffle(QAST::WVal $node, :$want) {
884-
TAST.new($OBJ, ['null']);
1038+
my $value := $node.value;
1039+
my $sc := nqp::getobjsc($value);
1040+
my str $handle := nqp::scgethandle($sc);
1041+
my int $idx := nqp::scgetobjidx($sc, $value);
1042+
TAST.new($OBJ, ['wval', $handle, $idx]);
8851043
}
8861044

8871045
method NYI($msg) {
@@ -961,7 +1119,8 @@ class TruffleBackend {
9611119
}
9621120

9631121
method is_precomp_stage($stage) {
964-
0;
1122+
# Currently, everything is pre-comp since we're a cross-compiler.
1123+
1;
9651124
}
9661125

9671126
method is_textual_stage($stage) {

src/vm/jvm/bin/run_tests.pl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
}
1010
});
1111

12-
my @nqp_tests = glob "t/nqp/{001,002,003,004,005,006,007,008,010,011,013,015,016,036,037,038,046,083,109}*.t";
12+
my @nqp_tests = glob "t/nqp/{001,002,003,004,005,006,007,008,010,011,013,015,016,036,037,038,046,083}*.t";
1313

1414
$harness->runtests(@nqp_tests);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.perl6.nqp.truffle.nodes.expression;
2+
import com.oracle.truffle.api.frame.VirtualFrame;
3+
import com.oracle.truffle.api.nodes.NodeInfo;
4+
import org.perl6.nqp.truffle.nodes.NQPNode;
5+
import org.perl6.nqp.truffle.nodes.NQPObjNode;
6+
import org.perl6.nqp.dsl.Deserializer;
7+
8+
@NodeInfo(shortName = "BVal")
9+
public final class NQPBValNode extends NQPObjNode {
10+
final String cuid;
11+
12+
@Deserializer
13+
public NQPBValNode(String cuid) {
14+
this.cuid = cuid;
15+
}
16+
17+
@Override
18+
public Object execute(VirtualFrame frame) {
19+
//return bval(argNode.executeStr(frame));
20+
System.out.println("BVal NYI");
21+
return org.perl6.nqp.truffle.runtime.NQPNull.SINGLETON;
22+
}
23+
}

0 commit comments

Comments
 (0)