25
25
#ifndef SHARE_NMT_NMTNATIVECALLSTACKSTORAGE_HPP
26
26
#define SHARE_NMT_NMTNATIVECALLSTACKSTORAGE_HPP
27
27
28
- #include " memory/allocation.hpp"
29
- #include " memory/arena.hpp"
28
+ #include " nmt/arrayWithFreeList.hpp"
30
29
#include " utilities/growableArray.hpp"
31
30
#include " utilities/nativeCallStack.hpp"
32
31
40
39
// - Have fast comparisons
41
40
// - Have constant time access
42
41
// We achieve this by using a closed hashtable for finding previously existing NCS:s and referring to them by an index that's smaller than a pointer.
43
- class NativeCallStackStorage : public CHeapObj <mtNMT> {
42
+ class NativeCallStackStorage : public CHeapObjBase {
44
43
public:
45
44
struct StackIndex {
46
45
friend NativeCallStackStorage;
47
-
48
- private:
49
- static constexpr const int32_t _invalid = -1 ;
50
-
51
46
int32_t _stack_index;
52
- StackIndex (int32_t stack_index)
53
- : _stack_index(stack_index) {
54
- }
55
-
56
47
public:
48
+ static constexpr const int32_t invalid = -1 ;
57
49
static bool equals (const StackIndex& a, const StackIndex& b) {
58
50
return a._stack_index == b._stack_index ;
59
51
}
60
52
61
53
bool is_invalid () {
62
- return _stack_index == _invalid;
63
- }
64
-
65
- StackIndex ()
66
- : _stack_index(_invalid) {
54
+ return _stack_index == invalid;
67
55
}
68
56
};
69
57
70
58
private:
71
- struct Link : public ArenaObj {
72
- Link* next;
59
+ struct TableEntry ;
60
+ using TableEntryStorage = ArrayWithFreeList<TableEntry, mtNMT>;
61
+ using TableEntryIndex = typename TableEntryStorage::I;
62
+
63
+ TableEntryStorage _entry_storage;
64
+
65
+ struct TableEntry {
66
+ TableEntryIndex next;
73
67
StackIndex stack;
74
- Link (Link* next, StackIndex v)
75
- : next(next),
76
- stack (v) {
77
- }
78
68
};
79
- StackIndex put (const NativeCallStack& value) {
80
- int bucket = value.calculate_hash () % _table_size;
81
- Link* link = _table[bucket];
82
- while (link != nullptr ) {
83
- if (value.equals (get (link ->stack ))) {
84
- return link ->stack ;
85
- }
86
- link = link ->next ;
87
- }
88
- int idx = _stacks.append (value);
89
- Link* new_link = new (&_arena) Link (_table[bucket], StackIndex (idx));
90
- _table[bucket] = new_link;
91
- return new_link->stack ;
92
- }
93
69
94
- // For storage of the Links
95
- Arena _arena;
70
+ StackIndex put ( const NativeCallStack& value);
71
+
96
72
// Pick a prime number of buckets.
97
73
// 4099 gives a 50% probability of collisions at 76 stacks (as per birthday problem).
98
74
static const constexpr int default_table_size = 4099 ;
99
- int _table_size;
100
- Link* * _table;
75
+ const int _table_size;
76
+ TableEntryIndex * _table;
101
77
GrowableArrayCHeap<NativeCallStack, mtNMT> _stacks;
102
78
const bool _is_detailed_mode;
103
79
@@ -107,7 +83,7 @@ class NativeCallStackStorage : public CHeapObj<mtNMT> {
107
83
StackIndex push (const NativeCallStack& stack) {
108
84
// Not in detailed mode, so not tracking stacks.
109
85
if (!_is_detailed_mode) {
110
- return StackIndex () ;
86
+ return StackIndex{StackIndex::invalid} ;
111
87
}
112
88
return put (stack);
113
89
}
@@ -119,16 +95,9 @@ class NativeCallStackStorage : public CHeapObj<mtNMT> {
119
95
return _stacks.at (si._stack_index );
120
96
}
121
97
122
- NativeCallStackStorage (bool is_detailed_mode, int table_size = default_table_size)
123
- : _arena(mtNMT), _table_size(table_size), _table(nullptr ), _stacks(),
124
- _is_detailed_mode(is_detailed_mode), _fake_stack() {
125
- if (_is_detailed_mode) {
126
- _table = NEW_ARENA_ARRAY (&_arena, Link*, _table_size);
127
- for (int i = 0 ; i < _table_size; i++) {
128
- _table[i] = nullptr ;
129
- }
130
- }
131
- }
98
+ NativeCallStackStorage (bool is_detailed_mode, int table_size = default_table_size);
99
+
100
+ ~NativeCallStackStorage ();
132
101
};
133
102
134
103
#endif // SHARE_NMT_NMTNATIVECALLSTACKSTORAGE_HPP
0 commit comments