Hi!
Concerning another discussion about VMs for Octave I thought I should share a partial implementation of one I made during sleepy time on my paternity leave.
Essentially it is a custom stack-ish VM which calls Octave Cpp code for the different opcodes. There is one stack for data.
There is still functionality that is missing. Eg.:
- Catching exceptions (it just unwinds now)
- eval, assignin, clear etc
- switch
- classes
- stack overflow check
- Only 256 slots for variables (Need “far slots”)
- Automatic compilation
… and more. E.g. it can’t unwind in a for-loop yet.
My approach might need some rework to make stack fiddling with eval and friends work – that’s probably the main annoying todo part missing.
The speed gains of using the VM depends on what code is executed. For scalar for loops it is about 5-10x and for recursive functions it is about 15-20x. About the square root of the speed improvement is due to other changes in the hooked in code and applies to the tree walker interpreter too. There is probably some more low hanging fruit to pick to speed up the VM.
See attached pathes. They are squashed to two patches from many.
octave_31191.patch (839.9 KB)
octave_31192.patch (7.5 KB)
The interesting files are:
pt-bytecode-vm.cc
pt-bytecode-walk.cc
and maybe the test/compile folder.
Usage:
compile foo % Compiles function foo in foo.m to bytecode
compile foo clear % Deletes bytecode
compile foo print % Print opcodes
Example:
function i = testspeed_bc ()
tic;
sortperf(50000);
toc; % 3.9s -> 0.27s
tic;
for j = 1:10000000
b = 1*2*3*4*5*6*7*8;
end
toc; %8.5s -> 1.35s
tic;
for j = 1:10000000
sin (j);
end
toc; % 22.2s -> 2.07s
end
function b = qsort(a)
b = qsort_kernel(a, 1, length(a));
end
function a = qsort_kernel(a, lo, hi)
i = lo;
j = hi;
while i < hi
pivot = a(floor((lo+hi)/2));
while i <= j
while a(i) < pivot, i = i + 1; end
while a(j) > pivot, j = j - 1; end
if i <= j
t = a(i);
a(i) = a(j);
a(j) = t;
i = i + 1;
j = j - 1;
end
end
if lo < j; a=qsort_kernel(a, lo, j); end
lo = i;
j = hi;
end
end
function v = sortperf(n)
v = rand(n,1);
v = qsort(v);
end