Skip to content

Commit 91292c7

Browse files
committed
---
yaml --- r: 4853 b: refs/heads/master c: 907ab4a h: refs/heads/master i: 4851: be9683b v: v3
1 parent d87c3fc commit 91292c7

File tree

2 files changed

+122
-9
lines changed

2 files changed

+122
-9
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 84a6b888c05cea0bfdebd825d425ba5cbee4772a
2+
refs/heads/master: 907ab4a11b57f6f75c760c004f647d649a68dce1

trunk/src/rt/rust_gc.cpp

Lines changed: 121 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Rust garbage collection.
22

3+
#include <algorithm>
34
#include <utility>
5+
#include <vector>
46
#include <stdint.h>
57

68
#include "rust_gc.h"
@@ -12,33 +14,79 @@
1214
#include <dlfcn.h>
1315
#endif
1416

17+
#define DPRINT(fmt,...) fprintf(stderr, fmt, ##__VA_ARGS__)
18+
19+
#define END_OF_STACK_RA (void (*)())0xdeadbeef
20+
1521
namespace gc {
1622

17-
struct root {
23+
struct frame {
24+
uint8_t *bp; // The frame pointer.
25+
void (*ra)(); // The return address.
26+
27+
frame(void *in_bp) : bp((uint8_t *)in_bp) {}
28+
29+
inline void read_ra() {
30+
ra = *(void (**)())(bp + sizeof(void *));
31+
}
32+
33+
inline void next() {
34+
bp = *(uint8_t **)bp;
35+
}
36+
};
37+
38+
struct root_info {
1839
intptr_t frame_offset;
1940
uintptr_t dynamic; // 0 = static, 1 = dynamic
2041
type_desc *tydesc;
2142
};
2243

44+
struct root {
45+
type_desc *tydesc;
46+
uint8_t *data;
47+
48+
root(const root_info &info, const frame &frame)
49+
: tydesc(info.tydesc),
50+
data((uint8_t *)frame.bp + info.frame_offset) {}
51+
};
52+
2353
struct safe_point {
2454
uintptr_t n_roots;
25-
root roots[0];
55+
root_info roots[0];
56+
};
57+
58+
struct safe_point_index_entry {
59+
void (*ra)(); // The return address.
60+
const safe_point *safe_point; // The safe point.
61+
62+
struct cmp {
63+
bool operator()(const safe_point_index_entry &entry, void (*ra)())
64+
const {
65+
return entry.ra < ra;
66+
}
67+
bool operator()(void (*ra)(), const safe_point_index_entry &entry)
68+
const {
69+
return ra < entry.ra;
70+
}
71+
};
2672
};
2773

2874
class safe_point_map {
2975
uintptr_t n_safe_points;
30-
const std::pair<void *,const safe_point *> *index;
76+
const safe_point_index_entry *index;
3177
const safe_point *safe_points;
3278

3379
public:
3480
safe_point_map() {
3581
const uintptr_t *data = get_safe_point_data();
3682
n_safe_points = *data++;
37-
index = (const std::pair<void *,const safe_point *> *)data;
83+
index = (const safe_point_index_entry *)data;
3884
data += n_safe_points * 2;
3985
safe_points = (const safe_point *)data;
4086
}
4187

88+
const safe_point *get_safe_point(void (*addr)());
89+
4290
static const uintptr_t *get_safe_point_data() {
4391
static bool init = false;
4492
static const uintptr_t *data;
@@ -56,13 +104,76 @@ class safe_point_map {
56104
}
57105
};
58106

107+
class gc {
108+
private:
109+
void mark(std::vector<root> &roots);
110+
void sweep();
111+
112+
public:
113+
void run(rust_task *task);
114+
std::vector<frame> backtrace();
115+
};
116+
117+
const safe_point *
118+
safe_point_map::get_safe_point(void (*addr)()) {
119+
safe_point_index_entry::cmp cmp;
120+
const safe_point_index_entry *entry =
121+
std::lower_bound(index, index + n_safe_points, addr, cmp);
122+
return (entry && entry->ra == addr) ? entry->safe_point : NULL;
123+
}
124+
59125
void
60-
gc(rust_task *task) {
61-
safe_point_map map;
126+
gc::mark(std::vector<root> &roots) {
127+
std::vector<root>::iterator ri = roots.begin(), rend = roots.end();
128+
while (ri < rend) {
129+
DPRINT("root: %p\n", ri->data);
130+
++ri;
131+
}
132+
// TODO
133+
}
62134

135+
void
136+
gc::sweep() {
63137
// TODO
64138
}
65139

140+
std::vector<frame>
141+
gc::backtrace() {
142+
std::vector<frame> frames;
143+
frame f(__builtin_frame_address(0));
144+
while (f.ra != END_OF_STACK_RA) {
145+
f.read_ra();
146+
frames.push_back(f);
147+
f.next();
148+
}
149+
return frames;
150+
}
151+
152+
void
153+
gc::run(rust_task *task) {
154+
safe_point_map map;
155+
156+
// Find roots.
157+
std::vector<root> roots;
158+
std::vector<frame> call_stack = backtrace();
159+
for (unsigned i = 0; i < call_stack.size(); i++) {
160+
frame f = call_stack[i];
161+
const safe_point *sp = map.get_safe_point(f.ra);
162+
if (!sp)
163+
continue;
164+
165+
DPRINT("%u: ra %p, ebp %p\n", i, call_stack[i].ra, call_stack[i].bp);
166+
for (unsigned j = 0; j < sp->n_roots; j++) {
167+
root r(sp->roots[j], f);
168+
roots.push_back(r);
169+
}
170+
}
171+
172+
// Mark and sweep.
173+
mark(roots);
174+
sweep();
175+
}
176+
66177
void
67178
maybe_gc(rust_task *task) {
68179
if (safe_point_map::get_safe_point_data() == NULL)
@@ -75,8 +186,10 @@ maybe_gc(rust_task *task) {
75186
zeal = ev && ev[0] != '\0' && ev[0] != '0';
76187
}
77188

78-
if (zeal)
79-
gc::gc(task);
189+
if (zeal) {
190+
gc gc;
191+
gc.run(task);
192+
}
80193
}
81194

82195
}

0 commit comments

Comments
 (0)