# What changed in 0.14

> Tensor primitives, faster gpu for launches, supervised actors, borrow checks, loop tiling, lambda specialization, stream fusion, WebAssembly packages and parallelization fixes.

Canonical: https://alice-lang.org/documentation/reference/whats-new-0-14/

[Documentation index](https://alice-lang.org/documentation/llms.txt) · [Complete book](https://alice-lang.org/llms-full.txt)

Alice 0.14 adds tensor kernels to the runtime, makes `gpu for` launches much cheaper, turns `Actor` into a
supervised process, and adds compile-time borrow checks. Most existing code compiles unchanged. The behavior changes
to check are listed first. The full list is in the
[changelog](https://github.com/alicelanguage/alice/blob/main/CHANGELOG.md).

## Behavior changes

| Change                                                                                                                                                   | What to do                                                               |
| -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| Passing one mutable value twice to a call that writes through one of the parameters is AL0217 (`copy_into(a, a)`).                                       | Pass a copy (`a.dup`) or a different value.                              |
| A `@[Stack]` value captured by a block, stored in a heap type's field or put in a collection is AL0218. Before, this was a C# error at emit time.        | Pass the fields the block needs.                                         |
| Using a mutable value after sending it through a `Channel` or `Actor` is AL0219.                                                                         | Send `xs.dup`, or rebind the name before using it again.                 |
| Actor messages must be sendable (AL0230), and actor blocks may not capture mutable locals (AL0231).                                                      | Build actor state in `init` with `Actor(S, T)`, or send it as a message. |
| Some loops that 0.13 parallelized now stay serial, because the compiler could not prove them safe (see [parallelization fixes](#parallelization-fixes)). | Nothing. The results were wrong before in these cases.                   |
| Telemetry ships disabled. The CLI never asks, records or sends, and `alice telemetry` only reports that it is disabled.                                  | Nothing.                                                                 |

## Tensor primitives

The runtime has tensor kernels (ADR 0030), callable with `using Alice.Runtime`:

```alice
using Alice.Runtime

w = Array(Float32).new(8)
x = Array(Float32).new(4)
y = Array(Float32).new(2)
Nn.Fill(w, 1)
Nn.Fill(x, 2)
Nn.Gemv(w, x, y, 2, 4)
puts y[0]          # 8.0
Nn.Softmax(y)
puts y[1]          # 0.5
puts Nn.Dot(x, x)  # 16.0
```

There are strided `Tensor<T>` views over 64-byte aligned memory, `BFloat16` and `Half`, int8 and int4 quantized
matrices with a fused dequantize and dot, memory-mapped files, and kernels for GEMV, GEMM, softmax, the norms and the
common activations. No call allocates. See [tensors](https://alice-lang.org/documentation/guides/tensors.md).

## Faster GPU loops

Each `gpu for` is now a grouped kernel with an occupancy-sized group and a grid-stride loop. Reductions do one atomic
add per group instead of one per iteration: a 10M `Int64` sum on an Iris Xe went from 18 ms to 4-6 ms. Arrays the
loop only writes are not uploaded, and arrays it only reads are not copied back. See
[GPU loops](https://alice-lang.org/documentation/guides/gpu.md#how-a-launch-is-sized).

## Supervised actors

`Actor(T)` is a supervised, linkable process, in the style of BEAM (ADR 0028). A crash kills only that actor,
`link` and `on_exit` propagate exits, and `Supervisor.one_for_one` / `one_for_all` restart children with a restart
limit (`max` restarts per window) and support nested trees. `Actor(S, T).new(init, handler)` builds the state inside
the actor. The mailbox is a lock-free queue: 0 bytes per message in steady state, about 6M messages/s on one actor.

## Compiler optimizations

- **Lambda specialization** (ADR 0026). A higher-order function called with a block literal gets a copy whose `yield`
  is a direct call of the block. No delegate or closure is allocated, and the JIT can inline the block (about 2.3x on
  a benchmark that calls many higher-order functions). `ALICE_NO_SPECIALIZE=1` turns it off.
- **Loop interchange and tiling** (ADR 0025). 2-3 deep counted nests over flat arrays are reordered so the innermost
  loop has stride-1 access (`i-j-k` matmul becomes `i-k-j`) and tiled when every dependence allows it. The new order
  runs behind a once-per-call bounds and aliasing guard; results are bit-identical. `ALICE_TILE=n` sets the tile size.
- **Stream fusion** (ADR 0029). `xs.map{}.select{}.take(n).sum` is one loop with no intermediate arrays. `to_a` and
  `map` write an exact-size array. Stages with side effects keep the order they were written in.

## WebAssembly packages

`kind = "wasm"` in `alice.toml` builds a static site, and `@[JSExport]` / `@[JSImport]` call between Alice and
JavaScript. See [WebAssembly](https://alice-lang.org/documentation/guides/webassembly.md).

## Parallelization fixes

- `for` loops that write one array with two index shapes (`a[i]` and `a[i * w + j]`) stay serial.
- A call to an overridable method is pure only when every override is.
- A loop that assigns a local declared in a branch, and reads it later, stays serial.
- AL0202 catches more races: `spawn { bump }` on a method that writes fields, and index writes keyed by `par_each` values.
- `Par.Sum` splits the index range in halves, so it gives the same float result on every run.

## Continue reading

- Previous: [MSBuild integration](https://alice-lang.org/documentation/tools/sdk.md)
- Next: [What changed in 0.13](https://alice-lang.org/documentation/reference/whats-new-0-13.md)
