@@ -100,6 +100,7 @@ const vis = {
100
100
},
101
101
printErr: function (text: any) {
102
102
stdioEl.value += text + '\n';
103
+ console.error(text);
103
104
},
104
105
} as any; /* TODO: emscripten types */
105
106
@@ -542,6 +543,15 @@ const vis = {
542
543
self['__destroy__']();
543
544
}
544
545
546
+ function withTiming(f: Function, start?: PerformanceMeasure) {
547
+ start = start ?? window.performance.mark('talvos');
548
+
549
+ return (async () => f())().finally(() => {
550
+ const call = window.performance.measure(start.name, start.name);
551
+ rootEl.querySelector<HTMLOutputElement>('output.timing')!.value = `done in ${call.duration}ms`;
552
+ });
553
+ }
554
+
545
555
// TODO refactor into `withTiming` / `withExec` ?
546
556
function captureOutput(f: Function, start?: PerformanceMeasure) {
547
557
stdioEl.value = '';
@@ -642,105 +652,124 @@ const vis = {
642
652
const text = (rootEl.querySelector('.module') as { value: string } | null)!.value;
643
653
644
654
const start = window.performance.mark('debug', { detail: { text } });
645
- const session = new (await Session)(text);
646
- // session.params.EntryName = 'vecadd';
647
- session.params.EntryName = entryEl.selectedOptions.item(0)?.value ?? 'main';
648
-
649
- const debugCtrl = rootEl.querySelector<HTMLElement>('.debugger')!;
655
+ withTiming(async () => {
656
+ const session = new (await Session)(text);
657
+ // session.params.EntryName = 'vecadd';
658
+ session.params.EntryName = entryEl.selectedOptions.item(0)?.value ?? 'main';
650
659
651
- function finish() {
652
- debugCtrl.hidden = true;
653
- // remove references to 1) allow the session to be GC'd, and 2) safety of the dangling pointer
654
- debugCtrl.querySelectorAll<HTMLButtonElement>('button').forEach((el) => (el.onclick = null));
655
- rootEl
656
- .querySelectorAll<HTMLButtonElement>('button.exec,textarea')
657
- .forEach((el) => el.removeAttribute('disabled'));
658
- window.dispatchEvent(ev_finish);
660
+ const debugCtrl = rootEl.querySelector<HTMLElement>('.debugger')!;
659
661
660
- destroy(session);
662
+ function finish() {
663
+ withTiming(() => {
664
+ debugCtrl.hidden = true;
665
+ // remove references to 1) allow the session to be GC'd, and 2) safety of the dangling pointer
666
+ debugCtrl.querySelectorAll<HTMLButtonElement>('button').forEach((el) => (el.onclick = null));
667
+ rootEl
668
+ .querySelectorAll<HTMLButtonElement>('button.exec,textarea')
669
+ .forEach((el) => el.removeAttribute('disabled'));
670
+ window.dispatchEvent(ev_finish);
661
671
662
- const call = window.performance.measure(start.name, start.name);
663
- rootEl.querySelector<HTMLOutputElement>('output.timing')!.value = `done in ${call.duration}ms`;
664
- }
665
-
666
- try {
667
- session.start();
668
- window.dispatchEvent(ev_start);
669
-
670
- stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
671
- session.printContext();
672
- } catch (e) {
673
- finish();
674
- throw e;
675
- }
672
+ destroy(session);
673
+ }, window.performance.mark('finish'));
676
674
677
- const FINISHED = 1; // TODO sync with talvos::PipelineExecutor::StepResult
675
+ const call = window.performance.measure(start.name, start.name);
676
+ // we need to be scheduled after the (async) bits in `withTiming`
677
+ // this is good and will in no way be broken by anything I do later
678
+ setTimeout(
679
+ () =>
680
+ (rootEl.querySelector<HTMLOutputElement>('output.timing')!.value +=
681
+ ` (session lifetime: ${call.duration}ms)`),
682
+ 0
683
+ );
684
+ }
678
685
679
- debugCtrl.querySelector<HTMLButtonElement>('button.tick')!.onclick = async function () {
680
- stdioEl.value = '';
681
- errorEl.value = '';
682
686
try {
683
- const last = await session.tick();
684
- window.dispatchEvent(ev_tick);
685
- if (last == FINISHED) {
686
- finish();
687
- }
687
+ session.start();
688
+ window.dispatchEvent(ev_start);
688
689
689
- // TODO remove (confusing)
690
690
stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
691
691
session.printContext();
692
692
} catch (e) {
693
693
finish();
694
694
throw e;
695
695
}
696
- };
697
- debugCtrl.querySelector<HTMLButtonElement>('button.step')!.onclick = async function () {
698
- stdioEl.value = '';
699
- errorEl.value = '';
700
- try {
701
- const last = await session.step();
702
- window.dispatchEvent(ev_step);
703
- if (last == FINISHED) {
704
- finish();
705
- }
706
696
707
- stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
708
- session.printContext();
709
- } catch (e) {
710
- finish();
711
- throw e;
712
- }
713
- };
714
- debugCtrl.querySelector<HTMLButtonElement>('button.switch')!.onclick = function () {
715
- const input = prompt('Usage: switch: X [Y [Z]]', 'X [Y [Z]]'); // %15 is `void` in vecadd
716
- if (input == null) {
717
- return;
718
- }
719
- const args = input.split(/\s+/);
720
- session.switch(args);
721
- };
722
- debugCtrl.querySelector<HTMLButtonElement>('button.print')!.onclick = function () {
723
- const input = prompt('Usage: print: %<id>', '%15'); // %15 is `void` in vecadd
724
- if (input == null) {
725
- return;
726
- }
727
- const args = input.split(/\s+/);
728
- session.print(args);
729
- };
697
+ const FINISHED = 1; // TODO sync with talvos::PipelineExecutor::StepResult
730
698
731
- debugCtrl.querySelector<HTMLButtonElement>('button.stop ')!.onclick = finish;
732
- debugCtrl.querySelector<HTMLButtonElement>('button.continue')!.onclick = function () {
733
- stdioEl .value = '';
734
- errorEl.value = '' ;
735
- try {
736
- session.continue();
737
- } finally {
738
- // TODO breakpoints
739
- finish();
740
- }
741
- };
699
+ debugCtrl.querySelector<HTMLButtonElement>('button.tick ')!.onclick = async function () {
700
+ stdioEl.value = '';
701
+ errorEl .value = '';
702
+ const start = window.performance.mark('tick', { detail: {} }) ;
703
+ withTiming(async () => {
704
+ try {
705
+ const last = await session.tick();
706
+ window.dispatchEvent(ev_tick);
707
+ if (last == FINISHED) {
708
+ finish();
709
+ }
742
710
743
- debugCtrl.hidden = false;
711
+ // TODO remove (confusing)
712
+ stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
713
+ session.printContext();
714
+ } catch (e) {
715
+ finish();
716
+ throw e;
717
+ }
718
+ }, start);
719
+ };
720
+ debugCtrl.querySelector<HTMLButtonElement>('button.step')!.onclick = async function () {
721
+ stdioEl.value = '';
722
+ errorEl.value = '';
723
+ const start = window.performance.mark('step', { detail: {} });
724
+ withTiming(async () => {
725
+ try {
726
+ const last = await session.step();
727
+ window.dispatchEvent(ev_step);
728
+ if (last == FINISHED) {
729
+ finish();
730
+ }
731
+
732
+ stdioEl.value = `@ {${[...session.lastId]}} (logical)\n`;
733
+ session.printContext();
734
+ } catch (e) {
735
+ finish();
736
+ throw e;
737
+ }
738
+ }, start);
739
+ };
740
+ debugCtrl.querySelector<HTMLButtonElement>('button.switch')!.onclick = function () {
741
+ const input = prompt('Usage: switch: X [Y [Z]]', 'X [Y [Z]]'); // %15 is `void` in vecadd
742
+ if (input == null) {
743
+ return;
744
+ }
745
+ const args = input.split(/\s+/);
746
+ session.switch(args);
747
+ };
748
+ debugCtrl.querySelector<HTMLButtonElement>('button.print')!.onclick = function () {
749
+ const input = prompt('Usage: print: %<id>', '%15'); // %15 is `void` in vecadd
750
+ if (input == null) {
751
+ return;
752
+ }
753
+ const args = input.split(/\s+/);
754
+ session.print(args);
755
+ };
756
+
757
+ debugCtrl.querySelector<HTMLButtonElement>('button.stop')!.onclick = finish;
758
+ debugCtrl.querySelector<HTMLButtonElement>('button.continue')!.onclick = function () {
759
+ stdioEl.value = '';
760
+ errorEl.value = '';
761
+ withTiming(() => {
762
+ try {
763
+ session.continue();
764
+ } finally {
765
+ // TODO breakpoints
766
+ finish();
767
+ }
768
+ });
769
+ };
770
+
771
+ debugCtrl.hidden = false;
772
+ }, start);
744
773
};
745
774
746
775
const entryEl = rootEl.querySelector<HTMLSelectElement>('select[name="entry"]')!;
0 commit comments