Skip to content

Commit 80270ae

Browse files
committed
Speed up register allocator
Replace the if/elsif chains by indexing an array by $kind. Since registers are named after consecutive numbers, we can actually use an array to store information about released register indexes. This makes access much cheaper.
1 parent b5084ab commit 80270ae

File tree

1 file changed

+17
-62
lines changed

1 file changed

+17
-62
lines changed

src/vm/moar/QAST/QASTCompilerMAST.nqp

Lines changed: 17 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -70,36 +70,16 @@ my class MASTCompilerInstance {
7070
# using the result as an arg to another op.
7171
my class RegAlloc {
7272
has $!frame;
73-
has @!objs;
74-
has @!int64s;
75-
has @!int32s;
76-
has @!int16s;
77-
has @!int8s;
78-
has @!num64s;
79-
has @!num32s;
80-
has @!strs;
81-
has @!uint64s;
82-
has @!uint32s;
83-
has @!uint16s;
84-
has @!uint8s;
85-
has %!released_indexes;
73+
has @!released;
74+
has @!released_indexes;
8675

76+
my @types := [nqp::null,int8,int16,int32,int,num32,num,str,NQPMu,nqp::null,nqp::null,nqp::null,nqp::null,nqp::null,nqp::null,nqp::null,nqp::null,uint8,uint16,uint32,uint64];
8777
method new($frame) {
8878
my $obj := nqp::create(self);
79+
my @released := [nqp::null,[],[],[],[],[],[],[],[],nqp::null,nqp::null,nqp::null,nqp::null,nqp::null,nqp::null,nqp::null,nqp::null,[],[],[],[]];
80+
nqp::bindattr($obj, RegAlloc, '@!released', @released);
8981
nqp::bindattr($obj, RegAlloc, '$!frame', $frame);
90-
nqp::bindattr($obj, RegAlloc, '@!objs', []);
91-
nqp::bindattr($obj, RegAlloc, '@!int64s', []);
92-
nqp::bindattr($obj, RegAlloc, '@!int32s', []);
93-
nqp::bindattr($obj, RegAlloc, '@!int16s', []);
94-
nqp::bindattr($obj, RegAlloc, '@!int8s', []);
95-
nqp::bindattr($obj, RegAlloc, '@!num64s', []);
96-
nqp::bindattr($obj, RegAlloc, '@!num32s', []);
97-
nqp::bindattr($obj, RegAlloc, '@!strs', []);
98-
nqp::bindattr($obj, RegAlloc, '@!uint64s', []);
99-
nqp::bindattr($obj, RegAlloc, '@!uint32s', []);
100-
nqp::bindattr($obj, RegAlloc, '@!uint16s', []);
101-
nqp::bindattr($obj, RegAlloc, '@!uint8s', []);
102-
nqp::bindattr($obj, RegAlloc, '%!released_indexes', {});
82+
nqp::bindattr($obj, RegAlloc, '@!released_indexes', nqp::list_i);
10383
$obj
10484
}
10585

@@ -112,33 +92,19 @@ my class MASTCompilerInstance {
11292
# so a Local can't be a non-Var for the first half of a block and
11393
# then a Var the second half, but then control returns to the first half
11494
method fresh_register($kind, $new = 0) {
115-
my @arr; my $type;
11695
# set $new to 1 here if you suspect a problem with the allocator,
11796
# or if you suspect a register is being double-released somewhere.
11897
# $new := 1;
119-
if $kind == $MVM_reg_int64 { @arr := @!int64s; $type := int }
120-
elsif $kind == $MVM_reg_num64 { @arr := @!num64s; $type := num }
121-
elsif $kind == $MVM_reg_str { @arr := @!strs; $type := str }
122-
elsif $kind == $MVM_reg_obj { @arr := @!objs; $type := NQPMu }
123-
elsif $kind == $MVM_reg_int32 { @arr := @!int32s; $type := int32 }
124-
elsif $kind == $MVM_reg_int16 { @arr := @!int16s; $type := int16 }
125-
elsif $kind == $MVM_reg_int8 { @arr := @!int8s; $type := int8 }
126-
elsif $kind == $MVM_reg_num32 { @arr := @!num32s; $type := num32 }
127-
elsif $kind == $MVM_reg_uint64 { @arr := @!uint64s; $type := uint64 }
128-
elsif $kind == $MVM_reg_uint32 { @arr := @!uint32s; $type := uint32 }
129-
elsif $kind == $MVM_reg_uint16 { @arr := @!uint16s; $type := uint16 }
130-
elsif $kind == $MVM_reg_uint8 { @arr := @!uint8s; $type := uint8 }
131-
else { nqp::die("Unhandled reg kind $kind") }
132-
133-
my $reg;
98+
my @arr := @!released[$kind];
99+
134100
if nqp::elems(@arr) && !$new {
135-
$reg := nqp::pop(@arr);
136-
nqp::deletekey(%!released_indexes, $reg.index);
101+
my $reg := nqp::pop(@arr);
102+
nqp::bindpos_i(@!released_indexes, nqp::unbox_u($reg), 0);
103+
$reg
137104
}
138105
else {
139-
$reg := MAST::Local.new(:index($!frame.add_local($type)));
106+
MAST::Local.new(:index($!frame.add_local(@types[$kind])));
140107
}
141-
$reg
142108
}
143109

144110
method release_i($reg) { self.release_register($reg, $MVM_reg_int64) }
@@ -147,22 +113,11 @@ my class MASTCompilerInstance {
147113
method release_o($reg) { self.release_register($reg, $MVM_reg_obj) }
148114

149115
method release_register($reg, int $kind, int $force = 0) {
150-
return 1 if $kind == $MVM_reg_void || !$force && $*BLOCK.is_var($reg)
151-
|| nqp::existskey(%!released_indexes, $reg.index);
152-
%!released_indexes{$reg.index} := 1;
153-
return nqp::push(@!int64s, $reg) if $kind == $MVM_reg_int64;
154-
return nqp::push(@!num64s, $reg) if $kind == $MVM_reg_num64;
155-
return nqp::push(@!strs, $reg) if $kind == $MVM_reg_str;
156-
return nqp::push(@!objs, $reg) if $kind == $MVM_reg_obj;
157-
return nqp::push(@!int32s, $reg) if $kind == $MVM_reg_int32;
158-
return nqp::push(@!int16s, $reg) if $kind == $MVM_reg_int16;
159-
return nqp::push(@!int8s, $reg) if $kind == $MVM_reg_int8;
160-
return nqp::push(@!num32s, $reg) if $kind == $MVM_reg_num32;
161-
return nqp::push(@!uint64s, $reg) if $kind == $MVM_reg_uint64;
162-
return nqp::push(@!uint32s, $reg) if $kind == $MVM_reg_uint32;
163-
return nqp::push(@!uint16s, $reg) if $kind == $MVM_reg_uint16;
164-
return nqp::push(@!uint8s, $reg) if $kind == $MVM_reg_uint8;
165-
nqp::die("Unhandled reg kind $kind");
116+
unless $kind == $MVM_reg_void || !$force && $*BLOCK.is_var($reg) {
117+
nqp::bindpos_i(@!released_indexes, nqp::unbox_u($reg), 1);
118+
nqp::push(@!released[$kind], $reg);
119+
}
120+
NQPMu
166121
}
167122
}
168123

0 commit comments

Comments
 (0)