Efficient GOTO
JavaScript performance comparison
Info
This jsperf is to explore options for generating JS out of luajit bytecode. https://gist.github.com/4206005#file_compiled.js
Preparation code
<script>
Benchmark.prototype.setup = function() {
function proto1(env, args, exit) {
// Allocate slots for frames
var f0, f1, f2, f3;
// Split the code into blocks to enable jumps
function _0001() {
f0 = [ null, 'This', 'is', 'a', 'stream?' ]; //0001 TDUP 0 0
f1 = 1; //0002 KSHORT 1 1
f2 = env.print; //0003 GGET 2 1 ; "print"
f3 = "before"; //0004 KSTR 3 2 ; "before"
f2(f3); //0005 CALL 2 1 2
return _0006;
}
function _0006() {
f2 = f0[f1]; //0006 => TGETV 2 0 1
if (!f2) //0007 ISF 2
return _0015; //0008 JMP 3 => 0015
//0009 LOOP 2 => 0015
f2 = env.print; //0010 GGET 2 1 ; "print"
f3 = f0[f1]; //0011 TGETV 3 0 1
f2(f3); //0012 CALL 2 1 2
f1 = f1 + 1; //0013 ADDVN 1 1 0 ; 1
return _0006; //0014 JMP 2 => 0006
}
function _0015() {
f2 = env.print; //0015 => GGET 2 1 ; "print"
f3 = "after"; //0016 KSTR 3 3 ; "after"
f2(f3); //0017 CALL 2 1 2
exit(null, []); //0018 RET0 0 1
}
// Run a little trampoline to enable the gotos
var next = _0001;
while (next = next());
}
function proto2(env, args, exit) {
// Allocate slots for frames
var f0, f1, f2, f3;
// Split the code into blocks to enable jumps
var blocks = {
_0001: function () {
f0 = [ null, 'This', 'is', 'a', 'stream?' ]; //0001 TDUP 0 0
f1 = 1; //0002 KSHORT 1 1
f2 = env.print; //0003 GGET 2 1 ; "print"
f3 = "before"; //0004 KSTR 3 2 ; "before"
f2(f3); //0005 CALL 2 1 2
return "_0006";
},
_0006: function () {
f2 = f0[f1]; //0006 => TGETV 2 0 1
if (!f2) //0007 ISF 2
return "_0015"; //0008 JMP 3 => 0015
//0009 LOOP 2 => 0015
f2 = env.print; //0010 GGET 2 1 ; "print"
f3 = f0[f1]; //0011 TGETV 3 0 1
f2(f3); //0012 CALL 2 1 2
f1 = f1 + 1; //0013 ADDVN 1 1 0 ; 1
return "_0006"; //0014 JMP 2 => 0006
},
_0015: function () {
f2 = env.print; //0015 => GGET 2 1 ; "print"
f3 = "after"; //0016 KSTR 3 3 ; "after"
f2(f3); //0017 CALL 2 1 2
exit(null, []); //0018 RET0 0 1
}
};
// Run a little trampoline to enable the gotos
var next = "_0001";
while (next = blocks[next]());
}
function proto3(env, args, exit) {
// Allocate slots for frames
var f0, f1, f2, f3;
var state = "0001";
main: while(true) {
switch(state) {
case "0001":
f0 = [ null, 'This', 'is', 'a', 'stream?' ]; //0001 TDUP 0 0
f1 = 1; //0002 KSHORT 1 1
f2 = env.print; //0003 GGET 2 1 ; "print"
f3 = "before"; //0004 KSTR 3 2 ; "before"
f2(f3); //0005 CALL 2 1 2
state = "0006";
break;
case "0006":
f2 = f0[f1]; //0006 => TGETV 2 0 1
if (!f2) { //0007 ISF 2
state = "0015"; //0008 JMP 3 => 0015
break;
}
// no-op tracing hook //0009 LOOP 2 => 0015
f2 = env.print; //0010 GGET 2 1 ; "print"
f3 = f0[f1]; //0011 TGETV 3 0 1
f2(f3); //0012 CALL 2 1 2
f1 = f1 + 1; //0013 ADDVN 1 1 0 ; 1
state = "0006"; //0014 JMP 2 => 0006
break;
case "0015":
f2 = env.print; //0015 => GGET 2 1 ; "print"
f3 = "after"; //0016 KSTR 3 3 ; "after"
f2(f3); //0017 CALL 2 1 2
exit(null, []); //0018 RET0 0 1
break main;
}
}
}
function proto4(env, args, exit) {
// Allocate slots for frames
var f0, f1, f2, f3;
var state = "0001";
for(;;) {
switch(state) {
case "0001":
f0 = [ null, 'This', 'is', 'a', 'stream?' ]; //0001 TDUP 0 0
f1 = 1; //0002 KSHORT 1 1
f2 = env.print; //0003 GGET 2 1 ; "print"
f3 = "before"; //0004 KSTR 3 2 ; "before"
f2(f3); //0005 CALL 2 1 2
state = "0006";
break;
case "0006":
f2 = f0[f1]; //0006 => TGETV 2 0 1
if (!f2) { //0007 ISF 2
state = "0015"; //0008 JMP 3 => 0015
break;
}
// no-op tracing hook //0009 LOOP 2 => 0015
f2 = env.print; //0010 GGET 2 1 ; "print"
f3 = f0[f1]; //0011 TGETV 3 0 1
f2(f3); //0012 CALL 2 1 2
f1 = f1 + 1; //0013 ADDVN 1 1 0 ; 1
state = "0006"; //0014 JMP 2 => 0006
break;
case "0015":
f2 = env.print; //0015 => GGET 2 1 ; "print"
f3 = "after"; //0016 KSTR 3 3 ; "after"
f2(f3); //0017 CALL 2 1 2
return exit(null, []); //0018 RET0 0 1
}
}
}
// Set up some global functions
var _G = {
print: function () {
//console.log(Array.prototype.join.call(arguments, " "));
return [];
}
};
function onExit(err, results) {
if (err) throw err;
}
};
</script>
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
Named Function Blocks |
|
pending… |
Object Function Blocks |
|
pending… |
Switch Blocks |
|
pending… |
For / Switch Blocks + Return |
|
pending… |
Compare results of other browsers
Revisions
You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:
- Revision 1: published by Tim Caswell
- Revision 2: published
0 comments