UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

177 lines (144 loc) 15.7 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]; } export default 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 && 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 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 popFrame() { this.registers[$sp] = this.registers[$fp] - 1; this.registers[$ra] = this.stack.get(0); this.registers[$fp] = this.stack.get(1); } pushSmallFrame() { this.stack.push(this.registers[$ra]); } popSmallFrame() { this.registers[$ra] = this.stack.pop(); } // Jump to an address in `program` goto(offset) { this.setPc(this.target(offset)); } target(offset) { return this.registers[$pc] + offset - this.currentOpSize; } // Save $pc into $ra, then jump to a new address in `program` (jal in MIPS) 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 returnTo(offset) { this.registers[$ra] = this.target(offset); } // Return to the `program` address stored in $ra return() { this.setPc(this.registers[$ra]); } nextStatement() { let { registers, program } = this; let 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. let opcode = program.opcode(pc); let operationSize = this.currentOpSize = opcode.size; this.registers[$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) { APPEND_OPCODES.evaluate(vm, opcode, opcode.type); } } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL2xvdy1sZXZlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxTQUFTLGNBQVQsUUFBK0IsWUFBL0I7QUFHQSxTQUEwQixHQUExQixFQUErQixHQUEvQixFQUFvQyxHQUFwQyxFQUF5QyxHQUF6QyxRQUFvRCxhQUFwRDtBQUNBLFNBQVMsTUFBVCxRQUF1QixlQUF2QjtBQVNBLE9BQU0sU0FBVSxtQkFBVixHQUE2QjtBQUNqQyxTQUFPLENBQUMsQ0FBRCxFQUFJLENBQUMsQ0FBTCxFQUFRLENBQVIsRUFBVyxDQUFYLENBQVA7QUFDRDtBQUVELE9BQU0sU0FBVSx5QkFBVixDQUFvQyxFQUFwQyxFQUE4QztBQUNsRCxTQUFPLENBQUMsQ0FBRCxFQUFJLENBQUMsQ0FBTCxFQUFRLEVBQVIsRUFBWSxDQUFaLENBQVA7QUFDRDtBQUVELE9BQU0sU0FBVSx5QkFBVixDQUFvQyxFQUFwQyxFQUE4QztBQUNsRCxTQUFPLENBQUMsRUFBRCxFQUFLLENBQUMsQ0FBTixFQUFTLENBQVQsRUFBWSxDQUFaLENBQVA7QUFDRDtBQWFELGVBQWMsTUFBTyxVQUFQLENBQWlCO0FBRzdCLEVBQUEsV0FBQSxDQUNTLEtBRFQsRUFFUyxJQUZULEVBR1MsT0FIVCxFQUlTLE9BSlQsRUFLVyxTQUxYLEVBS3VDO0FBSjlCLFNBQUEsS0FBQSxHQUFBLEtBQUE7QUFDQSxTQUFBLElBQUEsR0FBQSxJQUFBO0FBQ0EsU0FBQSxPQUFBLEdBQUEsT0FBQTtBQUNBLFNBQUEsT0FBQSxHQUFBLE9BQUE7QUFDRSxTQUFBLFNBQUEsR0FBQSxTQUFBO0FBUEosU0FBQSxhQUFBLEdBQWdCLENBQWhCO0FBUUg7O0FBRUosRUFBQSxhQUFhLENBQUMsUUFBRCxFQUEwQjtBQUNyQyxXQUFPLEtBQUssU0FBTCxDQUFlLFFBQWYsQ0FBUDtBQUNEOztBQUVELEVBQUEsWUFBWSxDQUFDLFFBQUQsRUFBNEIsS0FBNUIs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QVA7O0FBQ0YsV0FBQTtBQUFBO0FBQUE7QUFDRSxlQUFPLEtBQUssTUFBTCxFQUFQOztBQUNGLFdBQUE7QUFBQTtBQUFBO0FBQ0UsZUFBTyxLQUFLLFFBQUwsQ0FBYyxNQUFNLENBQUMsR0FBckIsQ0FBUDtBQWRKO0FBZ0JEOztBQUVELEVBQUEsZUFBZSxDQUFDLE1BQUQsRUFBb0IsRUFBcEIsRUFBMEI7QUFDdkMsSUFBQSxjQUFjLENBQUMsUUFBZixDQUF3QixFQUF4QixFQUE0QixNQUE1QixFQUFvQyxNQUFNLENBQUMsSUFBM0M7QUFDRDs7QUExSTRCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT3B0aW9uLCBSdW50aW1lSGVhcCwgTWFjaGluZU9wLCBSdW50aW1lUHJvZ3JhbSwgUnVudGltZU9wIH0gZnJvbSAnQGdsaW1tZXIvaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBBUFBFTkRfT1BDT0RFUyB9IGZyb20gJy4uL29wY29kZXMnO1xuaW1wb3J0IFZNIGZyb20gJy4vYXBwZW5kJztcbmltcG9ydCB7IExPQ0FMX0RFQlVHIH0gZnJvbSAnQGdsaW1tZXIvbG9jYWwtZGVidWctZmxhZ3MnO1xuaW1wb3J0IHsgTWFjaGluZVJlZ2lzdGVyLCAkcGMsICRyYSwgJGZwLCAkc3AgfSBmcm9tICdAZ2xpbW1lci92bSc7XG5pbXBvcnQgeyBhc3NlcnQgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcblxuZXhwb3J0IGludGVyZmFjZSBMb3dMZXZlbFJlZ2lzdGVycyB7XG4gIFtNYWNoaW5lUmVnaXN0ZXIucGNdOiBudW1iZXI7XG4gIFtNYWNoaW5lUmVnaXN0ZXIucmFdOiBudW1iZXI7XG4gIFtNYWNoaW5lUmVnaXN0ZXIuc3BdOiBudW1iZXI7XG4gIFtNYWNoaW5lUmVnaXN0ZXIuZnBdOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplUmVnaXN0ZXJzKCk6IExvd0xldmVsUmVnaXN0ZXJzIHtcbiAgcmV0dXJuIFswLCAtMSwgMCwgMF07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplUmVnaXN0ZXJzV2l0aFNQKHNwOiBudW1iZXIpOiBMb3dMZXZlbFJlZ2lzdGVycyB7XG4gIHJldHVybiBbMCwgLTEsIHNwLCAwXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVSZWdpc3RlcnNXaXRoUEMocGM6IG51bWJlcik6IExvd0xldmVsUmVnaXN0ZXJzIHtcbiAgcmV0dXJuIFtwYywgLTEsIDAsIDBdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YWNrIHtcbiAgcHVzaCh2YWx1ZTogdW5rbm93bik6IHZvaWQ7XG4gIGdldChwb3NpdGlvbjogbnVtYmVyKTogbnVtYmVyO1xuICBwb3A8VD4oKTogVDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFeHRlcm5zIHtcbiAgZGVidWdCZWZvcmUob3Bjb2RlOiBSdW50aW1lT3ApOiB1bmtub3duO1xuICBkZWJ1Z0FmdGVyKHN0YXRlOiB1bmtub3duKTogdm9pZDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTG93TGV2ZWxWTSB7XG4gIHB1YmxpYyBjdXJyZW50T3BTaXplID0gMDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgc3RhY2s6IFN0YWNrLFxuICAgIHB1YmxpYyBoZWFwOiBSdW50aW1lSGVhcCxcbiAgICBwdWJsaWMgcHJvZ3JhbTogUnVudGltZVByb2dyYW0sXG4gICAgcHVibGljIGV4dGVybnM6IEV4dGVybnMsXG4gICAgcmVhZG9ubHkgcmVnaXN0ZXJzOiBMb3dMZXZlbFJlZ2lzdGVyc1xuICApIHt9XG5cbiAgZmV0Y2hSZWdpc3RlcihyZWdpc3RlcjogTWFjaGluZVJlZ2lzdGVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RlcnNbcmVnaXN0ZXJdO1xuICB9XG5cbiAgbG9hZFJlZ2lzdGVyKHJlZ2lzdGVyOiBNYWNoaW5lUmVnaXN0ZXIsIHZhbHVlOiBudW1iZXIpIHtcbiAgICB0aGlzLnJlZ2lzdGVyc1tyZWdpc3Rlcl0gPSB2YWx1ZTtcbiAgfVxuXG4gIHNldFBjKHBjOiBudW1iZXIpOiB2b2lkIHtcbiAgICBhc3NlcnQodHlwZW9mIHBjID09PSAnbnVtYmVyJyAmJiAhaXNOYU4ocGMpLCAncGMgaXMgc2V0IHRvIGEgbnVtYmVyJyk7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHBjXSA9IHBjO1xuICB9XG5cbiAgLy8gU3RhcnQgYSBuZXcgZnJhbWUgYW5kIHNhdmUgJHJhIGFuZCAkZnAgb24gdGhlIHN0YWNrXG4gIHB1c2hGcmFtZSgpIHtcbiAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5yZWdpc3RlcnNbJHJhXSk7XG4gICAgdGhpcy5zdGFjay5wdXNoKHRoaXMucmVnaXN0ZXJzWyRmcF0pO1xuICAgIHRoaXMucmVnaXN0ZXJzWyRmcF0gPSB0aGlzLnJlZ2lzdGVyc1skc3BdIC0gMTtcbiAgfVxuXG4gIC8vIFJlc3RvcmUgJHJhLCAkc3AgYW5kICRmcFxuICBwb3BGcmFtZSgpIHtcbiAgICB0aGlzLnJlZ2lzdGVyc1skc3BdID0gdGhpcy5yZWdpc3RlcnNbJGZwXSAtIDE7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHJhXSA9IHRoaXMuc3RhY2suZ2V0KDApO1xuICAgIHRoaXMucmVnaXN0ZXJzWyRmcF0gPSB0aGlzLnN0YWNrLmdldCgxKTtcbiAgfVxuXG4gIHB1c2hTbWFsbEZyYW1lKCkge1xuICAgIHRoaXMuc3RhY2sucHVzaCh0aGlzLnJlZ2lzdGVyc1skcmFdKTtcbiAgfVxuXG4gIHBvcFNtYWxsRnJhbWUoKSB7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHJhXSA9IHRoaXMuc3RhY2sucG9wKCk7XG4gIH1cblxuICAvLyBKdW1wIHRvIGFuIGFkZHJlc3MgaW4gYHByb2dyYW1gXG4gIGdvdG8ob2Zmc2V0OiBudW1iZXIpIHtcbiAgICB0aGlzLnNldFBjKHRoaXMudGFyZ2V0KG9mZnNldCkpO1xuICB9XG5cbiAgdGFyZ2V0KG9mZnNldDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0ZXJzWyRwY10gKyBvZmZzZXQgLSB0aGlzLmN1cnJlbnRPcFNpemU7XG4gIH1cblxuICAvLyBTYXZlICRwYyBpbnRvICRyYSwgdGhlbiBqdW1wIHRvIGEgbmV3IGFkZHJlc3MgaW4gYHByb2dyYW1gIChqYWwgaW4gTUlQUylcbiAgY2FsbChoYW5kbGU6IG51bWJlcikge1xuICAgIGFzc2VydChoYW5kbGUgPCAweGZmZmZmZmZmLCBgSnVtcGluZyB0byBwbGFjZWhvbGRlciBhZGRyZXNzYCk7XG5cbiAgICB0aGlzLnJlZ2lzdGVyc1skcmFdID0gdGhpcy5yZWdpc3RlcnNbJHBjXTtcbiAgICB0aGlzLnNldFBjKHRoaXMuaGVhcC5nZXRhZGRyKGhhbmRsZSkpO1xuICB9XG5cbiAgLy8gUHV0IGEgc3BlY2lmaWMgYHByb2dyYW1gIGFkZHJlc3MgaW4gJHJhXG4gIHJldHVyblRvKG9mZnNldDogbnVtYmVyKSB7XG4gICAgdGhpcy5yZWdpc3RlcnNbJHJhXSA9IHRoaXMudGFyZ2V0KG9mZnNldCk7XG4gIH1cblxuICAvLyBSZXR1cm4gdG8gdGhlIGBwcm9ncmFtYCBhZGRyZXNzIHN0b3JlZCBpbiAkcmFcbiAgcmV0dXJuKCkge1xuICAgIHRoaXMuc2V0UGModGhpcy5yZWdpc3RlcnNbJHJhXSk7XG4gIH1cblxuICBuZXh0U3RhdGVtZW50KCk6IE9wdGlvbjxSdW50aW1lT3A+IHtcbiAgICBsZXQgeyByZWdpc3RlcnMsIHByb2dyYW0gfSA9IHRoaXM7XG5cbiAgICBsZXQgcGMgPSByZWdpc3RlcnNbJHBjXTtcblxuICAgIGFzc2VydCh0eXBlb2YgcGMgPT09ICdudW1iZXInLCAncGMgaXMgYSBudW1iZXInKTtcblxuICAgIGlmIChwYyA9PT0gLTEpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIFdlIGhhdmUgdG8gc2F2ZSBvZmYgdGhlIGN1cnJlbnQgb3BlcmF0aW9ucyBzaXplIHNvIHRoYXRcbiAgICAvLyB3aGVuIHdlIGRvIGEganVtcCB3ZSBjYW4gY2FsY3VsYXRlIHRoZSBjb3JyZWN0IG9mZnNldFxuICAgIC8vIHRvIHdoZXJlIHdlIGFyZSBnb2luZy4gV2UgY2FuJ3Qgc2ltcGx5IGFzayBmb3IgdGhlIHNpemVcbiAgICAvLyBpbiBhIGp1bXAgYmVjYXVzZSB3ZSBoYXZlIGhhdmUgYWxyZWFkeSBpbmNyZW1lbnRlZCB0aGVcbiAgICAvLyBwcm9ncmFtIGNvdW50ZXIgdG8gdGhlIG5leHQgaW5zdHJ1Y3Rpb24gcHJpb3IgdG8gZXhlY3V0aW5nLlxuICAgIGxldCBvcGNvZGUgPSBwcm9ncmFtLm9wY29kZShwYyk7XG4gICAgbGV0IG9wZXJhdGlvblNpemUgPSAodGhpcy5jdXJyZW50T3BTaXplID0gb3Bjb2RlLnNpemUpO1xuICAgIHRoaXMucmVnaXN0ZXJzWyRwY10gKz0gb3BlcmF0aW9uU2l6ZTtcblxuICAgIHJldHVybiBvcGNvZGU7XG4gIH1cblxuICBldmFsdWF0ZU91dGVyKG9wY29kZTogUnVudGltZU9wLCB2bTogVk0pIHtcbiAgICBpZiAoTE9DQUxfREVCVUcpIHtcbiAgICAgIGxldCB7XG4gICAgICAgIGV4dGVybnM6IHsgZGVidWdCZWZvcmUsIGRlYnVnQWZ0ZXIgfSxcbiAgICAgIH0gPSB0aGlzO1xuICAgICAgbGV0IHN0YXRlID0gZGVidWdCZWZvcmUob3Bjb2RlKTtcbiAgICAgIHRoaXMuZXZhbHVhdGVJbm5lcihvcGNvZGUsIHZtKTtcbiAgICAgIGRlYnVnQWZ0ZXIoc3RhdGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmV2YWx1YXRlSW5uZXIob3Bjb2RlLCB2bSk7XG4gICAgfVxuICB9XG5cbiAgZXZhbHVhdGVJbm5lcihvcGNvZGU6IFJ1bnRpbWVPcCwgdm06IFZNKSB7XG4gICAgaWYgKG9wY29kZS5pc01hY2hpbmUpIHtcbiAgICAgIHRoaXMuZXZhbHVhdGVNYWNoaW5lKG9wY29kZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZXZhbHVhdGVTeXNjYWxsKG9wY29kZSwgdm0pO1xuICAgIH1cbiAgfVxuXG4gIGV2YWx1YXRlTWFjaGluZShvcGNvZGU6IFJ1bnRpbWVPcCkge1xuICAgIHN3aXRjaCAob3Bjb2RlLnR5cGUpIHtcbiAgICAgIGNhc2UgTWFjaGluZU9wLlB1c2hGcmFtZTpcbiAgICAgICAgcmV0dXJuIHRoaXMucHVzaEZyYW1lKCk7XG4gICAgICBjYXNlIE1hY2hpbmVPcC5Qb3BGcmFtZTpcbiAgICAgICAgcmV0dXJuIHRoaXMucG9wRnJhbWUoKTtcbiAgICAgIGNhc2UgTWFjaGluZU9wLkludm9rZVN0YXRpYzpcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsbChvcGNvZGUub3AxKTtcbiAgICAgIGNhc2UgTWFjaGluZU9wLkludm9rZVZpcnR1YWw6XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGwodGhpcy5zdGFjay5wb3AoKSk7XG4gICAgICBjYXNlIE1hY2hpbmVPcC5KdW1wOlxuICAgICAgICByZXR1cm4gdGhpcy5nb3RvKG9wY29kZS5vcDEpO1xuICAgICAgY2FzZSBNYWNoaW5lT3AuUmV0dXJuOlxuICAgICAgICByZXR1cm4gdGhpcy5yZXR1cm4oKTtcbiAgICAgIGNhc2UgTWFjaGluZU9wLlJldHVyblRvOlxuICAgICAgICByZXR1cm4gdGhpcy5yZXR1cm5UbyhvcGNvZGUub3AxKTtcbiAgICB9XG4gIH1cblxuICBldmFsdWF0ZVN5c2NhbGwob3Bjb2RlOiBSdW50aW1lT3AsIHZtOiBWTSkge1xuICAgIEFQUEVORF9PUENPREVTLmV2YWx1YXRlKHZtLCBvcGNvZGUsIG9wY29kZS50eXBlKTtcbiAgfVxufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==