Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Store non-dynamic lexicals in an array
  • Loading branch information
sorear committed Sep 8, 2010
1 parent 981e8db commit b939063
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 13 deletions.
15 changes: 12 additions & 3 deletions lib/Kernel.cs
Expand Up @@ -188,8 +188,7 @@ public class Frame: IP6 {
public object resultSlot = null;
public int ip = 0;
public readonly DynBlockDelegate code; // premature optimization?
public readonly Dictionary<string, object> lex
= new Dictionary<string, object>();
public Dictionary<string, object> lex;
// statistically, most subs have between 1 and 4 anonymous lexicals
public object lex0;
public object lex1;
Expand Down Expand Up @@ -255,6 +254,10 @@ public class Frame: IP6 {
Frame csr = this;
while (csr != null) {
object o;
if (csr.lex == null) {
csr = csr.outer;
continue;
}
if (csr.lex.TryGetValue(name, out o))
return (Variable)o;
csr = csr.outer;
Expand Down Expand Up @@ -770,6 +773,10 @@ public class Kernel {
public static Variable ContextHelper(Frame th, string name) {
object rt;
while (th != null) {
if (th.lex == null) {
th = th.caller;
continue;
}
if (th.lex.TryGetValue(name, out rt)) {
return (Variable)rt;
}
Expand Down Expand Up @@ -945,6 +952,7 @@ public abstract class ExceptionPacket {
if (pop.info.hints != null &&
pop.info.hints.TryGetValue("!unwind", out o)) {
Frame n = new Frame(bot, bot, (SubInfo) o);
n.lex = new Dictionary<string,object>();
n.lex["!reunwind"] = this;
return n;
}
Expand All @@ -963,11 +971,12 @@ public abstract class ExceptionPacket {
if (top.info.hints != null &&
top.info.hints.TryGetValue(key, out o)) {
Frame fn = new Frame(bot, top, (SubInfo) o);
fn.lex = new Dictionary<string,object>();
fn.lex["!rethrow"] = this;
return fn;
}

if (top.lex.ContainsKey("!rethrow")) {
if (top.lex != null && top.lex.ContainsKey("!rethrow")) {
// this is an active exception handling frame! skip
// the corresponding handler
top = top.outer.caller;
Expand Down
16 changes: 12 additions & 4 deletions src/Body.pm
Expand Up @@ -48,22 +48,28 @@ use CgOp ();
$h{'?is_mainline'} = 0;
}

my $nfields_global;
my $nfields_global = 0;
my $nslots_local = 0;
my $usednamed = 0;
for my $le (map { $_->used_slots($h{'?is_mainline'}) } @{ $self->decls }) {
# 0: cloned 1: static field 2: hint
# 3: readonly static field
# 0: cloned dynamic 1: static field 2: hint
# 3: readonly static field 4: cloned non-dynamic
if ($le->[2] == 1 || $le->[2] == 3) {
my $sanname = $le->[0];
$sanname =~ s/\W//g;
$le->[3] = sprintf "%s.F%d_%d_%s", $::UNITNAME, $self->uid,
$nfields_global++, $sanname;
} elsif ($le->[2] == 2) {
$le->[3] = sprintf "%s.%s_info", $::UNITNAME, $self->csname;
} elsif ($le->[2] == 4) {
$le->[3] = $nslots_local++;
} else {
# TODO generate numbered lookups for clonedvars
$usednamed = 1;
}
$h{shift(@$le)} = $le;
}
$h{'?num_slots'} = $nslots_local;
$h{'?usednamed'} = $usednamed;
$self->lexical(\%h);

$h{'OUTER::'} = $outer;
Expand Down Expand Up @@ -166,6 +172,8 @@ use CgOp ();
my ($self) = @_;
$_->write for (map { $_->bodies } @{ $self->decls });
CodeGen->new(csname => $self->csname, body => $self,
minlets => $self->lexical->{'?num_slots'},
usednamed => $self->lexical->{'?usednamed'},
ops => $self->cgoptree)->write;
}

Expand Down
3 changes: 3 additions & 0 deletions src/CgOp.pm
Expand Up @@ -217,6 +217,9 @@ use warnings;
when ("clr_sfield_get") {
return;
}
when ("rtpadgeti") {
return;
}
when ("rtpadget") {
return;
}
Expand Down
43 changes: 43 additions & 0 deletions src/CodeGen.pm
Expand Up @@ -210,6 +210,7 @@ use 5.010;
has lettypes => (isa => 'ArrayRef', is => 'ro', default => sub { [] });
has numlets => (isa => 'Int', is => 'rw', default => 0);
has minlets => (isa => 'Int', is => 'ro', default => 0);
has usednamed => (isa => 'Bool', is => 'ro', default => 0);
has body => (isa => 'Body', is => 'ro');
has bodies => (isa => 'ArrayRef', is => 'ro', default => sub { [] });
has consttab => (isa => 'ArrayRef', is => 'ro', default => sub { [] });
Expand Down Expand Up @@ -428,6 +429,23 @@ use 5.010;
$self->_emit($frame . (".outer" x $order) . ".lex[" . qm($name) . "] = $val");
}

sub rtpadgeti {
my ($self, $type, $order, $name) = @_;
$self->callframe;
my ($frame) = $self->_popn(1);
my $tag = $name < 4 ? "lex$name" : ("lexn[" . ($name - 4) . "]");
$self->_push("object", $frame . (".outer" x $order) . ".$tag");
$self->cast($type);
}

sub rtpadputi {
my ($self, $order, $name) = @_;
$self->callframe;
my ($val, $frame) = $self->_popn(2);
my $tag = $name < 4 ? "lex$name" : ("lexn[" . ($name - 4) . "]");
$self->_emit($frame . (".outer" x $order) . ".$tag = $val");
}

sub callframe {
my ($self) = @_;
my $frame = 'th';
Expand Down Expand Up @@ -706,13 +724,25 @@ use 5.010;
sub proto_var {
my ($self, $name) = @_;
my ($type, $kind, $data) = @{ $self->bodies->[-1]->lexical->{$name} };
if (($kind == 4 || $kind == 0) && !$self->bodies->[-1]->needs_protopad) {
# XXX this isn't the right way
$self->_popn(1);
return
}
if ($kind == 3) {
$self->clr_sfield_set($data);
$self->clr_sfield_get($data . ":f,IP6");
$self->clr_call_direct('Kernel.NewROScalar', 1);
$self->clr_sfield_set($data . "_var");
return;
}
if ($kind == 4) {
$self->peek_let('protopad');
my ($pv, $pp) = $self->_popn(2);
my $tag = $data > 4 ? ("lexn[" . ($data - 4) . "]") : "lex$data";
$self->_emit("$pp.$tag = ($pv)");
return;
}
if ($kind == 1) {
$self->clr_sfield_set($data);
return;
Expand Down Expand Up @@ -743,6 +773,16 @@ use 5.010;
$self->_push('SubInfo', $body->csname . "_info");
$self->clr_new('Frame', 3);
$self->push_let('protopad');
if ($body->lexical->{'?usednamed'}) {
$self->peek_let('protopad');
$self->clr_new('Dictionary<string,object>', 0);
$self->clr_field_set('lex');
}
if ($body->lexical->{'?num_slots'} > 4) {
$self->peek_let('protopad');
$self->_push('object[]', 'new object[' . ($body->lexical->{'?num_slots'} - 4) . ']');
$self->clr_field_set('lexn');
}
}
push @{ $self->bodies }, $body;
}
Expand Down Expand Up @@ -779,6 +819,9 @@ use 5.010;
print ::NIECZA_OUT " " x 16, "th.lexn = new object[",
($self->numlets + $self->minlets - 4), "];\n";
}
if ($self->usednamed) {
print ::NIECZA_OUT " " x 16, "if (th.lex == null) th.lex = new Dictionary<string,object>();\n";
}
for (@{ $self->buffer }) {
s/\@\@L(\w+)/$self->labelname->{$1}/eg;
}
Expand Down
14 changes: 9 additions & 5 deletions src/Decl.pm
Expand Up @@ -10,6 +10,8 @@ use CgOp;

has zyg => (is => 'ro', isa => 'ArrayRef', default => sub { [] });

sub dyn_name { $_[1] =~ /^.?[?*]/ }

sub used_slots { () }
sub preinit_code { CgOp::noop }
sub enter_code { CgOp::noop }
Expand Down Expand Up @@ -60,7 +62,8 @@ use CgOp;
sub bodies { $_[0]->code }

sub used_slots {
[$_[0]->var, 'Variable', $_[1] ? 3 : 0];
[$_[0]->var, 'Variable', $_[1] ? 3 :
($_[0]->dyn_name($_[0]->var) ? 0 : 4)];
}

sub preinit_code {
Expand Down Expand Up @@ -99,7 +102,7 @@ use CgOp;
}

sub used_slots {
[$_[0]->slot, 'Variable', ($_[1] && !$_[0]->dynamic) ? 1 : 0];
[$_[0]->slot, 'Variable', $_[0]->dynamic ? 0 : $_[1] ? 1 : 4];
}

sub preinit_code {
Expand Down Expand Up @@ -190,7 +193,7 @@ use CgOp;
has list => (isa => 'Bool', is => 'ro', default => 0);

sub used_slots {
$_[0]->slot ? [$_[0]->slot, 'Variable', 0] : ();
$_[0]->slot ? [$_[0]->slot, 'Variable', 4] : ();
}

sub outer_decls {
Expand Down Expand Up @@ -261,7 +264,7 @@ use CgOp;
sub used_slots {
my ($self) = @_;
[$self->var, 'Variable', 3], [$self->stashvar, 'Variable', 3],
(!$self->stub ? [$self->bodyvar, 'Variable', $_[1] ? 1 : 0] : ());
(!$self->stub ? [$self->bodyvar, 'Variable', $_[1] ? 1 : 4] : ());
}

sub make_how { CgOp::newscalar(CgOp::null('IP6')); }
Expand Down Expand Up @@ -456,7 +459,8 @@ use CgOp;
has oname => (is => 'ro', isa => 'Str', required => 1);
has nname => (is => 'ro', isa => 'Str', required => 1);

sub used_slots { [ $_[0]->nname, 'Variable', 0 ] }
sub used_slots { [ $_[0]->nname, 'Variable',
$_[0]->dyn_name($_[0]->nname) ? 0 : 4 ] }

sub preinit_code {
my ($self, $body) = @_;
Expand Down
9 changes: 8 additions & 1 deletion src/ResolveLex.pm
Expand Up @@ -75,7 +75,14 @@ sub resolve_lex {
$::UNITREFS{$1} = 1;
}

if ($kind == 3) {
if ($kind == 4) {
if ($set_to) {
return CgOp::Primitive->new(op => ['rtpadputi', $order, $data],
zyg => [$set_to]);
} else {
return CgOp::Primitive->new(op => ['rtpadgeti', $type, $order, $data]);
}
} elsif ($kind == 3) {
if ($set_to) {
return CgOp::let($set_to, sub { my $x = $_[0];
CgOp::prog( CgOp::rawsset($data, CgOp::fetch($x)),
Expand Down

0 comments on commit b939063

Please sign in to comment.