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
|
package comp
import (
"fmt"
"reflect"
)
// Dump represents the state of a data dump.
type Dump struct {
Values []*DumpValue
}
// DumpValue is a value of a dump state.
type DumpValue struct {
Index int
Name string
Kind int
Type string
Value any
}
// Dump creates a snapshot of the execution state of global variables.
// This method is specifically implemented in the Compiler to minimize the coupling between
// the dump format and other components. By situating the dump logic in the Compiler,
// it relies solely on the program being executed and the indexing algorithm used for ordering variables
// (currently, this is an integer that corresponds to the order of variables in the program).
// This design choice allows the Virtual Machine (VM) to evolve its memory management strategies
// without compromising backward compatibility with dumps generated by previous versions.
func (c *Compiler) Dump() *Dump {
dict := c.symbolsByIndex()
dv := make([]*DumpValue, len(c.Data))
for i, d := range c.Data {
e := dict[i]
dv[i] = &DumpValue{
Index: e.Index,
Name: e.name,
Kind: int(e.Kind),
Type: e.Type.Name,
Value: d.Interface(),
}
}
return &Dump{Values: dv}
}
// ApplyDump sets previously saved dump, restoring the state of global variables.
func (c *Compiler) ApplyDump(d *Dump) error {
dict := c.symbolsByIndex()
for _, dv := range d.Values {
// do all the checks to be sure we are applying the correct values
e, ok := dict[dv.Index]
if !ok {
return fmt.Errorf("entry not found on index %d", dv.Index)
}
if dv.Name != e.name ||
dv.Type != e.Type.Name ||
dv.Kind != int(e.Kind) {
return fmt.Errorf("entry with index %d does not match with provided entry. "+
"dumpValue: %s, %s, %d. memoryValue: %s, %s, %d",
dv.Index,
dv.Name, dv.Type, dv.Kind,
e.name, e.Type, e.Kind)
}
if dv.Index >= len(c.Data) {
return fmt.Errorf("index (%d) bigger than memory (%d)", dv.Index, len(c.Data))
}
if !c.Data[dv.Index].CanSet() {
return fmt.Errorf("value %v cannot be set", dv.Value)
}
c.Data[dv.Index].Set(reflect.ValueOf(dv.Value))
}
return nil
}
|