Website Summary Files Commits Branches @commit @diff @stats
path: root / website / content / slides / 05_vm_intro / _index.md
blob: ab97f4d6ddb802528600e2742ada6b0b66693fce (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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
---
title: "Introduction to Virtual Machines"
date: 2020-11-01T17:45:53+03:00
draft: false
outputs: ["Reveal"]
---

# Virtual Machines - Wikipedia

> In computing, a virtual machine (VM) is an emulation of a computer system.
> Virtual machines are based on computer architectures and provide functionality
> of a physical computer.

---
# Virtual Machines - Wikipedia

- system virtual machines - provide substitute for a real machine
- process virtual machines - allow executing of computer programs in a platform
  independent environment

> We will be looking only at the second type of virtual machines and VM will
> mean that for us.

---
# Virtual Machines

- Implement a computational model
- Just like real machines AKA computers
- run on top of the real machine
- you can have a hardware implementation of VM

---

## Computational model

- Regular Languages
- Context Free Languages
- *Everything that is computable*

---
## Computational model

- Regular Expressions
- Pushdown automata
- Turing machines

---
### Turing machine

- has infinite tape with cells
- each cells can hold one of finite number of values
- head that can read, write and move to the left and right
- finite set of states, one designated as starting state
- finite program that given (state, value) return the new (state, action, value)

---
### Turing machine operation

1. starts with the initial state
2. Read the value at the head position
3. look up (state, value) in the table - if missing *HALT*
4. Set state to *new state*, write *new value* at the head position and move the
   head left or right
5. Go to 2

---
## From theory to practice

- Infinite tapes are expensive
- Not great user experience to interact via checking the cells on the tape

---
Still computers and VMs are an implementations of Turing machines.

The tape is not infinite :/

- less powerful
- we have to reuse the tape

---
### What is inside a machine

1. Processor - implements the machine running algorithm
    - reads, writes to the tape, moves the head and changes the current state
2. Memory - the tape, consists of cells of variable sizes filled with 0 and 1
    - almost always random accessible
3. Program - the state transition function/table
    - resides in the memory - von Neumann architecture
4. Program Counter (PC) - the current state

{{% note %}}

All the fancy output like sound and graphics is writing at dedicated addresses
in memory.

So to writing something on the screen, used to be write the bytes in
0xF000-0xFFFF and the hardware will just blit them on the screen.
Playing a sound - set some address to the frequency of the tone.


{{% /note %}}

---
#### How the machine works?

1. Reads the instruction at PC
2. Decodes the instruction at PC
3. Modifies the memory according to the instruction
4. Moves PC to the next instruction
5. Go to 1

---
### Instructions

- CISC - Complex Instruction Set Computer
    - one instruction can do a lot of operations
- RISC - Reduced Instruction Set Computer
- Register Memory - most operations can use both - registers and memory
  addresses
- Register Register - most operations take place only between registers and
  there are dedicated instructions that allow loading and storing data in memory

---
### Instructions

- x86 - CISC, Register Memory
    - the CPU actually runs microcode that is RISC ...
- ARM - RISC, Register Register

---
### Instructions

- transfer data between registers and memory
- add, substract, multiply, divide values
- boolean operations on values
- change the PC
- call a subroutine

---
### Subroutines

- not required by Turing machines
- but very useful, that are part of every machine

- Stack for storing return addresses (at least)
- Stack Pointer (SP)

---
### "Real" vs Virtual Machine

- the "real" machine is implemented in the hardware
- the operations of the machine are mapped 1:1 to the hardware actions
- these statements used to be true, not any more

{{% note %}}
Out-of-order execution, branch prediction -> meltdown, spectre show that our
"machine" code runs on a virtual machine.
{{% /note %}}

---
## Virtual machines

- Stack based
- Register based

---
### Stack based VM

- all operations work with arguments on the stack
    - operands are popped from the stack
    - the result is pushed on the stack

---

        read // from input to top of stack
        dup
    loop:
        push 1
        sub
        dup
        push 0
        jmpeq end
        swap
        dup -1
        add
        swap
        jmp loop
    end:
        pop
        print // pop result and print

---

- the instructions are smaller and the code is compact
- more code is required

---
### Register based VM

- operations can work with registers

---

        read 0
        move 1, 0
    loop:
        sub 0, 0, #1
        cmp 0, #0
        jmp end
        add 1, 1, 0
        jmp loop
    end:
        print 1

---

- less code
- the instructions have arguments and can be larger

---

#### Typing

VMs can be statically or dynamically typed

- certain registers / memory locations / instructions can work only on certain
  argument types.

---
### From VM to a interpreter

Implementing everything at the VM level would be too hard

- interpreter = VM + runtime
- VM - control logic and computations
- runtime - language features and standard library

---
### Course future

1. Implement a register based VM that works with numbers
2. Implement a runtime
    1. Strings
    2. Objects
    3. Arrays
    4. Functions
    5. Garbage Collector
3. Make JSImpl generate code for the VM

---
## Implementing a VM

- register based
- still needs a stack for argument passing and keeping local variables

---
### Instruction set

- choosing an instruction set is difficult
    - performance
        - speed
        - energy consumption
    - how easy it is to target that instruction set

---

Fixed size instructions vs variable length instructions:

- fixed size is easier to decode, but imposes restrictions and can be wasteful

---
### Instruction set

We'll be doing variable length instructions

> The instruction set is subject to change, so do not start the press (yet!).

---
### Instruction set

Instructions will be between 1 and 25 bytes.

- 6 bits for OpCode - we have up to 64 opcodes
- 2 bits - n - length of the arguments
    - 2^n bytes per agrument
    - up to 3 arguments per instruction

---
### Instruction set

https://docs.google.com/spreadsheets/d/1Q90x60BF-7T0jqPngScsjlaGBXXHRx4tszwCTSRYUrA/edit?usp=sharing

---
### Calling convention

1. push arguments on stack
2. call function
3. callee can access arguments from the stack with registers
    - 0 - count of arguments
    - -1 - first argument
    - -n - n-th argument
4. callee calls `ret reg`, which removes all locals and arguments and leaves
   `reg` on top of the stack
5. caller pops the result from the stack

---
### How a program looks?

    function add_answer(x) {
        return x + 42;
    }

---

    func add
    const 42 // goes to register 2
    add 2, -1, 2
    ret 2

---
### Interpreter loop

1. read the next instruction
2. decode the opcode and arguments
    - move PC to the next instruction
3. execute the operation
4. go to 1

---

    while (1) {
        auto instruction = get_op(PC);
        switch (instruction & 0x3F) {
            case ADD: {
                const auto size = (instruction >> 6);
                const auto arg0 = get_arg(PC, size);
                const auto arg1 = get_arg(PC, size);
                const auto arg2 = get_arg(PC, size);
                m_Stack[arg0] = m_Stack[arg1] + m_Stack[arg2];
            }
            // ...
        }
    }

---

    int get_op(byte*& PC) {
        return *(PC++);
    }
    size_t get_arg(byte*& PC, int size) {
        switch (size) {
            case 0:
                return *(PC++);
            case 1:
                return *(((unsigned short*&)PC)++);
            case 2:
                return *(((unsigned int*&)PC)++);
            case 3:
                return *(((size_t*)PC&)++);
        }
    }

---
# Homework

- implement a brainfuck interpreter
- implement a gcd in spasm

---
# ?