-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
132 lines (101 loc) · 3.26 KB
/
main.cpp
File metadata and controls
132 lines (101 loc) · 3.26 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
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
//
// This file tests the GC implementation. Please note that the stack test will
// fail on optimized builds, because the variable is optimized away or put in a
// register.
//
#include <cstring>
#include <malloc.h>
#include "gc.h"
#undef NDEBUG
#include <assert.h>
// Compiler hacks to ease feature testing.
// See helpers.asm
extern "C" void mov_to_r15(void*);
extern "C" void noop(void*);
__declspec(noinline)
void black_box(void* value)
{
//printf("black_box: %p\n", value);
noop(value);
}
__declspec(noinline)
void clear_stack_above()
{
int count = 64000;
char* ptr = (char*)alloca(count);
memset(ptr, 0xbb, count);
noop(ptr);
}
struct top_obj
{
int* foo;
const char** bar;
short data;
int* baz;
};
int* g_globalIntBss;
int* g_globalIntData = (int*)123;
int main(int argc, char* argv[])
{
gc_state* gc = gc_create();
top_obj* obj = gc_make<top_obj>(gc);
//gc_add_root(gc, obj);
obj->foo = (int*)gc_new0(gc, sizeof(int));
*obj->foo = 15;
obj->bar = (const char**)gc_new0(gc, sizeof(const char*));
*obj->bar = "Hello, world!";
obj->data = 0x1234;
obj->baz = (int*)gc_new0(gc, sizeof(int));
*obj->baz = 42;
assert(gc_get_object_count(gc) == 4 && "allocations should have produced objects");
clear_stack_above();
gc_collect(gc); // 4 obj left
assert(gc_get_object_count(gc) == 4 && "first collection should not collect any objects");
// CLEAR SUB-OBJECT REF
obj->baz = NULL;
clear_stack_above();
gc_collect(gc); // 3 obj left
assert(gc_get_object_count(gc) == 3 && "sub-object reference should be collected");
// STACK REF
int* number = (int*)gc_new0(gc, sizeof(int));
assert(gc_get_object_count(gc) == 4 && "stack ref should be allocated");
clear_stack_above();
gc_collect(gc);
assert(gc_get_object_count(gc) == 4 && "stack ref should be tracked");
number = NULL;
clear_stack_above();
gc_collect(gc);
assert(gc_get_object_count(gc) == 3 && "nulled stack ref should be collected");
// REGISTER REF
int* number2 = (int*)gc_new0(gc, sizeof(int));
assert(gc_get_object_count(gc) == 4 && "stack ref should be allocated");
mov_to_r15(number2); // set register
number2 = NULL; // clear stack ref
// now pointer should be only in the r15 register
clear_stack_above();
gc_collect(gc);
assert(gc_get_object_count(gc) == 4 && "register ref should be tracked");
mov_to_r15(0); // clear register
clear_stack_above();
gc_collect(gc);
assert(gc_get_object_count(gc) == 3 && "register ref should be cleared");
// GLOBALS
g_globalIntBss = (int*)gc_new0(gc, sizeof(int));
g_globalIntData = (int*)gc_new0(gc, sizeof(int));
assert(gc_get_object_count(gc) == 5 && "global refs should be allocated");
clear_stack_above();
gc_collect(gc);
assert(gc_get_object_count(gc) == 5 && "global refs should be tracked");
black_box(g_globalIntBss);
black_box(g_globalIntData);
g_globalIntBss = 0;
g_globalIntData = 0;
clear_stack_above();
gc_collect(gc);
assert(gc_get_object_count(gc) == 3 && "global refs should be cleared");
black_box(g_globalIntBss);
black_box(g_globalIntData);
// keep obj alive in optimized builds
black_box(obj);
return 0;
}