Skip to content

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).

Edited by Sylvain Henry
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information