UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

195 lines (153 loc) 15.9 kB
"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=