Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/jvmci/metadataHandles.cpp
40950 views
1
/*
2
* Copyright (c) 2019, 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
#include "precompiled.hpp"
25
#include "classfile/classLoaderData.hpp"
26
#include "jvmci/metadataHandles.hpp"
27
#include "runtime/atomic.hpp"
28
29
jmetadata MetadataHandles::allocate_metadata_handle(Metadata* obj) {
30
assert(obj->is_valid() && obj->is_metadata(), "must be");
31
32
if (_head == NULL) {
33
// This is the first allocation.
34
_head = new MetadataHandleBlock();
35
_last = _head;
36
_num_blocks++;
37
}
38
39
HandleRecord* handle = get_handle();
40
41
if (handle != NULL) {
42
handle->set_value(obj);
43
#ifdef METADATA_TRACK_NAMES
44
handle->set_name(obj->print_value_string());
45
#endif
46
return (jmetadata) handle;
47
}
48
49
// Check if an unused block follows last
50
if (_last->_next != NULL) {
51
// update last and retry
52
_last = _last->_next;
53
return allocate_metadata_handle(obj);
54
}
55
56
// No space available, we have to rebuild free list or expand
57
if (_allocate_before_rebuild == 0) {
58
rebuild_free_list(); // updates _allocate_before_rebuild counter
59
} else {
60
// Append new block
61
_last->_next = new MetadataHandleBlock();
62
_last = _last->_next;
63
_allocate_before_rebuild--;
64
_num_blocks++;
65
}
66
return allocate_metadata_handle(obj); // retry
67
}
68
69
70
void MetadataHandles::rebuild_free_list() {
71
assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");
72
int free = 0;
73
int blocks = 0;
74
for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
75
for (int index = 0; index < current->_top; index++) {
76
HandleRecord* handle = &(current->_handles)[index];
77
if (handle->value() == NULL) {
78
// this handle was cleared out by a delete call, reuse it
79
chain_free_list(handle);
80
free++;
81
}
82
}
83
// we should not rebuild free list if there are unused handles at the end
84
assert(current->_top == MetadataHandleBlock::block_size_in_handles, "just checking");
85
blocks++;
86
}
87
assert(_num_blocks == blocks, "%d != %d", _num_blocks, blocks);
88
assert(_num_free_handles == free, "%d != %d", _num_free_handles, free);
89
// Heuristic: if more than half of the handles are NOT free we rebuild next time
90
// as well, otherwise we append a corresponding number of new blocks before
91
// attempting a free list rebuild again.
92
int total = blocks * MetadataHandleBlock::block_size_in_handles;
93
int extra = total - 2*free;
94
if (extra > 0) {
95
// Not as many free handles as we would like - compute number of new blocks to append
96
_allocate_before_rebuild = (extra + MetadataHandleBlock::block_size_in_handles - 1) / MetadataHandleBlock::block_size_in_handles;
97
}
98
}
99
100
void MetadataHandles::clear() {
101
_free_list = 0;
102
_last = _head;
103
if (_head != NULL) {
104
for (MetadataHandleBlock* block = _head; block != NULL; block = block->_next) {
105
block->_top = 0;
106
}
107
}
108
_num_handles = 0;
109
_num_free_handles = 0;
110
}
111
112
void MetadataHandles::metadata_do(void f(Metadata*)) {
113
for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
114
for (int index = 0; index < current->_top; index++) {
115
HandleRecord* root = &(current->_handles)[index];
116
Metadata* value = root->value();
117
// traverse heap pointers only, not deleted handles or free list
118
// pointers
119
if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
120
assert(value->is_valid(), "invalid metadata %s", current->get_name(index));
121
f(value);
122
}
123
}
124
// the next handle block is valid only if current block is full
125
if (current->_top < MetadataHandleBlock::block_size_in_handles) {
126
break;
127
}
128
}
129
}
130
131
// Visit any live metadata handles and clean them up. Since clearing of these handles is driven by
132
// weak references they will be cleared at some point in the future when the reference cleaning logic is run.
133
void MetadataHandles::do_unloading() {
134
for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
135
for (int index = 0; index < current->_top; index++) {
136
HandleRecord* handle = &(current->_handles)[index];
137
Metadata* value = handle->value();
138
// traverse heap pointers only, not deleted handles or free list
139
// pointers
140
if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
141
Klass* klass = NULL;
142
if (value->is_klass()) {
143
klass = (Klass*)value;
144
} else if (value->is_method()) {
145
Method* m = (Method*)value;
146
klass = m->method_holder();
147
} else if (value->is_constantPool()) {
148
ConstantPool* cp = (ConstantPool*)value;
149
klass = cp->pool_holder();
150
} else {
151
ShouldNotReachHere();
152
}
153
if (klass->class_loader_data()->is_unloading()) {
154
// This needs to be marked so that it's no longer scanned
155
// but can't be put on the free list yet. The
156
// HandleCleaner will set this to NULL and
157
// put it on the free list.
158
jlong old_value = Atomic::cmpxchg((jlong*)handle, (jlong) value, (jlong) (ptr_tag));
159
if (old_value == (jlong) value) {
160
// Success
161
} else {
162
guarantee(old_value == 0, "only other possible value");
163
}
164
}
165
}
166
}
167
// the next handle block is valid only if current block is full
168
if (current->_top < MetadataHandleBlock::block_size_in_handles) {
169
break;
170
}
171
}
172
}
173
174