-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoptimization.go
More file actions
102 lines (89 loc) · 2.03 KB
/
optimization.go
File metadata and controls
102 lines (89 loc) · 2.03 KB
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
package mist
// +-------------------+
// | AST optimizations |
// +-------------------+
// Flags to turn off optimizations.
const (
OffoptArithmetic = 1 << iota
OffoptIf = 1 << iota
)
// TODO: If an arithmetic expression is made up of constants, replace
// it with the result instead.
func optimizeArithmetic(node Node) Node {
return node
}
// If the condition of an (if) expression is constant, replace the
// whole (if) expression with the corresponding branch.
func optimizeIf(node Node) Node {
if node.Type != NodeList || node.NumChildren() < 1 {
return node
}
if !node.Children[0].IsThisSymbol("if") {
ans := NewNodeList(node.Origin)
for i := range node.Children {
ans.AddChild(optimizeIf(node.Children[i]))
}
return ans
}
// (if cond yes no)
// 0 1 2 3
if node.Children[1].IsT() {
return node.Children[2]
} else if node.Children[1].IsNil() {
return node.Children[3]
}
return node
}
func OptimizeAST(node Node, offs uint32) Node {
type t func(node Node) Node
fns := []t{
optimizeArithmetic,
optimizeIf,
}
for i, fn := range fns {
bit := uint32(1) << i
if offs&bit == 0 {
node = fn(node)
}
}
return node
}
// +------------------------+
// | Bytecode optimizations |
// +------------------------+
// optimizePushPop deletes sequences of the following form:
//
// PUSH[1-16]
// DATA
// POP
func optimizePushPop(segments []Segment) []Segment {
marked := make([]int, 0, 16)
n := len(segments) - 2
for i := 0; i < n; i++ {
if segments[i].isPush() &&
segments[i+1].isData() &&
segments[i+2].isPop() {
//
marked = append(marked, i)
i += 2
}
}
optimized := make([]Segment, len(segments))
copy(optimized, segments)
for i := len(marked) - 1; i >= 0; i-- {
start := marked[i]
end := start + 3
optimized = append(optimized[:start], optimized[end:]...)
}
return optimized
}
func OptimizeBytecode(segments []Segment) []Segment {
type t func(segments []Segment) []Segment
fns := []t{
optimizePushPop,
}
for _, fn := range fns {
segments = fn(segments)
}
return segments
}