-
Notifications
You must be signed in to change notification settings - Fork 0
/
frame.cpp
149 lines (130 loc) · 4.17 KB
/
frame.cpp
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
#include "frame.h"
#include "gc/gc.h"
#include <algorithm>
using namespace std;
// instruction helpers
int Frame::numInstructions() {
return func->instructions.size();
}
BcInstruction& Frame::getCurrInstruction() {
return func->instructions[instructionIndex];
}
void Frame::checkLegalInstruction() {
if (instructionIndex < 0 || instructionIndex >= numInstructions()) {
throw RuntimeException("instruction " + to_string(instructionIndex) + " out of bounds");
}
}
// function value helpers
tagptr_t Frame::getConstantByIndex(int index) {
if (index < 0 || index >= func->constants_.size()) {
throw RuntimeException("constant " + to_string(index) + " out of bounds");
}
return func->constants_[index];
}
Function* Frame::getFunctionByIndex(int index) {
if (index < 0 || index >= func->functions_.size()) {
throw RuntimeException("function " + to_string(index) + " out of bounds");
}
return func->functions_[index];
}
string Frame::getLocalByIndex(int index) {
if (index < 0 || index >= func->local_vars_.size()) {
throw RuntimeException("var " + to_string(index) + " out of bounds");
}
return func->local_vars_[index];
}
string Frame::getNameByIndex(int index) {
if (index < 0 || index >= func->names_.size()) {
throw RuntimeException("name " + to_string(index) + " out of bounds");
}
return func->names_[index];
}
string Frame::getRefByIndex(int index) {
if (index < 0 || index >= (func->local_reference_vars_.size() + func->free_vars_.size())) {
throw RuntimeException("ref var " + to_string(index) + " out of bounds");
}
if (index < func->local_reference_vars_.size()) {
return func->local_reference_vars_[index];
}
return func->free_vars_[index - func->local_reference_vars_.size()];
}
// var map helpers
tagptr_t Frame::getLocalVar(string name) {
if (vars.count(name) != 0) {
tagptr_t result = vars[name]->ptr;
if (result == NULL_PTR) {
throw UninitializedVariableException(name + " is not defined");
}
return result;
}
throw UninitializedVariableException(name + " is not defined");
}
ValWrapper* Frame::getRefVar(string name) {
if (vars.count(name) != 0) {
return vars[name];
}
throw RuntimeException(name + " has not been created in its frame's vars");
}
void Frame::setLocalVar(string name, tagptr_t val) {
if (vars.count(name) == 0) {
vars[name] = collector->allocate<ValWrapper>(val);
collector->increment(sizeof(name) + name.size() + sizeof(val));
} else {
vars[name]->ptr = val;
}
}
void Frame::setRefVar(string name, tagptr_t val) {
if (vars.count(name) == 0) {
collector->increment(sizeof(name) + name.size() + sizeof(val));
}
ValWrapper* v = cast_val<ValWrapper>(val);
vars[name] = v;
}
// operand stack helpers
void Frame::opStackPush(tagptr_t val) {
collector->increment(sizeof(val));
opStack.push_back(val);
}
tagptr_t Frame::opStackPeek() {
if (opStack.empty()) {
throw InsufficientStackException("peek at empty stack");
}
return opStack.back();
}
tagptr_t Frame::opStackPop() {
if (opStack.empty()) {
throw InsufficientStackException("pop from empty stack");
}
tagptr_t top = opStack.back();
int size = sizeof(top);
collector->increment(-size);
opStack.pop_back();
return top;
}
void Frame::follow(CollectedHeap& heap) {
// follow the function it contains
// As well as all the stuff on the op stack?
heap.markSuccessors(func);
for (tagptr_t v : opStack) {
if (!is_tagged(v)) {
heap.markSuccessors(get_collectable(v));
}
}
for (string arg : func->local_vars_) {
if (vars.count(arg) != 0) {
Collectable* localVar = vars[arg];
heap.markSuccessors(localVar); }
}
for (string arg : func->local_reference_vars_) {
if (vars.count(arg) != 0) {
Collectable* localRef = vars[arg];
heap.markSuccessors(localRef);
}
}
}
size_t Frame::getSize() {
size_t overhead = sizeof(Frame);
size_t stackSize = getStackSize(opStack);
size_t varsSize = getMapSize(vars);
return overhead + stackSize + varsSize;
}