Skip to content

Conversation

flaviut
Copy link
Contributor

@flaviut flaviut commented May 26, 2014

No description provided.

Araq added a commit that referenced this pull request May 28, 2014
Fix 1226 and document associated methods
@Araq Araq merged commit 7ab2bc3 into nim-lang:devel May 28, 2014
@flaviut flaviut deleted the fix1226 branch May 29, 2014 00:41
@flaviut flaviut restored the fix1226 branch May 31, 2014 18:18
@flaviut flaviut deleted the fix1226 branch May 31, 2014 19:01
Clyybber pushed a commit to Clyybber/Nim that referenced this pull request Mar 13, 2024
## Summary

* use the goto-using CGIR for JavaScript code generation
* as a side-effect, multiple bugs with tracking of the current
  exception are fixed 
* exceptions thrown from `asm` or `.emit` code cannot be expected to be
  caught anymore (this was already undefined behaviour)

## Details

The CGIR for a body is first passed to the new `jsflow` module, where
the shape of the necessary JavaScript is computed, with the focus on
the control-flow constructs (`if`, `switch`, `try`, etc.). Constructs
are translated as follows:
* `cnkGotoStmt` and `cnkJoinStmt` are translated to `break` and labeled
  blocks (JavaScript doesn't support goto directly)
* `cnkCaseStmt` dispatchers are translated to `switch`/`case`
  statements
* `cnkFinally` and `cnkExcept` are translated to `try`/`finally` and
  `try`/`catch`, respectively

It's first computed which statements `try`s and labeled blocks *must*
enclose. Afterwards, their starts are reordered such that valid
JavaScript is formed.

Since `finally` and `catch` clauses can then intercept `break`s or
`throw`s that they shouldn't, `finally` and `catch` clauses are guarded
by a boolean flag. Immediately before an explicit (`break` and `throw`)
or implicit (procedure call) jump that would enter a clause it
shouldn't, the boolean locals for the problematic clauses are set to
false. Upon exit of a disabled clause, the local is set back to true.

#### Case Statements

Direct translation of `cnkCaseStmt`s into `switch`/`case` statement
where each branch is a `break` would result in very deep block nesting
for `case` statements with many branches. The resulting JavaScript code
can cause the V8 JavaScript engine to fail/crash when compiling the
code!

Therefore, the jump targets need to be inlined whenever possible.
`jsflow` computes the code regions eligible for inlining, and `jsgen`
handles the actual inlining.

#### Current Exception Tracking

When control-flow leaves an `except` handler, the `prevJSError` global
(whose content is returned by `getCurrentException`) needs to be reset
to the exception caught by the enclosing handler, something that was
previously missing for the most part.

The exception is restored:
* at the end of a block when the block is broken out of from within a
  `catch`
* at the start of a `finally` clause intercepting a `break` from within
  a `catch`
* at the start of a `finally` clause when it's entered due to an
  exception

If there's no enclosing `catch` within a procedure when the current
exception has to be restored, the value of `lastJSError` is captured at
procedure entry. Tracking of the current exception still doesn't
include in-flight exceptions, so `tfinally6.nim` still fails.

#### Unhandled Exception Reporting

Instead of incrementing, at run-time, a global counter (`excHandler`)
before entering a `try` and decrementing it again on exit, and then
reporting unhandled exceptions when throwing, the module-init
procedures (i.e., top-level code) are wrapped in a `try`/`catch` that
reports the escaping exceptions.

This is simpler to implement and should also have less run-time
overhead.

#### Throwing with `asm`

`asm` and `emit` statements are considered not to raise, and thus they
don't prevent `except` and `finally` sections from being eliminated by
unreachable code elimination.

The `tnativeexc` test is updated to not rely on undefined behaviour.

### Unreachable Code Elimination

Labels that mark the exit of case statements are now eliminated too, if
structured control-flow doesn't leave the case statement (i.e., each
branch ends in a noreturn-like statement).

---------

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
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.

2 participants