JS: change infotable representation for more code sharing
Currently in the JS backend we use a kind of "tables-next-to-code" representation for infotables. Note that JS functions are objects and as such they can have properties. The JS backend uses this to represent infotables: an infotable is represented by a JS function (the entry code) with specific properties (the other infotable fields).
With this scheme we need a different entry function for every infotable. For example consider:
data Zig = Zig Int
data Zag = Zag Int
We'll generate:
// Entry code for Zig
function h$mainZCMainziZZig_con_e() {
return h$rs(); -- return to stack
};
// exactly the same for Zag
function h$mainZCMainziZZag_con_e() {
return h$rs();
};
// Zig alloc function
function h$mainZCMainziZZig_e() {
var a = h$r2;
h$r1 = h$c1(h$mainZCMainziZZig_con_e, a);
return h$rs();
};
// Same for Zag: almost the same code, just not the same "infotable" argument for h$c1
function h$mainZCMainziZZag_e() {
var a = h$r2;
h$r1 = h$c1(h$mainZCMainziZZag_con_e, a);
return h$rs();
};
// Infotable fields setting
h$o(h$mainZCMainziZZig_e, 1, 257, 0, 257, null);
h$o(h$mainZCMainziZZig_con_e, 2, 1, 1, 256, null);
h$o(h$mainZCMainziZZag_e, 1, 257, 0, 257, null);
h$o(h$mainZCMainziZZag_con_e, 2, 1, 1, 256, null);
////////////////////////////////////////////////////
// In rts.js we have (when debug mode is disabled)
function h$o(o, typ, a, size, regs, srefs) {
h$setObjInfo(o, typ, "", [], a, size, regs, srefs);
}
// set heap/stack object information
function h$setObjInfo(o, typ, name, fields, a, size, regs, srefs) {
o.t = typ;
o.i = fields;
o.n = name;
o.a = a;
o.r = regs;
o.s = srefs;
o.m = 0
o.size = size;
}
/////////////////////////////////////////////////////
Proposal
What we could do instead is to use infotable objects with a function field for the entry code.
var h$mainZCMainziZZig_table = new InfoTable(h$mainZCMainziZZig_e, 1, 257, 0, 257, null);
var h$mainZCMainziZZig_con_table = new InfoTable(h$mainZCMainziZZig_con_e, 2, 1, 1, 256, null);
var h$mainZCMainziZZag_table = new InfoTable(h$mainZCMainziZZag_e, 1, 257, 0, 257, null);
var h$mainZCMainziZZag_con_table = new InfoTable(h$mainZCMainziZZag_con_e, 2, 1, 1, 256, null);
It would allow us to share identical entry codes automatically (with some AST hashing):
var h$mainZCMainziZZag_con_table = new InfoTable(h$mainZCMainziZZig_con_e, 2, 1, 1, 256, null); // Zag reuses Zig entry code
// we could even use h$rs directly:
var h$mainZCMainziZZag_con_table = new InfoTable(h$rs, 2, 1, 1, 256, null);
And even Infotable sharing (with InfoTable hashing):
var h$mainZCMainziZZag_con_table = h$mainZCmainziZZig_con_table;
We would substitute directly instead of generating this assignment, so then we would be able to see that h$mainZCMainziZZag_e
has actually the same code as h$mainZCMainziZZig_e
, etc.
Note that the current representation was introduced because it was supposed to be faster to call infotable()
than to call infotable.entry_code()
. We'll have to benchmark it. If there is a difference, we will have to introduce a flag to select between both approaches (performance versus code size).