Skip to content

Commit f21fa0d

Browse files
authored
feat(doc): Update engine architecture documentation (#970)
1 parent a5947e7 commit f21fa0d

13 files changed

Lines changed: 563 additions & 495 deletions

File tree

ARCHITECTURE.md

Lines changed: 24 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,27 @@ The architecture of Nova engine is built around data-oriented design. This means
44
that most "data" like things are found in the heap in a vector with like-minded
55
individuals.
66

7-
## Concurrency
8-
9-
Currently the heap is not thread-safe at all but the plan is to make it
10-
thread-safe enough for concurrent marking to become possible in the future. To
11-
this end, here's how I (@aapoalas) envision the engine to look like in the
12-
future:
13-
14-
```rs
15-
struct Agent<'agent, 'generation>(Box<AgentInner<'agent>>, AgentGuard<'generation>);
16-
```
17-
18-
The `Agent` struct here is just a RAII wrapper around the inner Heap-allocated
19-
Agent data. The first important thing is the `'agent` lifetime: This is a brand.
20-
It is valid for as long as the Nova engine instance lives, and its only purpose
21-
is to make sure that (type-wise) uses cannot mistakenly or otherwise mix and
22-
match Values from different engine instances.
23-
24-
The second lifetime, `'generation`, is the garbage collection generation. Here
25-
what I want to achieve is a separation between "gc" and "nogc" scopes. But
26-
before we dive into that, here's what I imagine a `Value` looking like:
27-
28-
```rs
29-
enum Value<'generation> {
30-
Undefined,
31-
String(StringIndex<'generation>>),
32-
SmallString(SmallString),
33-
// ...
34-
}
35-
```
36-
37-
The `Value` enum carries the `'generation` lifetime: As long as we can guarantee
38-
that no garbage collection happens, we can safely keep `Value<'gen>` on the
39-
stack or even temporarily on the heap.
40-
41-
If we call a method that may trigger GC, then all `Value<'gen>` items are
42-
invalidated. If we want to keep values alive through eg. JavaScript function
43-
calls, we must use:
44-
45-
```rs
46-
struct ShadowStackValue<'agent>(u32, PhantomPinned);
47-
```
48-
49-
This just moves the `Value` onto an Agent-controlled "shadow stack" that the
50-
`u32` points into. Due to the `PhantomPinned` the shadow stack is mostly just
51-
push-pop as any stack should be, and thus relatively quick. But it is also on
52-
the heap and thus garbage collection can update any references on the shadow
53-
stack.
54-
55-
Note that this is essentially equivalent to:
56-
57-
```rs
58-
struct GlobalValue<'agent>(u32);
59-
```
60-
61-
but "global values" are not push-pop, likely will have generational indexes,
62-
possibly will have reference counting and so on and so forth.
7+
## ECMAScript implementation
8+
9+
Nova code aims to conform fairly strictly to the
10+
[ECMAScript specification](https://tc39.es/ecma262/) in terms of both code
11+
layout and structure.
12+
13+
For details on the ECMAScript implementation, see the
14+
[ecmascript/README.md](./nova_vm/src/ecmascript/README.md).
15+
16+
## Engine implementation
17+
18+
Nova's VM is a stack-based bytecode interpreter.
19+
20+
For details on the engine, see the
21+
[engine/README.md](./nova_vm/src/engine/README.md).
22+
23+
## Heap implementation
24+
25+
Nova's heap is made up of a mix of normal Rust `Vec`s and custom `SoAVec`
26+
structs that implement a "Struct of Arrays" data structure with an API
27+
equivalent to normal `Vec`s, all referenced by-index.
28+
29+
For details on the heap architecture, see the
30+
[heap/README.md](./nova_vm/src/heap/README.md).

0 commit comments

Comments
 (0)