aboutsummaryrefslogtreecommitdiff
path: root/interpreter/Elymas.pm
diff options
context:
space:
mode:
authorDrahflow <drahflow@gmx.de>2013-02-17 17:49:01 +0100
committerDrahflow <drahflow@gmx.de>2013-02-17 17:49:01 +0100
commit3365f691362da7e7a9854c789ab1f7b49139e302 (patch)
treec52e8b423e44ea2fd20c365bff303887301791d8 /interpreter/Elymas.pm
parentd5b31ed75423b28f6589da103b0981d0327aa9f6 (diff)
Failing GC ideas removed
Diffstat (limited to 'interpreter/Elymas.pm')
-rw-r--r--interpreter/Elymas.pm226
1 files changed, 34 insertions, 192 deletions
diff --git a/interpreter/Elymas.pm b/interpreter/Elymas.pm
index 89bfb05..2a57b55 100644
--- a/interpreter/Elymas.pm
+++ b/interpreter/Elymas.pm
@@ -8,7 +8,6 @@ our @ISA = qw(Exporter);
our @EXPORT = qw(
popInt popString popArray $quoted @globalCallStack $globalScope $globalData
interpretCode compileCode execute executeString executeFile resolve canCastTo typeEqual
- register
);
use Data::Dumper;
@@ -25,7 +24,6 @@ our $quoted = 0;
our @globalCallStack;
our $globalScope;
our $globalData = [];
-our @globalGCRoots = (\@globalCallStack, \$globalScope, $globalData);
sub popInt {
my ($data) = @_;
@@ -105,12 +103,12 @@ sub compileCode {
my $name = $t->[2];
# $ret .= "\$name = '$name'; Elymas::applyResolvedName(\$name, resolve(\$\$lscope, \$data, \$name), \$data, \$lscope, 0);\n";
# $ret .= "\$meaning = resolve(\$\$lscope, \$data, '$name');\n";
- $ret .= "\$meaning = undef;\n";
+ # $ret .= "\$meaning = undef;\n";
$ret .= "\$rscope = \$\$lscope;\n";
- $ret .= "do {\n";
- $ret .= " \$meaning = \$rscope->{'$name'} and \$rscope = undef if exists \$rscope->{'$name'};\n";
+ $ret .= "while (defined \$rscope) {\n";
+ $ret .= " \$meaning = \$rscope->{'$name'} and last;\n";
$ret .= " \$rscope = \$rscope->{' parent'};\n";
- $ret .= "} while(defined \$rscope);\n";
+ $ret .= "}\n";
$ret .= "die 'could not resolve \"$name\"' unless defined \$meaning;\n";
$ret .= <<'EOPERL';
if($meaning->[2] eq 'passive') {
@@ -148,28 +146,38 @@ EOPERL
$ret .= "# -" . $code->[$i]->[0] . "\n";
my $spec = $code->[$i]->[0];
- my $max = 0;
+ if($spec eq '101') {
+ $ret .= "die 'Stack underflow in inlined stack-op' unless \@\$data >= 2;\n";
+ $ret .= "push \@\$data, \$data->[-2];\n";
+ } else {
+ my $max = 0;
- my @spec = split //, $spec;
- $max = $_ > $max? $_: $max foreach grep { $_ ne '*' } @spec;
+ my @spec = split //, $spec;
+ $max = $_ > $max? $_: $max foreach grep { $_ ne '*' } @spec;
- $ret .= "die 'Stack underflow in inlined stack-op' unless \@\$data >= $max;\n";
- $hasStackOps = 1;
- $ret .= "\@buffer = ();\n";
+ $ret .= "die 'Stack underflow in inlined stack-op' unless \@\$data >= $max;\n";
+ $hasStackOps = 1;
+ #$ret .= "\@buffer = ();\n";
- foreach (0 .. $max) {
- $ret .= "push \@buffer, pop \@\$data;\n";
- }
+ foreach my $j (0 .. $max) {
+ #$ret .= "push \@buffer, pop \@\$data;\n";
+ $ret .= "\$buffer[$j] = pop \@\$data;\n";
+ }
- foreach my $j (@spec) {
- if($j eq '*') {
- $ret .= "\$f = pop \@\$data or die 'Stack underflow in -*';\n";
- $ret .= "execute(\$f, \$data, \$scope);\n";
+ if($spec =~ /^\d+$/) {
+ $ret .= "push \@\$data, \@buffer[" . join(', ', @spec) . "];\n";
} else {
- $ret .= "push \@\$data, \$buffer[$j];\n";
+ foreach my $j (@spec) {
+ if($j eq '*') {
+ $ret .= "\$f = pop \@\$data or die 'Stack underflow in -*';\n";
+ $ret .= "execute(\$f, \$data, \$scope);\n";
+ } else {
+ $ret .= "push \@\$data, \$buffer[$j];\n";
+ }
+ }
}
}
-
+
$skip = 1;
} else {
$ret .= "push \@\$data, \$code[$i]; # " . $code->[$i]->[0] . "\n";
@@ -179,7 +187,7 @@ EOPERL
$ret .= $popCode and $popPending = 0 if $popPending;
if($hasStackOps) {
- $ret = "my \$f; my \@buffer; register(\\\@buffer); \n" . $ret;
+ $ret = "my \$f; my \@buffer; \n" . $ret;
}
$ret .= <<'EOPERL';
@@ -356,24 +364,20 @@ sub doLoopStep {
sub execute {
my ($f, $data, $scope) = @_;
- if(not grep { $data != $_ } @globalGCRoots) {
- die "executed-upon data not in GC root list";
- }
-
if(ref($f->[1]) ne 'ARRAY') {
push @$data, $f;
return;
}
if($f->[1]->[0] eq 'array') {
- execute(register([register(sub {
+ execute([sub {
my ($data) = @_;
my $i = pop @$data or die "Stack underflow";
die "array index must be int" unless $i->[1] eq 'int';
push @$data, $f->[0]->[$i->[0] % @{$f->[0]}];
- }), ['func', 'array-to-func-cast', ['int'], [$f->[1]->[1]]]]),
+ }, ['func', 'array-to-func-cast', ['int'], [$f->[1]->[1]]]],
$data, $scope);
return;
} elsif($f->[1]->[0] ne 'func') {
@@ -546,15 +550,12 @@ sub execute {
foreach my $i (@$stage) {
my @s = ($v, $argCopy[$i]);
my $func = pop @s or die "Stack underflow in abstraction";
- push @globalGCRoots, \@s;
execute($func, \@s, $scope);
- pop @globalGCRoots;
$argCopy[$i] = $s[0];
}
&$unravel($data, \@argCopy, \@stageCallCopy, \@argTypeCopy, \@loopCopy);
};
- register($abstraction);
push @$data, [$abstraction, ['func', 'autoabstraction of ' . $f->[1]->[1], [grep { $_ } @argTypeCopy], undef]];
# FIXME the undef can be determined
@@ -568,9 +569,7 @@ sub execute {
foreach my $j (@$stage) {
my @s = ($i, $argCopy2[$j]);
my $func = pop @s or die "Stack underflow in abstraction";
- push @globalGCRoots, \@s;
execute($func, \@s, $scope);
- pop @globalGCRoots;
$argCopy2[$j] = $s[0];
}
@@ -593,7 +592,6 @@ sub execute {
push @$data, @argCopy;
}
};
- register($unravel);
&$unravel($data, \@concreteArgs, \@stageCalls, \@argTypes, \@loops);
weaken($unravel);
}
@@ -623,25 +621,18 @@ sub applyResolvedName {
my $meaning = resolve($$scope, $data, $t->[0]);
applyResolvedName($t, $meaning, $data, $scope, 0);
};
- push @$data, register([register($quotedSub), ['func', 'quoted late-resolve of ' . $t->[0]], $t->[0]]);
+ push @$data, [$quotedSub, ['func', 'quoted late-resolve of ' . $t->[0]], $t->[0]];
weaken($quotedSub);
} else {
die "could not resolve '$t->[0]'";
}
} elsif($meaning->[2] eq 'passive') {
if($quoted) {
- my $subLive = 1;
my $sub; $sub = sub {
- unless($subLive) {
- warn Devel::FindRef::track($sub, 10);
- warn Dumper($sub);
- die "tried to execute GCed sub (quoted passive constant)";
- }
-
my ($data) = @_;
push @$data, [$meaning->[0], $meaning->[1]];
};
- push @$data, register([register($sub), ['func', 'quoted-constant of ' . $t->[0]], $t->[0]]);
+ push @$data, [$sub, ['func', 'quoted-constant of ' . $t->[0]], $t->[0]];
weaken($sub);
} else {
push @$data, [$meaning->[0], $meaning->[1]];
@@ -686,155 +677,6 @@ sub interpretTokens {
}
}
-sub garbageCollect {
- my $reachableObjs = {};
-
- foreach my $root (@globalGCRoots) {
- markObjs($reachableObjs, $root, "");
- }
- my $level;
- #warn "Marked objects: " . scalar keys %$reachableObjs;
- eval {
- for($level = 1; ; ++$level) {
- #warn "Level $level";
-
- # peek_my returns identical hash-ref each time, need to traverse
- # without seen-check
- my $locals = peek_my($level);
- markObjsInHash($reachableObjs, $locals, "S:");
- }
- };
- if($@ !~ /Not nested deeply enough/) {
- die "Unexpected level traversal error: " . $@;
- }
- #warn "Levels traversed: $level";
- #warn "Marked objects (2): " . join "\n", keys %$reachableObjs;
-
- my @cleanedObjs;
-
- foreach my $i (0 .. $#allObjs) {
- my $obj = $allObjs[$i];
-
- if(not exists $reachableObjs->{$obj}) {
- next unless ref($obj);
-
- if(ref($obj) eq 'CODE') {
- my ($closed_over, undef) = closed_over($obj);
- my $killHash = {};
-
- foreach my $key (keys %$closed_over) {
- if($key =~ /^@/) {
- $killHash->{$key} = [];
- } elsif($key =~ /^%/) {
- $killHash->{$key} = {};
- #} elsif($key eq '$obj') {
- # skip DEBUG FIXME
- } elsif($key =~ /^\$/) {
- $killHash->{$key} = \undef;
- } else {
- die "Cannot construct gc kill template for closed var: " . $key;
- }
- }
-
- set_closed_over($obj, $killHash);
- } elsif(ref($obj) eq 'ARRAY') {
- @$obj = ();
- } elsif(ref($obj) eq 'REF') {
- $$obj = undef;
- } else {
- die "Garbage collect sweep cannot handle object reference: $obj";
- }
-
- push @cleanedObjs, $allObjs[$i];
- $allObjs[$i] = undef;
- }
- }
-
- %$reachableObjs = ();
-
- print "Before GC: " . scalar @allObjs . "\n";
- @allObjs = grep { defined } @allObjs;
- print "After GC: " . scalar @allObjs . "\n";
-
-# foreach my $obj (@cleanedObjs) {
-# print Devel::FindRef::track($obj);
-# }
-}
-
-sub markObjsInHash {
- my ($reachableObjs, $hash, $indent) = @_;
-
- #warn $indent . "Unseen Hash-Walking: $obj";
- foreach my $k (keys %$hash) {
- #warn $indent . "-> $k: $obj->{$k}";
- markObjs($reachableObjs, $hash->{$k}, $indent . " ");
- }
-}
-
-sub markObjs {
- my ($reachableObjs, $obj, $indent) = @_;
-
- return unless defined $obj and ref($obj);
- return if exists $reachableObjs->{$obj};
-
- $reachableObjs->{$obj} = 1;
-
- if(ref($obj) eq 'ARRAY') {
- #warn $indent . "Array-Walking: $obj, " . scalar @$obj . " elements";
- foreach my $i (0 .. $#$obj) {
- #warn $indent . "-> [$i]: $obj->[$i]";
- markObjs($reachableObjs, $obj->[$i], $indent . " ");
- }
- } elsif(ref($obj) eq 'HASH') {
- #warn $indent . "Hash-Walking: $obj";
- foreach my $k (keys %$obj) {
- #warn $indent . "-> $k: $obj->{$k}";
- markObjs($reachableObjs, $obj->{$k}, $indent . " ");
- }
- } elsif(ref($obj) eq 'REF') {
- #warn $indent . "Ref-Walking: $obj";
- markObjs($reachableObjs, $$obj, $indent . " ");
- } elsif(ref($obj) eq 'SCALAR') {
- # nothing to follow here
- } elsif(ref($obj) eq 'GLOB') {
- #warn $indent . "Glob-Walking: $obj";
- markObjs($reachableObjs, *$obj{'SCALAR'}, $indent . " ");
- markObjs($reachableObjs, *$obj{'ARRAY'}, $indent . " ");
- markObjs($reachableObjs, *$obj{'HASH'}, $indent . " ");
- markObjs($reachableObjs, *$obj{'CODE'}, $indent . " ");
- markObjs($reachableObjs, *$obj{'IO'}, $indent . " ");
- markObjs($reachableObjs, *$obj{'GLOB'}, $indent . " ");
- markObjs($reachableObjs, *$obj{'FORMAT'}, $indent . " ");
- } elsif(ref($obj) eq 'IO::File') {
- # don't handle these
- } elsif(ref($obj) eq 'CODE') {
- #warn $indent . "Code-Walking: $obj";
- my ($closed_over, $closed_over_2) = closed_over($obj);
- markObjsInHash($reachableObjs, $closed_over, $indent . " ");
- markObjsInHash($reachableObjs, $closed_over_2, $indent . " ");
-
- my $peek_sub = peek_sub($obj);
- markObjsInHash($reachableObjs, $peek_sub, $indent . " ");
- } else {
- die "GC cannot handle ref type: " . ref($obj);
- }
-}
-
-my $lastAllObjSize = 0;
-
-sub register {
- my ($obj) = @_;
-
- # if(@allObjs > $lastAllObjSize + 100000) {
- # garbageCollect();
- # $lastAllObjSize = @allObjs;
- # }
-
- # push @allObjs, $obj;
-
- return $obj;
-}
-
sub executeFile {
my ($file, $data, $scope) = @_;