Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/memory/allocation.cpp
40949 views
1
/*
2
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
#include "memory/allocation.hpp"
27
#include "memory/allocation.inline.hpp"
28
#include "memory/arena.hpp"
29
#include "memory/metaspace.hpp"
30
#include "memory/resourceArea.hpp"
31
#include "runtime/os.hpp"
32
#include "runtime/task.hpp"
33
#include "runtime/threadCritical.hpp"
34
#include "services/memTracker.hpp"
35
#include "utilities/ostream.hpp"
36
37
// allocate using malloc; will fail if no memory available
38
char* AllocateHeap(size_t size,
39
MEMFLAGS flags,
40
const NativeCallStack& stack,
41
AllocFailType alloc_failmode /* = AllocFailStrategy::EXIT_OOM*/) {
42
char* p = (char*) os::malloc(size, flags, stack);
43
if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) {
44
vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "AllocateHeap");
45
}
46
return p;
47
}
48
49
char* AllocateHeap(size_t size,
50
MEMFLAGS flags,
51
AllocFailType alloc_failmode /* = AllocFailStrategy::EXIT_OOM*/) {
52
return AllocateHeap(size, flags, CALLER_PC);
53
}
54
55
char* ReallocateHeap(char *old,
56
size_t size,
57
MEMFLAGS flag,
58
AllocFailType alloc_failmode) {
59
char* p = (char*) os::realloc(old, size, flag, CALLER_PC);
60
if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) {
61
vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "ReallocateHeap");
62
}
63
return p;
64
}
65
66
// handles NULL pointers
67
void FreeHeap(void* p) {
68
os::free(p);
69
}
70
71
void* MetaspaceObj::_shared_metaspace_base = NULL;
72
void* MetaspaceObj::_shared_metaspace_top = NULL;
73
74
void* StackObj::operator new(size_t size) throw() { ShouldNotCallThis(); return 0; }
75
void StackObj::operator delete(void* p) { ShouldNotCallThis(); }
76
void* StackObj::operator new [](size_t size) throw() { ShouldNotCallThis(); return 0; }
77
void StackObj::operator delete [](void* p) { ShouldNotCallThis(); }
78
79
void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data,
80
size_t word_size,
81
MetaspaceObj::Type type, TRAPS) throw() {
82
// Klass has its own operator new
83
return Metaspace::allocate(loader_data, word_size, type, THREAD);
84
}
85
86
void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data,
87
size_t word_size,
88
MetaspaceObj::Type type) throw() {
89
assert(!Thread::current()->is_Java_thread(), "only allowed by non-Java thread");
90
return Metaspace::allocate(loader_data, word_size, type);
91
}
92
93
bool MetaspaceObj::is_valid(const MetaspaceObj* p) {
94
// Weed out obvious bogus values first without traversing metaspace
95
if ((size_t)p < os::min_page_size()) {
96
return false;
97
} else if (!is_aligned((address)p, sizeof(MetaWord))) {
98
return false;
99
}
100
return Metaspace::contains((void*)p);
101
}
102
103
void MetaspaceObj::print_address_on(outputStream* st) const {
104
st->print(" {" INTPTR_FORMAT "}", p2i(this));
105
}
106
107
void* ResourceObj::operator new(size_t size, Arena *arena) throw() {
108
address res = (address)arena->Amalloc(size);
109
DEBUG_ONLY(set_allocation_type(res, ARENA);)
110
return res;
111
}
112
113
void* ResourceObj::operator new [](size_t size, Arena *arena) throw() {
114
address res = (address)arena->Amalloc(size);
115
DEBUG_ONLY(set_allocation_type(res, ARENA);)
116
return res;
117
}
118
119
void* ResourceObj::operator new(size_t size, allocation_type type, MEMFLAGS flags) throw() {
120
address res = NULL;
121
switch (type) {
122
case C_HEAP:
123
res = (address)AllocateHeap(size, flags, CALLER_PC);
124
DEBUG_ONLY(set_allocation_type(res, C_HEAP);)
125
break;
126
case RESOURCE_AREA:
127
// new(size) sets allocation type RESOURCE_AREA.
128
res = (address)operator new(size);
129
break;
130
default:
131
ShouldNotReachHere();
132
}
133
return res;
134
}
135
136
void* ResourceObj::operator new [](size_t size, allocation_type type, MEMFLAGS flags) throw() {
137
return (address) operator new(size, type, flags);
138
}
139
140
void* ResourceObj::operator new(size_t size, const std::nothrow_t& nothrow_constant,
141
allocation_type type, MEMFLAGS flags) throw() {
142
// should only call this with std::nothrow, use other operator new() otherwise
143
address res = NULL;
144
switch (type) {
145
case C_HEAP:
146
res = (address)AllocateHeap(size, flags, CALLER_PC, AllocFailStrategy::RETURN_NULL);
147
DEBUG_ONLY(if (res!= NULL) set_allocation_type(res, C_HEAP);)
148
break;
149
case RESOURCE_AREA:
150
// new(size) sets allocation type RESOURCE_AREA.
151
res = (address)operator new(size, std::nothrow);
152
break;
153
default:
154
ShouldNotReachHere();
155
}
156
return res;
157
}
158
159
void* ResourceObj::operator new [](size_t size, const std::nothrow_t& nothrow_constant,
160
allocation_type type, MEMFLAGS flags) throw() {
161
return (address)operator new(size, nothrow_constant, type, flags);
162
}
163
164
void ResourceObj::operator delete(void* p) {
165
assert(((ResourceObj *)p)->allocated_on_C_heap(),
166
"delete only allowed for C_HEAP objects");
167
DEBUG_ONLY(((ResourceObj *)p)->_allocation_t[0] = (uintptr_t)badHeapOopVal;)
168
FreeHeap(p);
169
}
170
171
void ResourceObj::operator delete [](void* p) {
172
operator delete(p);
173
}
174
175
#ifdef ASSERT
176
void ResourceObj::set_allocation_type(address res, allocation_type type) {
177
// Set allocation type in the resource object
178
uintptr_t allocation = (uintptr_t)res;
179
assert((allocation & allocation_mask) == 0, "address should be aligned to 4 bytes at least: " INTPTR_FORMAT, p2i(res));
180
assert(type <= allocation_mask, "incorrect allocation type");
181
ResourceObj* resobj = (ResourceObj *)res;
182
resobj->_allocation_t[0] = ~(allocation + type);
183
if (type != STACK_OR_EMBEDDED) {
184
// Called from operator new(), set verification value.
185
resobj->_allocation_t[1] = (uintptr_t)&(resobj->_allocation_t[1]) + type;
186
}
187
}
188
189
ResourceObj::allocation_type ResourceObj::get_allocation_type() const {
190
assert(~(_allocation_t[0] | allocation_mask) == (uintptr_t)this, "lost resource object");
191
return (allocation_type)((~_allocation_t[0]) & allocation_mask);
192
}
193
194
bool ResourceObj::is_type_set() const {
195
allocation_type type = (allocation_type)(_allocation_t[1] & allocation_mask);
196
return get_allocation_type() == type &&
197
(_allocation_t[1] - type) == (uintptr_t)(&_allocation_t[1]);
198
}
199
200
// This whole business of passing information from ResourceObj::operator new
201
// to the ResourceObj constructor via fields in the "object" is technically UB.
202
// But it seems to work within the limitations of HotSpot usage (such as no
203
// multiple inheritance) with the compilers and compiler options we're using.
204
// And it gives some possibly useful checking for misuse of ResourceObj.
205
void ResourceObj::initialize_allocation_info() {
206
if (~(_allocation_t[0] | allocation_mask) != (uintptr_t)this) {
207
// Operator new() is not called for allocations
208
// on stack and for embedded objects.
209
set_allocation_type((address)this, STACK_OR_EMBEDDED);
210
} else if (allocated_on_stack()) { // STACK_OR_EMBEDDED
211
// For some reason we got a value which resembles
212
// an embedded or stack object (operator new() does not
213
// set such type). Keep it since it is valid value
214
// (even if it was garbage).
215
// Ignore garbage in other fields.
216
} else if (is_type_set()) {
217
// Operator new() was called and type was set.
218
assert(!allocated_on_stack(),
219
"not embedded or stack, this(" PTR_FORMAT ") type %d a[0]=(" PTR_FORMAT ") a[1]=(" PTR_FORMAT ")",
220
p2i(this), get_allocation_type(), _allocation_t[0], _allocation_t[1]);
221
} else {
222
// Operator new() was not called.
223
// Assume that it is embedded or stack object.
224
set_allocation_type((address)this, STACK_OR_EMBEDDED);
225
}
226
_allocation_t[1] = 0; // Zap verification value
227
}
228
229
ResourceObj::ResourceObj() {
230
initialize_allocation_info();
231
}
232
233
ResourceObj::ResourceObj(const ResourceObj&) {
234
// Initialize _allocation_t as a new object, ignoring object being copied.
235
initialize_allocation_info();
236
}
237
238
ResourceObj& ResourceObj::operator=(const ResourceObj& r) {
239
assert(allocated_on_stack(),
240
"copy only into local, this(" PTR_FORMAT ") type %d a[0]=(" PTR_FORMAT ") a[1]=(" PTR_FORMAT ")",
241
p2i(this), get_allocation_type(), _allocation_t[0], _allocation_t[1]);
242
// Keep current _allocation_t value;
243
return *this;
244
}
245
246
ResourceObj::~ResourceObj() {
247
// allocated_on_C_heap() also checks that encoded (in _allocation) address == this.
248
if (!allocated_on_C_heap()) { // ResourceObj::delete() will zap _allocation for C_heap.
249
_allocation_t[0] = (uintptr_t)badHeapOopVal; // zap type
250
}
251
}
252
#endif // ASSERT
253
254
//--------------------------------------------------------------------------------------
255
// Non-product code
256
257
#ifndef PRODUCT
258
void AllocatedObj::print() const { print_on(tty); }
259
void AllocatedObj::print_value() const { print_value_on(tty); }
260
261
void AllocatedObj::print_on(outputStream* st) const {
262
st->print_cr("AllocatedObj(" INTPTR_FORMAT ")", p2i(this));
263
}
264
265
void AllocatedObj::print_value_on(outputStream* st) const {
266
st->print("AllocatedObj(" INTPTR_FORMAT ")", p2i(this));
267
}
268
269
ReallocMark::ReallocMark() {
270
#ifdef ASSERT
271
Thread *thread = Thread::current();
272
_nesting = thread->resource_area()->nesting();
273
#endif
274
}
275
276
void ReallocMark::check() {
277
#ifdef ASSERT
278
if (_nesting != Thread::current()->resource_area()->nesting()) {
279
fatal("allocation bug: array could grow within nested ResourceMark");
280
}
281
#endif
282
}
283
284
#endif // Non-product
285
286