From 3caccd5c414688348b1c5d2f4e5c41014124f003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Murias?= Date: Thu, 11 Oct 2018 13:58:14 +0200 Subject: [PATCH] [js] Very basic int64/uint64 support Currently only ++/-- and converting them back and forth between Int works --- src/Perl6/Actions.nqp | 3 ++- src/Perl6/Metamodel/BOOTSTRAP.nqp | 31 ++++++++++++++++++++++++++++++ src/Perl6/Optimizer.nqp | 22 ++++++++++++++++++++- src/Perl6/World.nqp | 2 +- src/vm/js/Perl6/Ops.nqp | 3 +++ src/vm/js/perl6-runtime/runtime.js | 8 ++++++++ 6 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/Perl6/Actions.nqp b/src/Perl6/Actions.nqp index e991541bc00..2bbf7d4b35b 100644 --- a/src/Perl6/Actions.nqp +++ b/src/Perl6/Actions.nqp @@ -7537,7 +7537,8 @@ class Perl6::Actions is HLL::Actions does STDActions { } } - my @native_assign_ops := ['', 'assign_i', 'assign_n', 'assign_s']; + # The _i64 and _u64 are only used on backends that emulate int64/uint64 + my @native_assign_ops := ['', 'assign_i', 'assign_n', 'assign_s', 'assign_i64', 'assign_u64']; sub assign_op($/, $lhs_ast, $rhs_ast, :$initialize) { my $past; my $var_sigil; diff --git a/src/Perl6/Metamodel/BOOTSTRAP.nqp b/src/Perl6/Metamodel/BOOTSTRAP.nqp index d8c7c4c5b31..a98c622b354 100644 --- a/src/Perl6/Metamodel/BOOTSTRAP.nqp +++ b/src/Perl6/Metamodel/BOOTSTRAP.nqp @@ -92,6 +92,13 @@ my stub IntMultidimRef metaclass Perl6::Metamodel::NativeRefHOW { ... }; my stub NumMultidimRef metaclass Perl6::Metamodel::NativeRefHOW { ... }; my stub StrMultidimRef metaclass Perl6::Metamodel::NativeRefHOW { ... }; +#?if js +my stub Int64LexRef metaclass Perl6::Metamodel::NativeRefHOW { ... }; +my stub Int64AttrRef metaclass Perl6::Metamodel::NativeRefHOW { ... }; +my stub Int64PosRef metaclass Perl6::Metamodel::NativeRefHOW { ... }; +my stub Int64MultidimRef metaclass Perl6::Metamodel::NativeRefHOW { ... }; +#?endif + # Implement the signature binder. # The JVM backend really only uses trial_bind, # so we exclude everything else. @@ -1704,6 +1711,13 @@ BEGIN { setup_native_ref_type(NumMultidimRef, num, 'multidim'); setup_native_ref_type(StrMultidimRef, str, 'multidim'); +#?if js + setup_native_ref_type(Int64LexRef, int64, 'lexical'); + setup_native_ref_type(Int64AttrRef, int64, 'attribute'); + setup_native_ref_type(Int64PosRef, int64, 'positional'); + setup_native_ref_type(Int64MultidimRef, int64, 'multidim'); +#?endif + # class Proxy is Any { # has Mu &!FETCH; # has Mu &!STORE; @@ -3366,6 +3380,12 @@ BEGIN { Perl6::Metamodel::NativeRefHOW.add_stash(IntMultidimRef); Perl6::Metamodel::NativeRefHOW.add_stash(NumMultidimRef); Perl6::Metamodel::NativeRefHOW.add_stash(StrMultidimRef); +#?if js + Perl6::Metamodel::NativeRefHOW.add_stash(Int64LexRef); + Perl6::Metamodel::NativeRefHOW.add_stash(Int64AttrRef); + Perl6::Metamodel::NativeRefHOW.add_stash(Int64PosRef); + Perl6::Metamodel::NativeRefHOW.add_stash(Int64MultidimRef); +#?endif Perl6::Metamodel::ClassHOW.add_stash(List); Perl6::Metamodel::ClassHOW.add_stash(Slip); Perl6::Metamodel::ClassHOW.add_stash(Array); @@ -3483,6 +3503,11 @@ BEGIN { EXPORT::DEFAULT.WHO := IntPosRef; EXPORT::DEFAULT.WHO := NumPosRef; EXPORT::DEFAULT.WHO := StrPosRef; +#?if + EXPORT::DEFAULT.WHO := Int64LexRef; + EXPORT::DEFAULT.WHO := Int64AttrRef; + EXPORT::DEFAULT.WHO := Int64PosRef; +#?endif EXPORT::DEFAULT.WHO := Proxy; EXPORT::DEFAULT.WHO := Grammar; EXPORT::DEFAULT.WHO := Junction; @@ -3714,6 +3739,12 @@ nqp::sethllconfig('perl6', nqp::hash( 'int_multidim_ref', IntMultidimRef, 'num_multidim_ref', NumMultidimRef, 'str_multidim_ref', StrMultidimRef, +#?if js + 'int64_lex_ref', Int64LexRef, + 'int64_attr_ref', Int64AttrRef, + 'int64_pos_ref', Int64PosRef, + 'int64_multidim_ref', Int64MultidimRef, +#?endif )); # Tell parametric role groups how to create a dispatcher. diff --git a/src/Perl6/Optimizer.nqp b/src/Perl6/Optimizer.nqp index dc1947b1d19..c5ac71c9c7e 100644 --- a/src/Perl6/Optimizer.nqp +++ b/src/Perl6/Optimizer.nqp @@ -1915,7 +1915,7 @@ class Perl6::Optimizer { # if we got a native int/num, we can rewrite into nqp ops if nqp::istype($var,QAST::Var) && $var.scope eq 'lexicalref' && ((my $primspec := nqp::objprimspec($var.returns)) == 1 # native int - || $primspec == 2) # native num + || $primspec == 2 || $primspec == 4 || $primspec == 5) # native num or "emulated" 64bit int { my $returns := $var.returns; my $is-dec := nqp::eqat($op.name, '--', -3); @@ -1958,6 +1958,26 @@ class Perl6::Optimizer { $one } } + elsif $primspec == 4 || $primspec == 5 { # 64bit int on 32bit backends + my str $assign_op := $primspec == 4 ?? 'assign_i64' !! 'assign_u64'; + my $one := QAST::IVal.new: :value(1); + if $!void_context || nqp::eqat($op.name, '&pre', 0) { + # we can just use (or ignore) the result + return QAST::Op.new: :op($assign_op), :$node, :$returns, $var, + QAST::Op.new: :op($is-dec ?? 'sub_i64' !! 'add_i64'), + :$returns, $var, $one + } + else { + # need to assign original value; it's cheaper to just + # do the reverse operation than to use a temp var + return QAST::Op.new: :op($is-dec ?? 'add_i64' !! 'sub_i64'), + :$node, :$returns, + QAST::Op.new(:op($assign_op), :$returns, $var, + QAST::Op.new: :op($is-dec ?? 'sub_i64' !! 'add_i64'), + :$returns, $var, $one), + $one + } + } } # XXX TODO: my tests show the opt below makes things 25% slower. diff --git a/src/Perl6/World.nqp b/src/Perl6/World.nqp index 5858e867acb..4ff983e7e01 100644 --- a/src/Perl6/World.nqp +++ b/src/Perl6/World.nqp @@ -1593,7 +1593,7 @@ class Perl6::World is HLL::World { my $prim := %cont_info eq '$' && nqp::objprimspec($descriptor.of); if $prim { if $scope eq 'state' { nqp::die("Natively typed state variables not yet implemented") } - if $prim == 1 { + if $prim == 1 || $prim == 4 || $prim == 5 { $block[0].push(QAST::Op.new( :op('bind'), QAST::Var.new( :scope('lexical'), :name($name) ), QAST::IVal.new( :value(0) ) )) diff --git a/src/vm/js/Perl6/Ops.nqp b/src/vm/js/Perl6/Ops.nqp index 26fb192de26..f052770f41e 100644 --- a/src/vm/js/Perl6/Ops.nqp +++ b/src/vm/js/Perl6/Ops.nqp @@ -49,6 +49,9 @@ $ops.add_hll_unbox('perl6', $ops.INT, 'getInt'); $ops.add_hll_unbox('perl6', $ops.NUM, 'getNum'); $ops.add_hll_unbox('perl6', $ops.STR, 'getStr'); +$ops.add_hll_unbox('perl6', $ops.INT64, 'getInt64'); +$ops.add_hll_unbox('perl6', $ops.UINT64, 'getUint64'); + # Signature binding related bits. $ops.add_simple_op('p6setbinder', $ops.VOID, [$ops.OBJ], :side_effects, sub ($binder) {"nqp.p6binder = $binder"}); diff --git a/src/vm/js/perl6-runtime/runtime.js b/src/vm/js/perl6-runtime/runtime.js index 462ca1cc20d..50cbe1c1f70 100644 --- a/src/vm/js/perl6-runtime/runtime.js +++ b/src/vm/js/perl6-runtime/runtime.js @@ -324,6 +324,14 @@ module.exports.load = function(nqp, CodeRef, Capture, containerSpecs) { return this.$$getattr(Scalar, '$!value').$$getInt(); }); + this.STable.addInternalMethod('$$getInt64', function(ctx) { + return this.$$getattr(Scalar, '$!value').$$getInt64(); + }); + + this.STable.addInternalMethod('$$getUint64', function(ctx) { + return this.$$getattr(Scalar, '$!value').$$getUint64(); + }); + this.STable.addInternalMethod('$$getStr', function(ctx) { return this.$$getattr(Scalar, '$!value').$$getStr(); });