Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error Recovery #1462

Closed
wants to merge 51 commits into from
Closed

Error Recovery #1462

wants to merge 51 commits into from

Conversation

wycats
Copy link
Contributor

@wycats wycats commented Oct 24, 2023

This pull request implements error recovery in the VM.

More information to come.

wycats and others added 23 commits October 24, 2023 16:22
Co-authored-by: Godfrey Chan <godfreykfc@gmail.com>
The infrastructure doesn't *do* anything yet, but it exists end-to-end.
These changes will make it easier to iterate on the low-level VM, which
will be necessary in order to add error recovery in appropriate opcodes.
The logging should be significantly more useful, and the metadata is now
extensible to support arbitrary assertions.

I already added stack type assertions to the metadata, but these are
currently still implemented in terms of the old stack change check.

The improvements to metadata already improve the logs (because they
facilitate improved deserialization of immediate values in operands).

The next step is to assert the stack types and also log the (formatted)
stack parameters and return values in the log.

All of this facilitates quicker iteration on the in-progress error
recovery PR.
The devDependencies in package.json have been updated to their latest versions to ensure compatibility and take advantage of any bug fixes or new features. This includes updating various Babel plugins and presets, Rollup, ESLint, Prettier, Puppeteer, QUnit, rimraf, and TypeScript.
Update setup harness and add local types.
… source.fixAll over source.formatDocument

feat(vscode): add custom inline bookmark mapping for @fixme to highlight and style fixme comments in code
feat(vscode): add custom style for @fixme inline bookmarks to make them bold and display in red color
…urate

Handle `null`s in the metadata more reliably, and add nullable arrays to the metadata.
Also tweak code for better conformance to modern TypeScript.
- Make the debug infrastructure work again
- Have the "before" hook return the "after" hook so it can close
  over state it needs.
- Snapshot and formalize internal debug state.
- Properly handle errors in tracing so that log groups are properly
  closed.
- Improve the tracing output:
  - properly visualize the state of the element builder
  - properly visualize the block stack
  - improve visualization of the scope
- Streamline the interaction between the VM and debugger

The next commit uses all of these changes to significantly improve
stack verification and debugging metadata.
…gging

This commit overhauls opcode metadata:

Previously, many opcodes opted out of stack changes because their
changes were too dynamic (e.g. Pop reduces the stack size by a
parameter, which was previously too dynamic to be checked). This commit
enables dynamic stack checks, which are functions that take the runtime
op and debug VM state and dynamically determine the stack change.

This makes it possible to check the stack for every opcode except
`EnterList`, `Iterate`, `PrepareArgs` and `PopFrame` (the reasons for
these exceptions is documented in `opcode-metadata.ts`).

Dynamic checking is now used in:

- Concat (pops N from the stack based on an operand)
- Pop (same)
- BindDynamicScope (binds a number of names from an operand)

A previous commit enabled operand metadata. That infrastructure allows
the trace logger and compilation logger to print friendly versions of
opcodes.

This commit makes the metadata pervasively more accurate, piggy-backing
on the previous commit, which made nullable operands more accurate.

This deserialization process serves as a sort-of verification pass. If
an opcode is expecting an array, for example, and the operand
deserializes to a string, it will fail.

It currently fails confusingly (and not reliably) when the deserializer
fails to deserialize, but this can and should be improved in the future.

Enabling pervasive stack checks caused quite a few tests to fail.

For the most part, getting the tests to pass required improving the
accuracy of the opcode metadata.
Previously, the source of truth for opcodes was an array literal and a
matching interface for that literal. All other types were generated
using TypeScript reflection.

However, the TypeScript reflection was fairly elaborate and slowed down
type feedback when working with the types.

This commit moves the source of truth to bin/opcodes.json and generates:

- @glimmer/interfaces/lib/generated/vm-opcodes.d.ts
- @glimmer/vm/lib/generated/opcodes.ts
- @glimmer/debug/lib/generated/op-list.ts

It adds a lint rule to avoid code casually importing directly from these
generated files, preferring import paths that re-export the generated
types and values.

The schema in `bin/opcodes/opcodes.schema.json` validates
`bin/opcodes.json`.

An npm script (`generate:opcodes`) updates all three files, but can also
be used to update a single file or review the generated files.

The generator script is written in TypeScript and this commit adds
`esyes` (https://github.com/starbeamjs/esyes) to generate the
`bin/opcodes.mts` file. (esyes requires node 21, but that doesn't
affect users of Glimmer, just contributors).
There are better, more ergnomic, and more broadly supported ways to
handle enum-like patterns in TypeScript now.

TL;DR This commit replaces enums with literal types and type unions.
This commit also calls the specified handler asynchronously when an
error occurs.
@@ -20,6 +19,8 @@ export const DebugOpList = [
null,
null,
null,
null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the purpose of these nulls?

op.labels(() => {
expr(op, handler);
op(Op.PushTryFrame, op.target('CATCH'));
// ReplayableIf(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't forget that this is commented out!

@NullVoxPopuli
Copy link
Contributor

I extracted the lint dependency updates to here: #1474

The VM uses the `Stack` class (and friends) to manage its internal
state. This commit adds checkpointing to `Stack` so that the VM can
easily roll back to a point before a try frame began.
There are a few remaining open issues, but this commit gets us really
close to the finish line.
This commit cleans up and tests the behavior of references in the error
state. Documentation for the semantics is forthcoming.
Also improve the labelling infrastructure to be more useful for
debugging tools such as the trace logger.
Improve the overall infrastructure of debug labels, and introduce a
minifier-friendly approach to dev-mode values that captures the notion
of values that should *always* be present in development but never in
production.
This commit makes it possible for a code to reset the error state in a
reference in order to attempt error recovery.

When a reference's error is reset, its tag is invalidated, which will
result in consumers of that reference recomputing its value.
This commit removes gratuitous differences between different modes in an
attempt to clarify how the system works.

It also begins some documentation on how blocks and frames work.
This commit migrates more cases from unwrapReactive to readReactive.

Ideally we'd have explicit tests for each `readReactive` case, but there
are already some blanket error recovery tests and I'm moving forward
with these changes as long as all of the existing tests and blanket
error tests pass.
@NullVoxPopuli
Copy link
Contributor

I'm going to be helping rebase, but:
A note on conflicting changes:

  • dom-change-list is no longer in this repo, it's moved to another repo
  • all the package.json scripts needed to change, due improper-for-ember configuration
  • lint configs had to change due in order to work with CI and turbo
  • various bugfixes in interfaces, reference, and runtime that were needed for ember-source

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's up with this diff?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

– and, in general, now that this is in (from what I understand) a ready for merge/review state, can you back out all these unrelated config/workflow changes into a separate PR and land them first or separately later? Don't want to merge a big experimental new feature (which has a non-zero chance of needed to be reverted later) with a lot of unrelated changes.

Copy link
Contributor

@chancancode chancancode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I'll be able to successfully review this in the current state in the amount of time I had allocated for the task. (To be fair, it was still marked as draft, but I was recently told it's ready.)

Let me know when it is cleaned up with the unrelated changes backed out; especially for the formatting changes, I would strongly prefer to have them landed ahead of time and this rebased on top (which, I think @NullVoxPopuli had already started doing).

NullVoxPopuli added a commit that referenced this pull request Nov 21, 2023
NullVoxPopuli added a commit that referenced this pull request Nov 21, 2023
This was referenced Nov 21, 2023
NullVoxPopuli added a commit that referenced this pull request Nov 21, 2023
NullVoxPopuli added a commit that referenced this pull request Nov 21, 2023
* Copy bin folder from #1462

* Sync from remote

* update lockfile

* Do not typecheck vm-babel-plugins, because doing so provides no value
@NullVoxPopuli
Copy link
Contributor

Closing due to conflicts and #1501 supersedes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants