@glimmer/runtime
Version:
Minimal runtime needed to render Glimmer templates
195 lines (153 loc) • 15.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.initializeRegisters = initializeRegisters;
exports.initializeRegistersWithSP = initializeRegistersWithSP;
exports.initializeRegistersWithPC = initializeRegistersWithPC;
exports.default = void 0;
var _opcodes = require("../opcodes");
var _vm = require("@glimmer/vm");
var _util = require("@glimmer/util");
function initializeRegisters() {
return [0, -1, 0, 0];
}
function initializeRegistersWithSP(sp) {
return [0, -1, sp, 0];
}
function initializeRegistersWithPC(pc) {
return [pc, -1, 0, 0];
}
class LowLevelVM {
constructor(stack, heap, program, externs, registers) {
this.stack = stack;
this.heap = heap;
this.program = program;
this.externs = externs;
this.registers = registers;
this.currentOpSize = 0;
}
fetchRegister(register) {
return this.registers[register];
}
loadRegister(register, value) {
this.registers[register] = value;
}
setPc(pc) {
false && (0, _util.assert)(typeof pc === 'number' && !isNaN(pc), 'pc is set to a number');
this.registers[_vm.$pc] = pc;
} // Start a new frame and save $ra and $fp on the stack
pushFrame() {
this.stack.push(this.registers[_vm.$ra]);
this.stack.push(this.registers[_vm.$fp]);
this.registers[_vm.$fp] = this.registers[_vm.$sp] - 1;
} // Restore $ra, $sp and $fp
popFrame() {
this.registers[_vm.$sp] = this.registers[_vm.$fp] - 1;
this.registers[_vm.$ra] = this.stack.get(0);
this.registers[_vm.$fp] = this.stack.get(1);
}
pushSmallFrame() {
this.stack.push(this.registers[_vm.$ra]);
}
popSmallFrame() {
this.registers[_vm.$ra] = this.stack.pop();
} // Jump to an address in `program`
goto(offset) {
this.setPc(this.target(offset));
}
target(offset) {
return this.registers[_vm.$pc] + offset - this.currentOpSize;
} // Save $pc into $ra, then jump to a new address in `program` (jal in MIPS)
call(handle) {
false && (0, _util.assert)(handle < 0xffffffff, `Jumping to placeholder address`);
this.registers[_vm.$ra] = this.registers[_vm.$pc];
this.setPc(this.heap.getaddr(handle));
} // Put a specific `program` address in $ra
returnTo(offset) {
this.registers[_vm.$ra] = this.target(offset);
} // Return to the `program` address stored in $ra
return() {
this.setPc(this.registers[_vm.$ra]);
}
nextStatement() {
let {
registers,
program
} = this;
let pc = registers[_vm.$pc];
false && (0, _util.assert)(typeof pc === 'number', 'pc is a number');
if (pc === -1) {
return null;
} // We have to save off the current operations size so that
// when we do a jump we can calculate the correct offset
// to where we are going. We can't simply ask for the size
// in a jump because we have have already incremented the
// program counter to the next instruction prior to executing.
let opcode = program.opcode(pc);
let operationSize = this.currentOpSize = opcode.size;
this.registers[_vm.$pc] += operationSize;
return opcode;
}
evaluateOuter(opcode, vm) {
if (false
/* LOCAL_DEBUG */
) {
let {
externs: {
debugBefore,
debugAfter
}
} = this;
let state = debugBefore(opcode);
this.evaluateInner(opcode, vm);
debugAfter(state);
} else {
this.evaluateInner(opcode, vm);
}
}
evaluateInner(opcode, vm) {
if (opcode.isMachine) {
this.evaluateMachine(opcode);
} else {
this.evaluateSyscall(opcode, vm);
}
}
evaluateMachine(opcode) {
switch (opcode.type) {
case 0
/* PushFrame */
:
return this.pushFrame();
case 1
/* PopFrame */
:
return this.popFrame();
case 3
/* InvokeStatic */
:
return this.call(opcode.op1);
case 2
/* InvokeVirtual */
:
return this.call(this.stack.pop());
case 4
/* Jump */
:
return this.goto(opcode.op1);
case 5
/* Return */
:
return this.return();
case 6
/* ReturnTo */
:
return this.returnTo(opcode.op1);
}
}
evaluateSyscall(opcode, vm) {
_opcodes.APPEND_OPCODES.evaluate(vm, opcode, opcode.type);
}
}
exports.default = LowLevelVM;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL2xvdy1sZXZlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQ0E7O0FBR0E7O0FBQ0E7O0FBU00sU0FBQSxtQkFBQSxHQUE2QjtBQUNqQyxTQUFPLENBQUEsQ0FBQSxFQUFJLENBQUosQ0FBQSxFQUFBLENBQUEsRUFBUCxDQUFPLENBQVA7QUFDRDs7QUFFSyxTQUFBLHlCQUFBLENBQUEsRUFBQSxFQUE4QztBQUNsRCxTQUFPLENBQUEsQ0FBQSxFQUFJLENBQUosQ0FBQSxFQUFBLEVBQUEsRUFBUCxDQUFPLENBQVA7QUFDRDs7QUFFSyxTQUFBLHlCQUFBLENBQUEsRUFBQSxFQUE4QztBQUNsRCxTQUFPLENBQUEsRUFBQSxFQUFLLENBQUwsQ0FBQSxFQUFBLENBQUEsRUFBUCxDQUFPLENBQVA7QUFDRDs7QUFhYSxNQUFBLFVBQUEsQ0FBaUI7QUFHN0IsRUFBQSxXQUFBLENBQUEsS0FBQSxFQUFBLElBQUEsRUFBQSxPQUFBLEVBQUEsT0FBQSxFQUFBLFNBQUEsRUFLdUM7QUFKOUIsU0FBQSxLQUFBLEdBQUEsS0FBQTtBQUNBLFNBQUEsSUFBQSxHQUFBLElBQUE7QUFDQSxTQUFBLE9BQUEsR0FBQSxPQUFBO0FBQ0EsU0FBQSxPQUFBLEdBQUEsT0FBQTtBQUNFLFNBQUEsU0FBQSxHQUFBLFNBQUE7QUFQSixTQUFBLGFBQUEsR0FBQSxDQUFBO0FBUUg7O0FBRUosRUFBQSxhQUFhLENBQUEsUUFBQSxFQUEwQjtBQUNyQyxXQUFPLEtBQUEsU0FBQSxDQUFQLFFBQU8sQ0FBUDtBQUNEOztBQUVELEVBQUEsWUFBWSxDQUFBLFFBQUEsRUFBQSxLQUFBLEVBQXlDO0FBQ25ELFNBQUEsU0FBQSxDQUFBLFFBQUEsSUFBQSxLQUFBO0FBQ0Q7O0FBRUQsRUFBQSxLQUFLLENBQUEsRUFBQSxFQUFXO0FBQUEsYUFDZCxrQkFBTyxPQUFBLEVBQUEsS0FBQSxRQUFBLElB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QUFBLGVBQWUsQ0FBQSxNQUFBLEVBQUEsRUFBQSxFQUEwQjtBQUN2Qyw0QkFBQSxRQUFBLENBQUEsRUFBQSxFQUFBLE1BQUEsRUFBb0MsTUFBTSxDQUExQyxJQUFBO0FBQ0Q7O0FBMUk0QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9wdGlvbiwgUnVudGltZUhlYXAsIE1hY2hpbmVPcCwgUnVudGltZVByb2dyYW0sIFJ1bnRpbWVPcCB9IGZyb20gJ0BnbGltbWVyL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgQVBQRU5EX09QQ09ERVMgfSBmcm9tICcuLi9vcGNvZGVzJztcbmltcG9ydCBWTSBmcm9tICcuL2FwcGVuZCc7XG5pbXBvcnQgeyBMT0NBTF9ERUJVRyB9IGZyb20gJ0BnbGltbWVyL2xvY2FsLWRlYnVnLWZsYWdzJztcbmltcG9ydCB7IE1hY2hpbmVSZWdpc3RlciwgJHBjLCAkcmEsICRmcCwgJHNwIH0gZnJvbSAnQGdsaW1tZXIvdm0nO1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSAnQGdsaW1tZXIvdXRpbCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG93TGV2ZWxSZWdpc3RlcnMge1xuICBbTWFjaGluZVJlZ2lzdGVyLnBjXTogbnVtYmVyO1xuICBbTWFjaGluZVJlZ2lzdGVyLnJhXTogbnVtYmVyO1xuICBbTWFjaGluZVJlZ2lzdGVyLnNwXTogbnVtYmVyO1xuICBbTWFjaGluZVJlZ2lzdGVyLmZwXTogbnVtYmVyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZVJlZ2lzdGVycygpOiBMb3dMZXZlbFJlZ2lzdGVycyB7XG4gIHJldHVybiBbMCwgLTEsIDAsIDBdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZVJlZ2lzdGVyc1dpdGhTUChzcDogbnVtYmVyKTogTG93TGV2ZWxSZWdpc3RlcnMge1xuICByZXR1cm4gWzAsIC0xLCBzcCwgMF07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplUmVnaXN0ZXJzV2l0aFBDKHBjOiBudW1iZXIpOiBMb3dMZXZlbFJlZ2lzdGVycyB7XG4gIHJldHVybiBbcGMsIC0xLCAwLCAwXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdGFjayB7XG4gIHB1c2godmFsdWU6IHVua25vd24pOiB2b2lkO1xuICBnZXQocG9zaXRpb246IG51bWJlcik6IG51bWJlcjtcbiAgcG9wPFQ+KCk6IFQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXh0ZXJucyB7XG4gIGRlYnVnQmVmb3JlKG9wY29kZTogUnVudGltZU9wKTogdW5rbm93bjtcbiAgZGVidWdBZnRlcihzdGF0ZTogdW5rbm93bik6IHZvaWQ7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExvd0xldmVsVk0ge1xuICBwdWJsaWMgY3VycmVudE9wU2l6ZSA9IDA7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIHN0YWNrOiBTdGFjayxcbiAgICBwdWJsaWMgaGVhcDogUnVudGltZUhlYXAsXG4gICAgcHVibGljIHByb2dyYW06IFJ1bnRpbWVQcm9ncmFtLFxuICAgIHB1YmxpYyBleHRlcm5zOiBFeHRlcm5zLFxuICAgIHJlYWRvbmx5IHJlZ2lzdGVyczogTG93TGV2ZWxSZWdpc3RlcnNcbiAgKSB7fVxuXG4gIGZldGNoUmVnaXN0ZXIocmVnaXN0ZXI6IE1hY2hpbmVSZWdpc3Rlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0ZXJzW3JlZ2lzdGVyXTtcbiAgfVxuXG4gIGxvYWRSZWdpc3RlcihyZWdpc3RlcjogTWFjaGluZVJlZ2lzdGVyLCB2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5yZWdpc3RlcnNbcmVnaXN0ZXJdID0gdmFsdWU7XG4gIH1cblxuICBzZXRQYyhwYzogbnVtYmVyKTogdm9pZCB7XG4gICAgYXNzZXJ0KHR5cGVvZiBwYyA9PT0gJ251bWJlcicgJiYgIWlzTmFOKHBjKSwgJ3BjIGlzIHNldCB0byBhIG51bWJlcicpO1xuICAgIHRoaXMucmVnaXN0ZXJzWyRwY10gPSBwYztcbiAgfVxuXG4gIC8vIFN0YXJ0IGEgbmV3IGZyYW1lIGFuZCBzYXZlICRyYSBhbmQgJGZwIG9uIHRoZSBzdGFja1xuICBwdXNoRnJhbWUoKSB7XG4gICAgdGhpcy5zdGFjay5wdXNoKHRoaXMucmVnaXN0ZXJzWyRyYV0pO1xuICAgIHRoaXMuc3RhY2sucHVzaCh0aGlzLnJlZ2lzdGVyc1skZnBdKTtcbiAgICB0aGlzLnJlZ2lzdGVyc1skZnBdID0gdGhpcy5yZWdpc3RlcnNbJHNwXSAtIDE7XG4gIH1cblxuICAvLyBSZXN0b3JlICRyYSwgJHNwIGFuZCAkZnBcbiAgcG9wRnJhbWUoKSB7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHNwXSA9IHRoaXMucmVnaXN0ZXJzWyRmcF0gLSAxO1xuICAgIHRoaXMucmVnaXN0ZXJzWyRyYV0gPSB0aGlzLnN0YWNrLmdldCgwKTtcbiAgICB0aGlzLnJlZ2lzdGVyc1skZnBdID0gdGhpcy5zdGFjay5nZXQoMSk7XG4gIH1cblxuICBwdXNoU21hbGxGcmFtZSgpIHtcbiAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5yZWdpc3RlcnNbJHJhXSk7XG4gIH1cblxuICBwb3BTbWFsbEZyYW1lKCkge1xuICAgIHRoaXMucmVnaXN0ZXJzWyRyYV0gPSB0aGlzLnN0YWNrLnBvcCgpO1xuICB9XG5cbiAgLy8gSnVtcCB0byBhbiBhZGRyZXNzIGluIGBwcm9ncmFtYFxuICBnb3RvKG9mZnNldDogbnVtYmVyKSB7XG4gICAgdGhpcy5zZXRQYyh0aGlzLnRhcmdldChvZmZzZXQpKTtcbiAgfVxuXG4gIHRhcmdldChvZmZzZXQ6IG51bWJlcikge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdGVyc1skcGNdICsgb2Zmc2V0IC0gdGhpcy5jdXJyZW50T3BTaXplO1xuICB9XG5cbiAgLy8gU2F2ZSAkcGMgaW50byAkcmEsIHRoZW4ganVtcCB0byBhIG5ldyBhZGRyZXNzIGluIGBwcm9ncmFtYCAoamFsIGluIE1JUFMpXG4gIGNhbGwoaGFuZGxlOiBudW1iZXIpIHtcbiAgICBhc3NlcnQoaGFuZGxlIDwgMHhmZmZmZmZmZiwgYEp1bXBpbmcgdG8gcGxhY2Vob2xkZXIgYWRkcmVzc2ApO1xuXG4gICAgdGhpcy5yZWdpc3RlcnNbJHJhXSA9IHRoaXMucmVnaXN0ZXJzWyRwY107XG4gICAgdGhpcy5zZXRQYyh0aGlzLmhlYXAuZ2V0YWRkcihoYW5kbGUpKTtcbiAgfVxuXG4gIC8vIFB1dCBhIHNwZWNpZmljIGBwcm9ncmFtYCBhZGRyZXNzIGluICRyYVxuICByZXR1cm5UbyhvZmZzZXQ6IG51bWJlcikge1xuICAgIHRoaXMucmVnaXN0ZXJzWyRyYV0gPSB0aGlzLnRhcmdldChvZmZzZXQpO1xuICB9XG5cbiAgLy8gUmV0dXJuIHRvIHRoZSBgcHJvZ3JhbWAgYWRkcmVzcyBzdG9yZWQgaW4gJHJhXG4gIHJldHVybigpIHtcbiAgICB0aGlzLnNldFBjKHRoaXMucmVnaXN0ZXJzWyRyYV0pO1xuICB9XG5cbiAgbmV4dFN0YXRlbWVudCgpOiBPcHRpb248UnVudGltZU9wPiB7XG4gICAgbGV0IHsgcmVnaXN0ZXJzLCBwcm9ncmFtIH0gPSB0aGlzO1xuXG4gICAgbGV0IHBjID0gcmVnaXN0ZXJzWyRwY107XG5cbiAgICBhc3NlcnQodHlwZW9mIHBjID09PSAnbnVtYmVyJywgJ3BjIGlzIGEgbnVtYmVyJyk7XG5cbiAgICBpZiAocGMgPT09IC0xKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBXZSBoYXZlIHRvIHNhdmUgb2ZmIHRoZSBjdXJyZW50IG9wZXJhdGlvbnMgc2l6ZSBzbyB0aGF0XG4gICAgLy8gd2hlbiB3ZSBkbyBhIGp1bXAgd2UgY2FuIGNhbGN1bGF0ZSB0aGUgY29ycmVjdCBvZmZzZXRcbiAgICAvLyB0byB3aGVyZSB3ZSBhcmUgZ29pbmcuIFdlIGNhbid0IHNpbXBseSBhc2sgZm9yIHRoZSBzaXplXG4gICAgLy8gaW4gYSBqdW1wIGJlY2F1c2Ugd2UgaGF2ZSBoYXZlIGFscmVhZHkgaW5jcmVtZW50ZWQgdGhlXG4gICAgLy8gcHJvZ3JhbSBjb3VudGVyIHRvIHRoZSBuZXh0IGluc3RydWN0aW9uIHByaW9yIHRvIGV4ZWN1dGluZy5cbiAgICBsZXQgb3Bjb2RlID0gcHJvZ3JhbS5vcGNvZGUocGMpO1xuICAgIGxldCBvcGVyYXRpb25TaXplID0gKHRoaXMuY3VycmVudE9wU2l6ZSA9IG9wY29kZS5zaXplKTtcbiAgICB0aGlzLnJlZ2lzdGVyc1skcGNdICs9IG9wZXJhdGlvblNpemU7XG5cbiAgICByZXR1cm4gb3Bjb2RlO1xuICB9XG5cbiAgZXZhbHVhdGVPdXRlcihvcGNvZGU6IFJ1bnRpbWVPcCwgdm06IFZNKSB7XG4gICAgaWYgKExPQ0FMX0RFQlVHKSB7XG4gICAgICBsZXQge1xuICAgICAgICBleHRlcm5zOiB7IGRlYnVnQmVmb3JlLCBkZWJ1Z0FmdGVyIH0sXG4gICAgICB9ID0gdGhpcztcbiAgICAgIGxldCBzdGF0ZSA9IGRlYnVnQmVmb3JlKG9wY29kZSk7XG4gICAgICB0aGlzLmV2YWx1YXRlSW5uZXIob3Bjb2RlLCB2bSk7XG4gICAgICBkZWJ1Z0FmdGVyKHN0YXRlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5ldmFsdWF0ZUlubmVyKG9wY29kZSwgdm0pO1xuICAgIH1cbiAgfVxuXG4gIGV2YWx1YXRlSW5uZXIob3Bjb2RlOiBSdW50aW1lT3AsIHZtOiBWTSkge1xuICAgIGlmIChvcGNvZGUuaXNNYWNoaW5lKSB7XG4gICAgICB0aGlzLmV2YWx1YXRlTWFjaGluZShvcGNvZGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmV2YWx1YXRlU3lzY2FsbChvcGNvZGUsIHZtKTtcbiAgICB9XG4gIH1cblxuICBldmFsdWF0ZU1hY2hpbmUob3Bjb2RlOiBSdW50aW1lT3ApIHtcbiAgICBzd2l0Y2ggKG9wY29kZS50eXBlKSB7XG4gICAgICBjYXNlIE1hY2hpbmVPcC5QdXNoRnJhbWU6XG4gICAgICAgIHJldHVybiB0aGlzLnB1c2hGcmFtZSgpO1xuICAgICAgY2FzZSBNYWNoaW5lT3AuUG9wRnJhbWU6XG4gICAgICAgIHJldHVybiB0aGlzLnBvcEZyYW1lKCk7XG4gICAgICBjYXNlIE1hY2hpbmVPcC5JbnZva2VTdGF0aWM6XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGwob3Bjb2RlLm9wMSk7XG4gICAgICBjYXNlIE1hY2hpbmVPcC5JbnZva2VWaXJ0dWFsOlxuICAgICAgICByZXR1cm4gdGhpcy5jYWxsKHRoaXMuc3RhY2sucG9wKCkpO1xuICAgICAgY2FzZSBNYWNoaW5lT3AuSnVtcDpcbiAgICAgICAgcmV0dXJuIHRoaXMuZ290byhvcGNvZGUub3AxKTtcbiAgICAgIGNhc2UgTWFjaGluZU9wLlJldHVybjpcbiAgICAgICAgcmV0dXJuIHRoaXMucmV0dXJuKCk7XG4gICAgICBjYXNlIE1hY2hpbmVPcC5SZXR1cm5UbzpcbiAgICAgICAgcmV0dXJuIHRoaXMucmV0dXJuVG8ob3Bjb2RlLm9wMSk7XG4gICAgfVxuICB9XG5cbiAgZXZhbHVhdGVTeXNjYWxsKG9wY29kZTogUnVudGltZU9wLCB2bTogVk0pIHtcbiAgICBBUFBFTkRfT1BDT0RFUy5ldmFsdWF0ZSh2bSwgb3Bjb2RlLCBvcGNvZGUudHlwZSk7XG4gIH1cbn1cbiJdLCJzb3VyY2VSb290IjoiIn0=