@glimmer/runtime
Version:
Minimal runtime needed to render Glimmer templates
193 lines (156 loc) • 16.6 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];
}
var LowLevelVM = /*#__PURE__*/function () {
function LowLevelVM(stack, heap, program, externs, registers) {
this.stack = stack;
this.heap = heap;
this.program = program;
this.externs = externs;
this.registers = registers;
this.currentOpSize = 0;
}
var _proto = LowLevelVM.prototype;
_proto.fetchRegister = function fetchRegister(register) {
return this.registers[register];
};
_proto.loadRegister = function loadRegister(register, value) {
this.registers[register] = value;
};
_proto.setPc = function 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
;
_proto.pushFrame = function 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
;
_proto.popFrame = function 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);
};
_proto.pushSmallFrame = function pushSmallFrame() {
this.stack.push(this.registers[_vm.$ra]);
};
_proto.popSmallFrame = function popSmallFrame() {
this.registers[_vm.$ra] = this.stack.pop();
} // Jump to an address in `program`
;
_proto["goto"] = function goto(offset) {
this.setPc(this.target(offset));
};
_proto.target = function 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)
;
_proto.call = function 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
;
_proto.returnTo = function returnTo(offset) {
this.registers[_vm.$ra] = this.target(offset);
} // Return to the `program` address stored in $ra
;
_proto["return"] = function _return() {
this.setPc(this.registers[_vm.$ra]);
};
_proto.nextStatement = function nextStatement() {
var registers = this.registers,
program = this.program;
var 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.
var opcode = program.opcode(pc);
var operationSize = this.currentOpSize = opcode.size;
this.registers[_vm.$pc] += operationSize;
return opcode;
};
_proto.evaluateOuter = function evaluateOuter(opcode, vm) {
if (false
/* LOCAL_DEBUG */
) {
var _this$externs = this.externs,
debugBefore = _this$externs.debugBefore,
debugAfter = _this$externs.debugAfter;
var state = debugBefore(opcode);
this.evaluateInner(opcode, vm);
debugAfter(state);
} else {
this.evaluateInner(opcode, vm);
}
};
_proto.evaluateInner = function evaluateInner(opcode, vm) {
if (opcode.isMachine) {
this.evaluateMachine(opcode);
} else {
this.evaluateSyscall(opcode, vm);
}
};
_proto.evaluateMachine = function 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);
}
};
_proto.evaluateSyscall = function evaluateSyscall(opcode, vm) {
_opcodes.APPEND_OPCODES.evaluate(vm, opcode, opcode.type);
};
return LowLevelVM;
}();
exports.default = LowLevelVM;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL2xvdy1sZXZlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQ0E7O0FBR0E7O0FBQ0E7O0FBU00sU0FBQSxtQkFBQSxHQUE2QjtBQUNqQyxTQUFPLENBQUEsQ0FBQSxFQUFJLENBQUosQ0FBQSxFQUFBLENBQUEsRUFBUCxDQUFPLENBQVA7QUFDRDs7QUFFSyxTQUFBLHlCQUFBLENBQUEsRUFBQSxFQUE4QztBQUNsRCxTQUFPLENBQUEsQ0FBQSxFQUFJLENBQUosQ0FBQSxFQUFBLEVBQUEsRUFBUCxDQUFPLENBQVA7QUFDRDs7QUFFSyxTQUFBLHlCQUFBLENBQUEsRUFBQSxFQUE4QztBQUNsRCxTQUFPLENBQUEsRUFBQSxFQUFLLENBQUwsQ0FBQSxFQUFBLENBQUEsRUFBUCxDQUFPLENBQVA7QUFDRDs7SUFhYSxVO0FBR1osV0FBQSxVQUFBLENBQUEsS0FBQSxFQUFBLElBQUEsRUFBQSxPQUFBLEVBQUEsT0FBQSxFQUFBLFNBQUEsRUFLdUM7QUFKOUIsU0FBQSxLQUFBLEdBQUEsS0FBQTtBQUNBLFNBQUEsSUFBQSxHQUFBLElBQUE7QUFDQSxTQUFBLE9BQUEsR0FBQSxPQUFBO0FBQ0EsU0FBQSxPQUFBLEdBQUEsT0FBQTtBQUNFLFNBQUEsU0FBQSxHQUFBLFNBQUE7QUFQSixTQUFBLGFBQUEsR0FBQSxDQUFBO0FBUUg7Ozs7U0FFSixhLEdBQUEsU0FBQSxhQUFBLENBQUEsUUFBQSxFQUF1QztBQUNyQyxXQUFPLEtBQUEsU0FBQSxDQUFQLFFBQU8sQ0FBUDs7O1NBR0YsWSxHQUFBLFNBQUEsWUFBQSxDQUFBLFFBQUEsRUFBQSxLQUFBLEVBQXFEO0FBQ25ELFNBQUEsU0FBQSxDQUFBLFFBQUEsSUFBQSxLQUFBOzs7U0FHRixLLEdBQUEsU0FBQSxLQUFBLENBQUEsRUFBQSxFQUFnQjtBQUFBLGFBQ2Qsa0JBQU8sT0FBQSxFQUFBLEtBQUEsUUFBQSxJ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QkYsZSxHQUFBLFNBQUEsZUFBQSxDQUFBLE1BQUEsRUFBQSxFQUFBLEVBQXlDO0FBQ3ZDLDRCQUFBLFFBQUEsQ0FBQSxFQUFBLEVBQUEsTUFBQSxFQUFvQyxNQUFNLENBQTFDLElBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPcHRpb24sIFJ1bnRpbWVIZWFwLCBNYWNoaW5lT3AsIFJ1bnRpbWVQcm9ncmFtLCBSdW50aW1lT3AgfSBmcm9tICdAZ2xpbW1lci9pbnRlcmZhY2VzJztcbmltcG9ydCB7IEFQUEVORF9PUENPREVTIH0gZnJvbSAnLi4vb3Bjb2Rlcyc7XG5pbXBvcnQgVk0gZnJvbSAnLi9hcHBlbmQnO1xuaW1wb3J0IHsgTE9DQUxfREVCVUcgfSBmcm9tICdAZ2xpbW1lci9sb2NhbC1kZWJ1Zy1mbGFncyc7XG5pbXBvcnQgeyBNYWNoaW5lUmVnaXN0ZXIsICRwYywgJHJhLCAkZnAsICRzcCB9IGZyb20gJ0BnbGltbWVyL3ZtJztcbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJ0BnbGltbWVyL3V0aWwnO1xuXG5leHBvcnQgaW50ZXJmYWNlIExvd0xldmVsUmVnaXN0ZXJzIHtcbiAgW01hY2hpbmVSZWdpc3Rlci5wY106IG51bWJlcjtcbiAgW01hY2hpbmVSZWdpc3Rlci5yYV06IG51bWJlcjtcbiAgW01hY2hpbmVSZWdpc3Rlci5zcF06IG51bWJlcjtcbiAgW01hY2hpbmVSZWdpc3Rlci5mcF06IG51bWJlcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVSZWdpc3RlcnMoKTogTG93TGV2ZWxSZWdpc3RlcnMge1xuICByZXR1cm4gWzAsIC0xLCAwLCAwXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVSZWdpc3RlcnNXaXRoU1Aoc3A6IG51bWJlcik6IExvd0xldmVsUmVnaXN0ZXJzIHtcbiAgcmV0dXJuIFswLCAtMSwgc3AsIDBdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZVJlZ2lzdGVyc1dpdGhQQyhwYzogbnVtYmVyKTogTG93TGV2ZWxSZWdpc3RlcnMge1xuICByZXR1cm4gW3BjLCAtMSwgMCwgMF07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhY2sge1xuICBwdXNoKHZhbHVlOiB1bmtub3duKTogdm9pZDtcbiAgZ2V0KHBvc2l0aW9uOiBudW1iZXIpOiBudW1iZXI7XG4gIHBvcDxUPigpOiBUO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEV4dGVybnMge1xuICBkZWJ1Z0JlZm9yZShvcGNvZGU6IFJ1bnRpbWVPcCk6IHVua25vd247XG4gIGRlYnVnQWZ0ZXIoc3RhdGU6IHVua25vd24pOiB2b2lkO1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMb3dMZXZlbFZNIHtcbiAgcHVibGljIGN1cnJlbnRPcFNpemUgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBzdGFjazogU3RhY2ssXG4gICAgcHVibGljIGhlYXA6IFJ1bnRpbWVIZWFwLFxuICAgIHB1YmxpYyBwcm9ncmFtOiBSdW50aW1lUHJvZ3JhbSxcbiAgICBwdWJsaWMgZXh0ZXJuczogRXh0ZXJucyxcbiAgICByZWFkb25seSByZWdpc3RlcnM6IExvd0xldmVsUmVnaXN0ZXJzXG4gICkge31cblxuICBmZXRjaFJlZ2lzdGVyKHJlZ2lzdGVyOiBNYWNoaW5lUmVnaXN0ZXIpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdGVyc1tyZWdpc3Rlcl07XG4gIH1cblxuICBsb2FkUmVnaXN0ZXIocmVnaXN0ZXI6IE1hY2hpbmVSZWdpc3RlciwgdmFsdWU6IG51bWJlcikge1xuICAgIHRoaXMucmVnaXN0ZXJzW3JlZ2lzdGVyXSA9IHZhbHVlO1xuICB9XG5cbiAgc2V0UGMocGM6IG51bWJlcik6IHZvaWQge1xuICAgIGFzc2VydCh0eXBlb2YgcGMgPT09ICdudW1iZXInICYmICFpc05hTihwYyksICdwYyBpcyBzZXQgdG8gYSBudW1iZXInKTtcbiAgICB0aGlzLnJlZ2lzdGVyc1skcGNdID0gcGM7XG4gIH1cblxuICAvLyBTdGFydCBhIG5ldyBmcmFtZSBhbmQgc2F2ZSAkcmEgYW5kICRmcCBvbiB0aGUgc3RhY2tcbiAgcHVzaEZyYW1lKCkge1xuICAgIHRoaXMuc3RhY2sucHVzaCh0aGlzLnJlZ2lzdGVyc1skcmFdKTtcbiAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5yZWdpc3RlcnNbJGZwXSk7XG4gICAgdGhpcy5yZWdpc3RlcnNbJGZwXSA9IHRoaXMucmVnaXN0ZXJzWyRzcF0gLSAxO1xuICB9XG5cbiAgLy8gUmVzdG9yZSAkcmEsICRzcCBhbmQgJGZwXG4gIHBvcEZyYW1lKCkge1xuICAgIHRoaXMucmVnaXN0ZXJzWyRzcF0gPSB0aGlzLnJlZ2lzdGVyc1skZnBdIC0gMTtcbiAgICB0aGlzLnJlZ2lzdGVyc1skcmFdID0gdGhpcy5zdGFjay5nZXQoMCk7XG4gICAgdGhpcy5yZWdpc3RlcnNbJGZwXSA9IHRoaXMuc3RhY2suZ2V0KDEpO1xuICB9XG5cbiAgcHVzaFNtYWxsRnJhbWUoKSB7XG4gICAgdGhpcy5zdGFjay5wdXNoKHRoaXMucmVnaXN0ZXJzWyRyYV0pO1xuICB9XG5cbiAgcG9wU21hbGxGcmFtZSgpIHtcbiAgICB0aGlzLnJlZ2lzdGVyc1skcmFdID0gdGhpcy5zdGFjay5wb3AoKTtcbiAgfVxuXG4gIC8vIEp1bXAgdG8gYW4gYWRkcmVzcyBpbiBgcHJvZ3JhbWBcbiAgZ290byhvZmZzZXQ6IG51bWJlcikge1xuICAgIHRoaXMuc2V0UGModGhpcy50YXJnZXQob2Zmc2V0KSk7XG4gIH1cblxuICB0YXJnZXQob2Zmc2V0OiBudW1iZXIpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RlcnNbJHBjXSArIG9mZnNldCAtIHRoaXMuY3VycmVudE9wU2l6ZTtcbiAgfVxuXG4gIC8vIFNhdmUgJHBjIGludG8gJHJhLCB0aGVuIGp1bXAgdG8gYSBuZXcgYWRkcmVzcyBpbiBgcHJvZ3JhbWAgKGphbCBpbiBNSVBTKVxuICBjYWxsKGhhbmRsZTogbnVtYmVyKSB7XG4gICAgYXNzZXJ0KGhhbmRsZSA8IDB4ZmZmZmZmZmYsIGBKdW1waW5nIHRvIHBsYWNlaG9sZGVyIGFkZHJlc3NgKTtcblxuICAgIHRoaXMucmVnaXN0ZXJzWyRyYV0gPSB0aGlzLnJlZ2lzdGVyc1skcGNdO1xuICAgIHRoaXMuc2V0UGModGhpcy5oZWFwLmdldGFkZHIoaGFuZGxlKSk7XG4gIH1cblxuICAvLyBQdXQgYSBzcGVjaWZpYyBgcHJvZ3JhbWAgYWRkcmVzcyBpbiAkcmFcbiAgcmV0dXJuVG8ob2Zmc2V0OiBudW1iZXIpIHtcbiAgICB0aGlzLnJlZ2lzdGVyc1skcmFdID0gdGhpcy50YXJnZXQob2Zmc2V0KTtcbiAgfVxuXG4gIC8vIFJldHVybiB0byB0aGUgYHByb2dyYW1gIGFkZHJlc3Mgc3RvcmVkIGluICRyYVxuICByZXR1cm4oKSB7XG4gICAgdGhpcy5zZXRQYyh0aGlzLnJlZ2lzdGVyc1skcmFdKTtcbiAgfVxuXG4gIG5leHRTdGF0ZW1lbnQoKTogT3B0aW9uPFJ1bnRpbWVPcD4ge1xuICAgIGxldCB7IHJlZ2lzdGVycywgcHJvZ3JhbSB9ID0gdGhpcztcblxuICAgIGxldCBwYyA9IHJlZ2lzdGVyc1skcGNdO1xuXG4gICAgYXNzZXJ0KHR5cGVvZiBwYyA9PT0gJ251bWJlcicsICdwYyBpcyBhIG51bWJlcicpO1xuXG4gICAgaWYgKHBjID09PSAtMSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gV2UgaGF2ZSB0byBzYXZlIG9mZiB0aGUgY3VycmVudCBvcGVyYXRpb25zIHNpemUgc28gdGhhdFxuICAgIC8vIHdoZW4gd2UgZG8gYSBqdW1wIHdlIGNhbiBjYWxjdWxhdGUgdGhlIGNvcnJlY3Qgb2Zmc2V0XG4gICAgLy8gdG8gd2hlcmUgd2UgYXJlIGdvaW5nLiBXZSBjYW4ndCBzaW1wbHkgYXNrIGZvciB0aGUgc2l6ZVxuICAgIC8vIGluIGEganVtcCBiZWNhdXNlIHdlIGhhdmUgaGF2ZSBhbHJlYWR5IGluY3JlbWVudGVkIHRoZVxuICAgIC8vIHByb2dyYW0gY291bnRlciB0byB0aGUgbmV4dCBpbnN0cnVjdGlvbiBwcmlvciB0byBleGVjdXRpbmcuXG4gICAgbGV0IG9wY29kZSA9IHByb2dyYW0ub3Bjb2RlKHBjKTtcbiAgICBsZXQgb3BlcmF0aW9uU2l6ZSA9ICh0aGlzLmN1cnJlbnRPcFNpemUgPSBvcGNvZGUuc2l6ZSk7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHBjXSArPSBvcGVyYXRpb25TaXplO1xuXG4gICAgcmV0dXJuIG9wY29kZTtcbiAgfVxuXG4gIGV2YWx1YXRlT3V0ZXIob3Bjb2RlOiBSdW50aW1lT3AsIHZtOiBWTSkge1xuICAgIGlmIChMT0NBTF9ERUJVRykge1xuICAgICAgbGV0IHtcbiAgICAgICAgZXh0ZXJuczogeyBkZWJ1Z0JlZm9yZSwgZGVidWdBZnRlciB9LFxuICAgICAgfSA9IHRoaXM7XG4gICAgICBsZXQgc3RhdGUgPSBkZWJ1Z0JlZm9yZShvcGNvZGUpO1xuICAgICAgdGhpcy5ldmFsdWF0ZUlubmVyKG9wY29kZSwgdm0pO1xuICAgICAgZGVidWdBZnRlcihzdGF0ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZXZhbHVhdGVJbm5lcihvcGNvZGUsIHZtKTtcbiAgICB9XG4gIH1cblxuICBldmFsdWF0ZUlubmVyKG9wY29kZTogUnVudGltZU9wLCB2bTogVk0pIHtcbiAgICBpZiAob3Bjb2RlLmlzTWFjaGluZSkge1xuICAgICAgdGhpcy5ldmFsdWF0ZU1hY2hpbmUob3Bjb2RlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5ldmFsdWF0ZVN5c2NhbGwob3Bjb2RlLCB2bSk7XG4gICAgfVxuICB9XG5cbiAgZXZhbHVhdGVNYWNoaW5lKG9wY29kZTogUnVudGltZU9wKSB7XG4gICAgc3dpdGNoIChvcGNvZGUudHlwZSkge1xuICAgICAgY2FzZSBNYWNoaW5lT3AuUHVzaEZyYW1lOlxuICAgICAgICByZXR1cm4gdGhpcy5wdXNoRnJhbWUoKTtcbiAgICAgIGNhc2UgTWFjaGluZU9wLlBvcEZyYW1lOlxuICAgICAgICByZXR1cm4gdGhpcy5wb3BGcmFtZSgpO1xuICAgICAgY2FzZSBNYWNoaW5lT3AuSW52b2tlU3RhdGljOlxuICAgICAgICByZXR1cm4gdGhpcy5jYWxsKG9wY29kZS5vcDEpO1xuICAgICAgY2FzZSBNYWNoaW5lT3AuSW52b2tlVmlydHVhbDpcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsbCh0aGlzLnN0YWNrLnBvcCgpKTtcbiAgICAgIGNhc2UgTWFjaGluZU9wLkp1bXA6XG4gICAgICAgIHJldHVybiB0aGlzLmdvdG8ob3Bjb2RlLm9wMSk7XG4gICAgICBjYXNlIE1hY2hpbmVPcC5SZXR1cm46XG4gICAgICAgIHJldHVybiB0aGlzLnJldHVybigpO1xuICAgICAgY2FzZSBNYWNoaW5lT3AuUmV0dXJuVG86XG4gICAgICAgIHJldHVybiB0aGlzLnJldHVyblRvKG9wY29kZS5vcDEpO1xuICAgIH1cbiAgfVxuXG4gIGV2YWx1YXRlU3lzY2FsbChvcGNvZGU6IFJ1bnRpbWVPcCwgdm06IFZNKSB7XG4gICAgQVBQRU5EX09QQ09ERVMuZXZhbHVhdGUodm0sIG9wY29kZSwgb3Bjb2RlLnR5cGUpO1xuICB9XG59XG4iXSwic291cmNlUm9vdCI6IiJ9