UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

178 lines (148 loc) 16.3 kB
import { APPEND_OPCODES } from '../opcodes'; import { $pc, $ra, $fp, $sp } from '@glimmer/vm'; import { assert } from '@glimmer/util'; export function initializeRegisters() { return [0, -1, 0, 0]; } export function initializeRegistersWithSP(sp) { return [0, -1, sp, 0]; } export 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 && assert(typeof pc === 'number' && !isNaN(pc), 'pc is set to a number'); this.registers[$pc] = pc; } // Start a new frame and save $ra and $fp on the stack ; _proto.pushFrame = function pushFrame() { this.stack.push(this.registers[$ra]); this.stack.push(this.registers[$fp]); this.registers[$fp] = this.registers[$sp] - 1; } // Restore $ra, $sp and $fp ; _proto.popFrame = function popFrame() { this.registers[$sp] = this.registers[$fp] - 1; this.registers[$ra] = this.stack.get(0); this.registers[$fp] = this.stack.get(1); }; _proto.pushSmallFrame = function pushSmallFrame() { this.stack.push(this.registers[$ra]); }; _proto.popSmallFrame = function popSmallFrame() { this.registers[$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[$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 && assert(handle < 0xffffffff, "Jumping to placeholder address"); this.registers[$ra] = this.registers[$pc]; this.setPc(this.heap.getaddr(handle)); } // Put a specific `program` address in $ra ; _proto.returnTo = function returnTo(offset) { this.registers[$ra] = this.target(offset); } // Return to the `program` address stored in $ra ; _proto["return"] = function _return() { this.setPc(this.registers[$ra]); }; _proto.nextStatement = function nextStatement() { var registers = this.registers, program = this.program; var pc = registers[$pc]; false && 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[$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) { APPEND_OPCODES.evaluate(vm, opcode, opcode.type); }; return LowLevelVM; }(); export { LowLevelVM as default }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL2xvdy1sZXZlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxTQUFBLGNBQUEsUUFBQSxZQUFBO0FBR0EsU0FBQSxHQUFBLEVBQUEsR0FBQSxFQUFBLEdBQUEsRUFBQSxHQUFBLFFBQUEsYUFBQTtBQUNBLFNBQUEsTUFBQSxRQUFBLGVBQUE7QUFTQSxPQUFNLFNBQUEsbUJBQUEsR0FBNkI7QUFDakMsU0FBTyxDQUFBLENBQUEsRUFBSSxDQUFKLENBQUEsRUFBQSxDQUFBLEVBQVAsQ0FBTyxDQUFQO0FBQ0Q7QUFFRCxPQUFNLFNBQUEseUJBQUEsQ0FBQSxFQUFBLEVBQThDO0FBQ2xELFNBQU8sQ0FBQSxDQUFBLEVBQUksQ0FBSixDQUFBLEVBQUEsRUFBQSxFQUFQLENBQU8sQ0FBUDtBQUNEO0FBRUQsT0FBTSxTQUFBLHlCQUFBLENBQUEsRUFBQSxFQUE4QztBQUNsRCxTQUFPLENBQUEsRUFBQSxFQUFLLENBQUwsQ0FBQSxFQUFBLENBQUEsRUFBUCxDQUFPLENBQVA7QUFDRDs7SUFhYSxVO0FBR1osc0JBQUEsS0FBQSxFQUFBLElBQUEsRUFBQSxPQUFBLEVBQUEsT0FBQSxFQUFBLFNBQUEsRUFLdUM7QUFKOUIsU0FBQSxLQUFBLEdBQUEsS0FBQTtBQUNBLFNBQUEsSUFBQSxHQUFBLElBQUE7QUFDQSxTQUFBLE9BQUEsR0FBQSxPQUFBO0FBQ0EsU0FBQSxPQUFBLEdBQUEsT0FBQTtBQUNFLFNBQUEsU0FBQSxHQUFBLFNBQUE7QUFQSixTQUFBLGFBQUEsR0FBQSxDQUFBO0FBUUg7Ozs7U0FFSixhLEdBQUEsdUJBQWEsUUFBYixFQUF1QztBQUNyQyxXQUFPLEtBQUEsU0FBQSxDQUFQLFFBQU8sQ0FBUDtBQUNELEc7O1NBRUQsWSxHQUFBLHNCQUFZLFFBQVosRUFBWSxLQUFaLEVBQXFEO0FBQ25ELFNBQUEsU0FBQSxDQUFBLFFBQUEsSUFBQSxLQUFBO0FBQ0QsRzs7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LEdBQU8sQ0FBUDtBQWRKO0FBZ0JELEc7O1NBRUQsZSxHQUFBLHlCQUFlLE1BQWYsRUFBZSxFQUFmLEVBQXlDO0FBQ3ZDLElBQUEsY0FBYyxDQUFkLFFBQUEsQ0FBQSxFQUFBLEVBQUEsTUFBQSxFQUFvQyxNQUFNLENBQTFDLElBQUE7QUFDRCxHOzs7OztTQTFJVyxVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT3B0aW9uLCBSdW50aW1lSGVhcCwgTWFjaGluZU9wLCBSdW50aW1lUHJvZ3JhbSwgUnVudGltZU9wIH0gZnJvbSAnQGdsaW1tZXIvaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBBUFBFTkRfT1BDT0RFUyB9IGZyb20gJy4uL29wY29kZXMnO1xuaW1wb3J0IFZNIGZyb20gJy4vYXBwZW5kJztcbmltcG9ydCB7IExPQ0FMX0RFQlVHIH0gZnJvbSAnQGdsaW1tZXIvbG9jYWwtZGVidWctZmxhZ3MnO1xuaW1wb3J0IHsgTWFjaGluZVJlZ2lzdGVyLCAkcGMsICRyYSwgJGZwLCAkc3AgfSBmcm9tICdAZ2xpbW1lci92bSc7XG5pbXBvcnQgeyBhc3NlcnQgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcblxuZXhwb3J0IGludGVyZmFjZSBMb3dMZXZlbFJlZ2lzdGVycyB7XG4gIFtNYWNoaW5lUmVnaXN0ZXIucGNdOiBudW1iZXI7XG4gIFtNYWNoaW5lUmVnaXN0ZXIucmFdOiBudW1iZXI7XG4gIFtNYWNoaW5lUmVnaXN0ZXIuc3BdOiBudW1iZXI7XG4gIFtNYWNoaW5lUmVnaXN0ZXIuZnBdOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplUmVnaXN0ZXJzKCk6IExvd0xldmVsUmVnaXN0ZXJzIHtcbiAgcmV0dXJuIFswLCAtMSwgMCwgMF07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplUmVnaXN0ZXJzV2l0aFNQKHNwOiBudW1iZXIpOiBMb3dMZXZlbFJlZ2lzdGVycyB7XG4gIHJldHVybiBbMCwgLTEsIHNwLCAwXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVSZWdpc3RlcnNXaXRoUEMocGM6IG51bWJlcik6IExvd0xldmVsUmVnaXN0ZXJzIHtcbiAgcmV0dXJuIFtwYywgLTEsIDAsIDBdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YWNrIHtcbiAgcHVzaCh2YWx1ZTogdW5rbm93bik6IHZvaWQ7XG4gIGdldChwb3NpdGlvbjogbnVtYmVyKTogbnVtYmVyO1xuICBwb3A8VD4oKTogVDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFeHRlcm5zIHtcbiAgZGVidWdCZWZvcmUob3Bjb2RlOiBSdW50aW1lT3ApOiB1bmtub3duO1xuICBkZWJ1Z0FmdGVyKHN0YXRlOiB1bmtub3duKTogdm9pZDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTG93TGV2ZWxWTSB7XG4gIHB1YmxpYyBjdXJyZW50T3BTaXplID0gMDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgc3RhY2s6IFN0YWNrLFxuICAgIHB1YmxpYyBoZWFwOiBSdW50aW1lSGVhcCxcbiAgICBwdWJsaWMgcHJvZ3JhbTogUnVudGltZVByb2dyYW0sXG4gICAgcHVibGljIGV4dGVybnM6IEV4dGVybnMsXG4gICAgcmVhZG9ubHkgcmVnaXN0ZXJzOiBMb3dMZXZlbFJlZ2lzdGVyc1xuICApIHt9XG5cbiAgZmV0Y2hSZWdpc3RlcihyZWdpc3RlcjogTWFjaGluZVJlZ2lzdGVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RlcnNbcmVnaXN0ZXJdO1xuICB9XG5cbiAgbG9hZFJlZ2lzdGVyKHJlZ2lzdGVyOiBNYWNoaW5lUmVnaXN0ZXIsIHZhbHVlOiBudW1iZXIpIHtcbiAgICB0aGlzLnJlZ2lzdGVyc1tyZWdpc3Rlcl0gPSB2YWx1ZTtcbiAgfVxuXG4gIHNldFBjKHBjOiBudW1iZXIpOiB2b2lkIHtcbiAgICBhc3NlcnQodHlwZW9mIHBjID09PSAnbnVtYmVyJyAmJiAhaXNOYU4ocGMpLCAncGMgaXMgc2V0IHRvIGEgbnVtYmVyJyk7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHBjXSA9IHBjO1xuICB9XG5cbiAgLy8gU3RhcnQgYSBuZXcgZnJhbWUgYW5kIHNhdmUgJHJhIGFuZCAkZnAgb24gdGhlIHN0YWNrXG4gIHB1c2hGcmFtZSgpIHtcbiAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5yZWdpc3RlcnNbJHJhXSk7XG4gICAgdGhpcy5zdGFjay5wdXNoKHRoaXMucmVnaXN0ZXJzWyRmcF0pO1xuICAgIHRoaXMucmVnaXN0ZXJzWyRmcF0gPSB0aGlzLnJlZ2lzdGVyc1skc3BdIC0gMTtcbiAgfVxuXG4gIC8vIFJlc3RvcmUgJHJhLCAkc3AgYW5kICRmcFxuICBwb3BGcmFtZSgpIHtcbiAgICB0aGlzLnJlZ2lzdGVyc1skc3BdID0gdGhpcy5yZWdpc3RlcnNbJGZwXSAtIDE7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHJhXSA9IHRoaXMuc3RhY2suZ2V0KDApO1xuICAgIHRoaXMucmVnaXN0ZXJzWyRmcF0gPSB0aGlzLnN0YWNrLmdldCgxKTtcbiAgfVxuXG4gIHB1c2hTbWFsbEZyYW1lKCkge1xuICAgIHRoaXMuc3RhY2sucHVzaCh0aGlzLnJlZ2lzdGVyc1skcmFdKTtcbiAgfVxuXG4gIHBvcFNtYWxsRnJhbWUoKSB7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHJhXSA9IHRoaXMuc3RhY2sucG9wKCk7XG4gIH1cblxuICAvLyBKdW1wIHRvIGFuIGFkZHJlc3MgaW4gYHByb2dyYW1gXG4gIGdvdG8ob2Zmc2V0OiBudW1iZXIpIHtcbiAgICB0aGlzLnNldFBjKHRoaXMudGFyZ2V0KG9mZnNldCkpO1xuICB9XG5cbiAgdGFyZ2V0KG9mZnNldDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0ZXJzWyRwY10gKyBvZmZzZXQgLSB0aGlzLmN1cnJlbnRPcFNpemU7XG4gIH1cblxuICAvLyBTYXZlICRwYyBpbnRvICRyYSwgdGhlbiBqdW1wIHRvIGEgbmV3IGFkZHJlc3MgaW4gYHByb2dyYW1gIChqYWwgaW4gTUlQUylcbiAgY2FsbChoYW5kbGU6IG51bWJlcikge1xuICAgIGFzc2VydChoYW5kbGUgPCAweGZmZmZmZmZmLCBgSnVtcGluZyB0byBwbGFjZWhvbGRlciBhZGRyZXNzYCk7XG5cbiAgICB0aGlzLnJlZ2lzdGVyc1skcmFdID0gdGhpcy5yZWdpc3RlcnNbJHBjXTtcbiAgICB0aGlzLnNldFBjKHRoaXMuaGVhcC5nZXRhZGRyKGhhbmRsZSkpO1xuICB9XG5cbiAgLy8gUHV0IGEgc3BlY2lmaWMgYHByb2dyYW1gIGFkZHJlc3MgaW4gJHJhXG4gIHJldHVyblRvKG9mZnNldDogbnVtYmVyKSB7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHJhXSA9IHRoaXMudGFyZ2V0KG9mZnNldCk7XG4gIH1cblxuICAvLyBSZXR1cm4gdG8gdGhlIGBwcm9ncmFtYCBhZGRyZXNzIHN0b3JlZCBpbiAkcmFcbiAgcmV0dXJuKCkge1xuICAgIHRoaXMuc2V0UGModGhpcy5yZWdpc3RlcnNbJHJhXSk7XG4gIH1cblxuICBuZXh0U3RhdGVtZW50KCk6IE9wdGlvbjxSdW50aW1lT3A+IHtcbiAgICBsZXQgeyByZWdpc3RlcnMsIHByb2dyYW0gfSA9IHRoaXM7XG5cbiAgICBsZXQgcGMgPSByZWdpc3RlcnNbJHBjXTtcblxuICAgIGFzc2VydCh0eXBlb2YgcGMgPT09ICdudW1iZXInLCAncGMgaXMgYSBudW1iZXInKTtcblxuICAgIGlmIChwYyA9PT0gLTEpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIFdlIGhhdmUgdG8gc2F2ZSBvZmYgdGhlIGN1cnJlbnQgb3BlcmF0aW9ucyBzaXplIHNvIHRoYXRcbiAgICAvLyB3aGVuIHdlIGRvIGEganVtcCB3ZSBjYW4gY2FsY3VsYXRlIHRoZSBjb3JyZWN0IG9mZnNldFxuICAgIC8vIHRvIHdoZXJlIHdlIGFyZSBnb2luZy4gV2UgY2FuJ3Qgc2ltcGx5IGFzayBmb3IgdGhlIHNpemVcbiAgICAvLyBpbiBhIGp1bXAgYmVjYXVzZSB3ZSBoYXZlIGhhdmUgYWxyZWFkeSBpbmNyZW1lbnRlZCB0aGVcbiAgICAvLyBwcm9ncmFtIGNvdW50ZXIgdG8gdGhlIG5leHQgaW5zdHJ1Y3Rpb24gcHJpb3IgdG8gZXhlY3V0aW5nLlxuICAgIGxldCBvcGNvZGUgPSBwcm9ncmFtLm9wY29kZShwYyk7XG4gICAgbGV0IG9wZXJhdGlvblNpemUgPSAodGhpcy5jdXJyZW50T3BTaXplID0gb3Bjb2RlLnNpemUpO1xuICAgIHRoaXMucmVnaXN0ZXJzWyRwY10gKz0gb3BlcmF0aW9uU2l6ZTtcblxuICAgIHJldHVybiBvcGNvZGU7XG4gIH1cblxuICBldmFsdWF0ZU91dGVyKG9wY29kZTogUnVudGltZU9wLCB2bTogVk0pIHtcbiAgICBpZiAoTE9DQUxfREVCVUcpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIGV4dGVybnM6IHsgZGVidWdCZWZvcmUsIGRlYnVnQWZ0ZXIgfSxcbiAgICAgIH0gPSB0aGlzO1xuICAgICAgbGV0IHN0YXRlID0gZGVidWdCZWZvcmUob3Bjb2RlKTtcbiAgICAgIHRoaXMuZXZhbHVhdGVJbm5lcihvcGNvZGUsIHZtKTtcbiAgICAgIGRlYnVnQWZ0ZXIoc3RhdGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmV2YWx1YXRlSW5uZXIob3Bjb2RlLCB2bSk7XG4gICAgfVxuICB9XG5cbiAgZXZhbHVhdGVJbm5lcihvcGNvZGU6IFJ1bnRpbWVPcCwgdm06IFZNKSB7XG4gICAgaWYgKG9wY29kZS5pc01hY2hpbmUpIHtcbiAgICAgIHRoaXMuZXZhbHVhdGVNYWNoaW5lKG9wY29kZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZXZhbHVhdGVTeXNjYWxsKG9wY29kZSwgdm0pO1xuICAgIH1cbiAgfVxuXG4gIGV2YWx1YXRlTWFjaGluZShvcGNvZGU6IFJ1bnRpbWVPcCkge1xuICAgIHN3aXRjaCAob3Bjb2RlLnR5cGUpIHtcbiAgICAgIGNhc2UgTWFjaGluZU9wLlB1c2hGcmFtZTpcbiAgICAgICAgcmV0dXJuIHRoaXMucHVzaEZyYW1lKCk7XG4gICAgICBjYXNlIE1hY2hpbmVPcC5Qb3BGcmFtZTpcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wRnJhbWUoKTtcbiAgICAgIGNhc2UgTWFjaGluZU9wLkludm9rZVN0YXRpYzpcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsbChvcGNvZGUub3AxKTtcbiAgICAgIGNhc2UgTWFjaGluZU9wLkludm9rZVZpcnR1YWw6XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGwodGhpcy5zdGFjay5wb3AoKSk7XG4gICAgICBjYXNlIE1hY2hpbmVPcC5KdW1wOlxuICAgICAgICByZXR1cm4gdGhpcy5nb3RvKG9wY29kZS5vcDEpO1xuICAgICAgY2FzZSBNYWNoaW5lT3AuUmV0dXJuOlxuICAgICAgICByZXR1cm4gdGhpcy5yZXR1cm4oKTtcbiAgICAgIGNhc2UgTWFjaGluZU9wLlJldHVyblRvOlxuICAgICAgICByZXR1cm4gdGhpcy5yZXR1cm5UbyhvcGNvZGUub3AxKTtcbiAgICB9XG4gIH1cblxuICBldmFsdWF0ZVN5c2NhbGwob3Bjb2RlOiBSdW50aW1lT3AsIHZtOiBWTSkge1xuICAgIEFQUEVORF9PUENPREVTLmV2YWx1YXRlKHZtLCBvcGNvZGUsIG9wY29kZS50eXBlKTtcbiAgfVxufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==