-
Notifications
You must be signed in to change notification settings - Fork 1
/
mutator.cpp
122 lines (95 loc) · 3.11 KB
/
mutator.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
#include <atomic>
#include <cstdlib>
#include <memory>
#include "atomic_list.hpp"
#include "impl_details.hpp"
#include "gc.hpp"
#include "mutator.hpp"
using namespace std;
namespace otf_gc
{
inline size_t mutator::binary_log(int sz)
{
assert(sz >= 8);
sz--;
sz |= sz >> 1;
sz |= sz >> 2;
sz |= sz >> 4;
sz |= sz >> 8;
sz |= sz >> 16;
sz -= (sz >> 1) & 0x5555555555555555ULL;
sz = (sz & 0x3333333333333333ULL) + ((sz >> 2) & 0x3333333333333333ULL);
sz = (sz + (sz >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
return (sz * 0x0101010101010101ULL) >> 56;
}
inline impl_details::underlying_header_t
mutator::create_header(impl_details::underlying_header_t desc)
{
using namespace impl_details;
return static_cast<underlying_header_t>(alloc_color.c) | (desc << color_bits);
}
inline bool mutator::transfer_small_blocks_from_collector(size_t power)
{
stub_list stubs = gc::collector->small_free_lists[power-3].pop_front();
if(stubs) {
fixed_managers[power-3].append(std::move(stubs));
return true;
}
return false;
}
void* mutator::allocate_small(size_t power, impl_details::underlying_header_t desc)
{
void* ptr = fixed_managers[power-3].get_block();
if(!ptr) {
if(transfer_small_blocks_from_collector(power))
ptr = fixed_managers[power-3].get_block();
if(!ptr) {
void* blk = fixed_managers[power-3].get_new_block();
allocation_dump.push_front(blk);
ptr = blk;
}
}
new(ptr) impl_details::log_ptr_t(nullptr);
new(reinterpret_cast<header_t*>(reinterpret_cast<std::ptrdiff_t>(ptr) + log_ptr_size))
impl_details::header_t(create_header(desc));
return ptr;
}
void* mutator::allocate_large(size_t sz,
impl_details::underlying_header_t desc,
size_t num_log_ptrs)
{
void* blk = aligned_alloc(alignof(impl_details::header_t), sz);
large_used_list.push_front(blk);
block_cursor blk_c(blk);
blk_c.num_log_ptrs() = num_log_ptrs;
blk_c.recalculate();
for(size_t i = 0; i < num_log_ptrs; ++i)
new(blk_c.log_ptr(i)) impl_details::log_ptr_t(nullptr);
new(blk_c.header()) impl_details::header_t(create_header(desc));
return blk;
}
stub_list mutator::vacate_small_used_list(size_t i)
{
return fixed_managers[i].release_used_list();
}
large_block_list mutator::vacate_large_used_list()
{
auto result = large_used_list;
large_used_list.reset();
return result;
}
void* mutator::allocate(int raw_sz,
impl_details::underlying_header_t desc,
size_t num_log_ptrs)
{
using namespace impl_details;
if(raw_sz + small_block_metadata_size <= large_obj_threshold) {
void* p = allocate_small(mutator::binary_log(raw_sz + small_block_metadata_size), desc);
return reinterpret_cast<void*>(reinterpret_cast<std::ptrdiff_t>(p) + small_block_metadata_size);
} else {
size_t preamble_sz = large_block_metadata_size + num_log_ptrs * log_ptr_size;
void *p = allocate_large(preamble_sz + raw_sz, desc, num_log_ptrs);
return reinterpret_cast<void*>(reinterpret_cast<std::ptrdiff_t>(p) + preamble_sz);
}
}
}