Fix #1134: asInstanceOf is undefined behavior by default

`asInstanceOf`s, including unboxing operations, are too expensive. This PR introduces configurable `Semantics` for the Scala.js linker. These semantics include the concept of `CheckedBehaviors`, which describe how we implement some exceptional behaviors, for now only `asInstanceOf`. These exceptional behaviors have well-defined semantics on the JVM (throw a particular kind of exception) even though they should be considered programmer errors. When compiling to JS, we don't have support from the VM to eliminate the unnecessary checks, which makes these error cases too expensive to check.

Each `CheckedBehavior` has 3 possible values:
* `Compliant`: perform the checks and throw the exceptions as specified on the JVM.
* `Fatal`: perform the checks, but throw a different kind of exception, `UndefinedBehaviorError`, which is a `java.lang.Error with s.u.control.ControlThrowable`. It is therefore not caught by `NonFatal` clauses.
* `Unchecked`: do not perform the checks.

By default, the `asInstanceOf` checks are in `Fatal` mode. In `fullOpt`, every behavior in `Fatal` mode is automatically mapped to the `Unchecked` mode. In this mode, if the program does something that would have been detected in `Fatal` mode, the whole program enters undefined behavior, and anything can happen (of course we're still under the JS VM's control, so the computer won't explode). If an application needs a particular kind of behavior to be fully compliant (say because it catches `ClassCastException`s -- bad!), an sbt setting allows to do so. Compliant behaviors are kept compliant in `fullOpt`.

```scala
ScalaJSKeys.scalaJSSemantics ~= {
  _.transformCheckedBehaviors(_.withAsInstanceOfs(
      scala.scalajs.tools.sem.CheckedBehaviors.Compliant))
}
```

The idea of the `Fatal` mode is that during development (including `fastOptStage::test`), portions of code that would enter undefined behavior are detected with a severe `Error` that will be reported, and is tractable and debuggable. For production, all `Fatal` behaviors are turned into `Unchecked` for maximum performance.

This is similar to how Dart does, for example: a development mode with more checks, and a production mode where they are erased for performance.

The same mechanism of `CheckedBehaviors` can be used for other exceptional behaviors that, so far, we have always treated as if in `Unchecked` mode:
* `ArithmeticException`, e.g., integer division by 0
* `ArrayIndexOutOfBoundsException` and `StringIndexOutOfBoundsException`
* `ArrayStoreException`

The global concept of `Semantics` can be used to configure other semantic tweaks, for example, whether `Float`s should be enforced as 32-bit floats or not.
On second thought, we maybe should do this for all the cases we excluded but nevertheless should test (n.b. string representations)... So if you want to defer this to another issue, I'm fine with that, too.