aboutsummaryrefslogtreecommitdiff
path: root/docs/docs/internals/backend.md
blob: e1fd20da226f0274420c6935f3e0f2559cd59e1e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
---
layout: doc-page
title: "Backend Internals"
---

The code for the backend is split up by functionality and assembled in the
object `GenBCode`.

```none
object GenBCode    --- [defines] -->        PlainClassBuilder       GenBCode also defines class BCodePhase, the compiler phase
     |                                              |
 [extends]                                      [extends]
     |                                              |
BCodeSyncAndTry    ---------------->        SyncAndTryBuilder
     |                                              |
BCodeBodyBuilder   ---------------->        PlainBodyBuilder
     |                                              |
BCodeSkelBuilder   ---------------->        PlainSkelBuilder
     |                                       /      |       \
 BCodeHelpers      ---------------->  BCClassGen BCAnnotGen ...  (more components)
     |      \       \
     |       \       \------------->  helper methods
     |        \       \------------>  JMirrorBuilder, JBeanInfoBuilder (uses some components, e.g. BCInnerClassGen)
     |         \
     |   BytecodeWriters  --------->        methods and classes to write byte code files
     |
 BCodeTypes        ---------------->        maps and fields for common BTypes, class Tracked, methods to collect information on classes, tests for BTypes (conforms), ...
     |
BCodeIdiomatic     ---------------->        utilities for code generation, e.g. genPrimitiveArithmetic
     |
  BCodeGlue        ---------------->        BType class, predefined BTypes
```

### Data Flow ###
Compiler creates a `BCodePhase`, calls `runOn(compilationUnits)`.

* initializes fields of `GenBCode` defined in `BCodeTypes` (BType maps,
  common BTypes like `StringReference`)
* initialize `primitives` map defined in `scalaPrimitives` (maps primitive
  members, like `int.+`, to bytecode instructions)
* creates `BytecodeWriter`, `JMirrorBuilder` and `JBeanInfoBuilder` instances
  (on each compiler run)
* `buildAndSendToDisk(units)`: uses work queues, see below.
  - `BCodePhase.addToQ1` adds class trees to `q1`
  - `Worker1.visit` creates ASM `ClassNodes`, adds to `q2`. It creates one
    `PlainClassBuilder` for each compilation unit.
  - `Worker2.addToQ3` adds byte arrays (one for each class) to `q3`
  - `BCodePhase.drainQ3` writes byte arrays to disk


### Architecture ###
The architecture of `GenBCode` is the same as in Scalac. It can be partitioned
into weakly coupled components (called "subsystems" below):


#### (a) The queue subsystem ####
Queues mediate between processors, queues don't know what each processor does.

The first queue contains AST trees for compilation units, the second queue
contains ASM ClassNodes, and finally the third queue contains byte arrays,
ready for serialization to disk.

Currently the queue subsystem is all sequential, but as can be seen in
http://magarciaepfl.github.io/scala/ the above design enables overlapping (a.1)
building of `ClassNodes`, (a.2) intra-method optimizations, and (a.3)
serialization to disk.

This subsystem is described in detail in `GenBCode.scala`

#### (b) Bytecode-level types, BType ####
The previous bytecode emitter goes to great lengths to reason about
bytecode-level types in terms of Symbols.

`GenBCode` uses `BType` as a more direct representation. A `BType` is immutable, and
a value class (once the rest of GenBCode is merged from
http://magarciaepfl.github.io/scala/ ).

Whether value class or not, its API is the same. That API doesn't reach into
the type checker. Instead, each method on a `BType` answers a question that can
be answered based on the `BType` itself. Sounds too simple to be good? It's a
good building block, that's what it is.

The internal representation of a `BType` is based on what the JVM uses: internal
names (e.g. `Ljava/lang/String;` ) and method descriptors; as defined in the JVM
spec (that's why they aren't documented in `GenBCode`, just read the [JVM 8 spec](https://docs.oracle.com/javase/specs/jvms/se8/html/)).

All things `BType` can be found in `BCodeGlue.scala`

#### (c) Utilities offering a more "high-level" API to bytecode emission ####
Bytecode can be emitted one opcode at a time, but there are recurring patterns
that call for a simpler API.

For example, when emitting a load-constant, a dedicated instruction exists for
emitting load-zero. Similarly, emitting a switch can be done according to one
of two strategies.

All these utilities are encapsulated in file `BCodeIdiomatic.scala`. They know
nothing about the type checker (because, just between us, they don't need to).

#### (d) Mapping between type-checker types and BTypes ####
So that (c) can remain oblivious to what AST trees contain, some bookkeepers
are needed:

  - Tracked: for a bytecode class (BType), its superclass, directly declared
    interfaces, and inner classes.

To understand how it's built, see:

```scala
final def exemplar(csym0: Symbol): Tracked = { ... }
```

Details in `BCodeTypes.scala`

#### (e) More "high-level" utilities for bytecode emission ####
In the spirit of `BCodeIdiomatic`, utilities are added in `BCodeHelpers` for
emitting:

- bean info class
- mirror class and their forwarders
- android-specific creator classes
- annotations


#### (f) Building an ASM ClassNode given an AST TypeDef ####
It's done by `PlainClassBuilder`(see `GenBCode.scala`).