26
#include "precompiled.hpp"
27
#include "nmt/nmtPreInit.hpp"
28
#include "runtime/os.hpp"
29
#include "utilities/align.hpp"
30
#include "utilities/debug.hpp"
31
#include "utilities/globalDefinitions.hpp"
32
#include "utilities/ostream.hpp"
36
static void* raw_malloc(size_t s) { ALLOW_C_FUNCTION(::malloc, return ::malloc(s);) }
37
static void* raw_realloc(void* old, size_t s) { ALLOW_C_FUNCTION(::realloc, return ::realloc(old, s);) }
38
static void raw_free(void* p) { ALLOW_C_FUNCTION(::free, ::free(p);) }
44
static void* raw_checked_malloc(size_t s) {
45
void* p = raw_malloc(s);
47
vm_exit_out_of_memory(s, OOM_MALLOC_ERROR, "VM early initialization phase");
52
static void* raw_checked_realloc(void* old, size_t s) {
53
void* p = raw_realloc(old, s);
55
vm_exit_out_of_memory(s, OOM_MALLOC_ERROR, "VM early initialization phase");
62
void* NMTPreInitAllocation::operator new(size_t count) {
63
return raw_checked_malloc(count);
66
void NMTPreInitAllocation::operator delete(void* p) {
70
NMTPreInitAllocation* NMTPreInitAllocation::do_alloc(size_t payload_size) {
71
void* payload = raw_checked_malloc(payload_size);
72
NMTPreInitAllocation* a = new NMTPreInitAllocation(payload_size, payload);
76
NMTPreInitAllocation* NMTPreInitAllocation::do_reallocate(NMTPreInitAllocation* a, size_t new_payload_size) {
77
assert(a->next == nullptr, "unhang from map first");
78
void* new_payload = raw_checked_realloc(a->payload, new_payload_size);
79
NMTPreInitAllocation* a2 = new NMTPreInitAllocation(new_payload_size, new_payload);
84
void NMTPreInitAllocation::do_free(NMTPreInitAllocation* a) {
85
assert(a->next == nullptr, "unhang from map first");
92
void* NMTPreInitAllocationTable::operator new(size_t count) {
93
return raw_checked_malloc(count);
96
void NMTPreInitAllocationTable::operator delete(void* p) {
100
NMTPreInitAllocationTable::NMTPreInitAllocationTable() {
101
::memset(_entries, 0, sizeof(_entries));
104
NMTPreInitAllocationTable::~NMTPreInitAllocationTable() {
106
for (int i = 0; i < table_size; i++) {
107
NMTPreInitAllocation* a = _entries[i];
108
while (a != nullptr) {
109
NMTPreInitAllocation* a2 = a->next;
117
void NMTPreInitAllocationTable::print_state(outputStream* st) const {
120
int num_primary_entries = 0;
121
int longest_chain = 0;
122
size_t sum_bytes = 0;
123
for (int i = 0; i < table_size; i++) {
125
for (NMTPreInitAllocation* a = _entries[i]; a != nullptr; a = a->next) {
127
sum_bytes += a->size;
130
num_primary_entries++;
132
num_entries += chain_len;
133
longest_chain = MAX2(chain_len, longest_chain);
135
st->print("entries: %d (primary: %d, empties: %d), sum bytes: " SIZE_FORMAT
136
", longest chain length: %d",
137
num_entries, num_primary_entries, table_size - num_primary_entries,
138
sum_bytes, longest_chain);
142
void NMTPreInitAllocationTable::print_map(outputStream* st) const {
143
for (int i = 0; i < table_size; i++) {
144
st->print("[%d]: ", i);
145
for (NMTPreInitAllocation* a = _entries[i]; a != nullptr; a = a->next) {
146
st->print( PTR_FORMAT "(" SIZE_FORMAT ") ", p2i(a->payload), a->size);
152
void NMTPreInitAllocationTable::verify() const {
157
const int longest_acceptable_chain_len = 30;
158
int num_chains_too_long = 0;
159
for (index_t i = 0; i < table_size; i++) {
161
for (const NMTPreInitAllocation* a = _entries[i]; a != nullptr; a = a->next) {
162
index_t i2 = index_for_key(a->payload);
163
assert(i2 == i, "wrong hash");
164
assert(a->size > 0, "wrong size");
168
for (const NMTPreInitAllocation* a2 = _entries[i]; a2 != nullptr; a2 = a2->next) {
170
assert(!found, "dup!");
175
if (len > longest_acceptable_chain_len) {
176
num_chains_too_long++;
179
if (num_chains_too_long > 0) {
180
assert(false, "NMT preinit lookup table degenerated (%d/%d chains longer than %d)",
181
num_chains_too_long, table_size, longest_acceptable_chain_len);
188
NMTPreInitAllocationTable* NMTPreInit::_table = nullptr;
191
unsigned NMTPreInit::_num_mallocs_pre = 0;
192
unsigned NMTPreInit::_num_reallocs_pre = 0;
193
unsigned NMTPreInit::_num_frees_pre = 0;
195
void NMTPreInit::create_table() {
196
assert(_table == nullptr, "just once");
197
_table = new NMTPreInitAllocationTable;
201
void* NMTPreInit::do_os_malloc(size_t size, MEMFLAGS memflags) {
202
return os::malloc(size, memflags);
207
void NMTPreInit::pre_to_post(bool nmt_off) {
209
assert(!MemTracker::is_initialized(), "just once");
210
DEBUG_ONLY(verify();)
227
void NMTPreInit::verify() {
228
if (_table != nullptr) {
231
assert(_num_reallocs_pre <= _num_mallocs_pre &&
232
_num_frees_pre <= _num_mallocs_pre, "stats are off");
236
void NMTPreInit::print_state(outputStream* st) {
237
if (_table != nullptr) {
238
_table->print_state(st);
241
st->print_cr("pre-init mallocs: %u, pre-init reallocs: %u, pre-init frees: %u",
242
_num_mallocs_pre, _num_reallocs_pre, _num_frees_pre);