-
Notifications
You must be signed in to change notification settings - Fork 2
/
slots.c
282 lines (231 loc) · 7.64 KB
/
slots.c
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
// slots.c
#include <stdio.h>
#include <stdlib.h>
#include "slots.h"
#include "vm.h"
#include "alloc.h"
#include "debug.h"
const uint16_t TAG_DOUBLE_MAX = 0xFFF8;
const uint16_t TAG_DOUBLE_MIN = 0x0007;
const uint16_t TAG_POINTER_LO = 0x0000;
const uint16_t TAG_POINTER_HI = 0xFFFF;
const uint16_t TAG_SMALL_INTEGER = 0xFFFE;
const uint16_t TAG_BOOL = 0xFFFD;
const uint16_t TAG_TYPE = 0xFFFC;
const uint16_t TAG_FNEW = 0xFFFB;
const uint16_t TAG_BUILTIN = 0xFFFA;
void slots_init(Slots *slots, mps_arena_t arena) {
// initialize size and capacity
slots->size = 0;
slots->capacity = SLOTS_INITIAL_CAPACITY;
slots->arena = arena;
slots->data = malloc(sizeof(uint64_t) * slots->capacity);
mps_root_t root_o;
mps_res_t res = mps_root_create_table_masked(&root_o,
arena,
mps_rank_exact(),
(mps_rm_t)0,
(mps_addr_t *)slots->data,
slots->capacity,
(mps_word_t)TAG_MASK);
slots->root_o = root_o;
if (res != MPS_RES_OK) printf("Couldn't create slots roots");
// allocate memory for slots->data
}
void slots_append(Slots *slots, uint64_t value) {
slots_double_capacity_if_full(slots);
slots->data[slots->size++] = value;
}
uint64_t slots_get(Slots *slots, uint32_t index) {
if(slots->capacity != SLOTS_INITIAL_CAPACITY && ((uint32_t)(slots->capacity / 2) * 0.6) >= slots->size) {
slots_half_capacity(slots);
}
if (index >= slots->size || index < 0) {
printf("Index %d out of bounds for slots of size %d\n", index, slots->size);
exit(1);
}
return slots->data[index];
}
void slots_set(Slots *slots, uint32_t index, uint64_t value) {
while (index >= slots->size) {
slots_append(slots, 0);
}
slots->data[index] = value;
}
static mps_addr_t obj_isfwd(mps_addr_t addr) {
struct obj_stub *obj = addr;
if (obj->type == OBJ_MPS_TYPE_FORWARD) {
return obj->ref[0];
}
return NULL;
}
// Only call if you have checked that the halfed
// slot capacity will fit in the new slot
void slots_half_capacity(Slots *slots) {
slots->capacity = (uint32_t) slots->capacity / 2;
uint64_t* data = malloc(sizeof(uint64_t) * slots->capacity);
mps_root_t root_o_old;
root_o_old = slots->root_o;
mps_root_t root_o_new;
mps_res_t res = mps_root_create_table_masked(&root_o_new,
slots->arena,
mps_rank_exact(),
(mps_rm_t)0,
(mps_addr_t *)data,
slots->capacity,
(mps_word_t)TAG_MASK);
if (res != MPS_RES_OK) printf("Couldn't create root for increased slots\n");
for(int i = 0; i != slots->size; i++) {
data[i] = slots->data[i];
}
free(slots->data);
slots->root_o = root_o_new;
slots->data = data;
mps_root_destroy(root_o_old);
}
void slots_double_capacity_if_full(Slots *slots) {
if (slots->size >= slots->capacity) {
/* Double the size of the Stack */
slots->capacity *= 2;
uint64_t* data = malloc(sizeof(uint64_t) * slots->capacity);
mps_root_t root_o_old;
root_o_old = slots->root_o;
mps_root_t root_o_new;
mps_res_t res = mps_root_create_table_masked(&root_o_new,
slots->arena,
mps_rank_exact(),
(mps_rm_t)0,
(mps_addr_t *)data,
slots->capacity,
(mps_word_t)TAG_MASK);
if (res != MPS_RES_OK) printf("Couldn't create root for decreased slots\n");
for(int i = 0; i != slots->size; i++) {
data[i] = slots->data[i];
}
free(slots->data);
slots->root_o = root_o_new;
slots->data = data;
mps_root_destroy(root_o_old);
}
}
void slots_free(Slots *slots) {
free(slots->data);
}
//////////////////////////SLOT FUNCTION//////////////////////////
uint64_t invert_non_negative(uint64_t slot) {
uint64_t mask = ( ~((int64_t)slot) >> 63) & !(1LU << 63);
return slot ^ mask;
}
uint16_t tag(uint64_t slot) {
return (slot >> 48 & 0xFFFF);
}
bool is_pointer(uint64_t slot) {
uint16_t t = tag(slot);
return !is_nil(slot) && (t == TAG_POINTER_LO || t == TAG_POINTER_HI);
}
// ---------------- Double Function ----------------
bool is_double(uint64_t slot) {
uint16_t t = tag(slot);
return t >= TAG_DOUBLE_MIN && t <= TAG_DOUBLE_MAX;
}
double get_double(uint64_t slot) {
if (is_double(slot)) {
union slot bits;
bits.raw = invert_non_negative(slot);
return *((double *)(void*) bits.ptr);
} else {
printf("get_double called with nondouble\n");
return 0.0;
}
}
uint64_t to_double(double num) {
union slot bits;
bits.dbl = num;
return invert_non_negative(bits.raw);
}
// ---------------- Type Function ----------------
uint64_t to_type(uint16_t type) {
uint64_t int0 = ((uint64_t) TAG_TYPE) << 48;
uint64_t result = int0 | type;
return result;
}
bool is_type(uint64_t slot) {
uint16_t t = tag(slot);
return t == TAG_TYPE;
}
uint16_t get_type(uint64_t slot) {
return (slot & 0xFFFFFFFF);
}
// ---------------- BUILTIN Function --------------
uint64_t to_builtin(builtin_fn fn) {
uint64_t int0 = ((uint64_t) TAG_BUILTIN) << 48;
uint64_t result = int0 | ((uint64_t) fn) ;
return result;
}
bool is_builtin(uint64_t slot) {
uint16_t t = tag(slot);
return t == TAG_BUILTIN;
}
builtin_fn get_builtin(uint64_t slot) {
return (builtin_fn) (void *) (slot & 0xFFFFFFFF);
}
// ---------------- FNEW Function ----------------
uint64_t to_fnew(int16_t type) {
uint64_t int0 = ((uint64_t) TAG_FNEW) << 48;
uint64_t result = int0 | type;
return result;
}
bool is_fnew(uint64_t slot) {
uint16_t t = tag(slot);
return t == TAG_FNEW;
}
int16_t get_fnew(uint64_t slot) {
return (slot & 0xFFFFFFFF);
}
// ---------------- Int Function ----------------
uint64_t to_small_int(int32_t num) {
uint64_t int0 = ((uint64_t) TAG_SMALL_INTEGER) << 48;
uint64_t result = int0 | num;
return result;
}
bool is_small_int(uint64_t slot) {
uint16_t t = tag(slot);
return t == TAG_SMALL_INTEGER;
}
int32_t get_small_int(uint64_t slot) {
return (slot & 0xFFFFFFFF);
}
// ---------------- Nil Function ----------------
bool is_nil(uint64_t slot) {
return slot == 0;
}
uint64_t get_nil() {
return (uint64_t)0;
}
// ---------------- Bool Function ----------------
bool is_bool(uint64_t slot) {
uint16_t t = tag(slot);
return t == TAG_BOOL;
}
bool get_bool(uint64_t slot) {
return (bool) (slot & 0x1);
}
uint64_t to_bool(bool value) {
uint64_t mask = ((uint64_t) TAG_BOOL) << 48;
uint64_t result = mask | (uint64_t) value;
return result;
}
// ---------------- Truthy/Falsy Function ----------------
bool is_falsy(uint64_t slot) {
printf("is_truthy \n");
if(is_bool(slot))
return get_bool(slot) == 0;
if(is_nil(slot))
return true;
else
return false;
}
bool is_truthy(uint64_t slot) {
printf("is_truthy \n");
return !is_falsy(slot);
}