1/*
2 * Copyright (c) 2019, 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 "jvmci/metadataHandleBlock.hpp"
26
27MetadataHandleBlock* MetadataHandleBlock::_last = NULL;
28intptr_t MetadataHandleBlock::_free_list = 0;
29int MetadataHandleBlock::_allocate_before_rebuild = 0;
30
31jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) {
32 assert(obj->is_valid() && obj->is_metadata(), "must be");
33
34 if (_last == NULL) {
35 // This is the first allocation.
36 _last = this;
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 unused block follow 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 // This can block, but the caller has a metadata handle around this object.
62 _last->_next = allocate_block();
63 _last = _last->_next;
64 _allocate_before_rebuild--;
65 }
66 return allocate_metadata_handle(obj); // retry
67}
68
69
70void MetadataHandleBlock::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 = this; 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 == block_size_in_handles, "just checking");
85 blocks++;
86 }
87 // Heuristic: if more than half of the handles are NOT free we rebuild next time
88 // as well, otherwise we append a corresponding number of new blocks before
89 // attempting a free list rebuild again.
90 int total = blocks * block_size_in_handles;
91 int extra = total - 2*free;
92 if (extra > 0) {
93 // Not as many free handles as we would like - compute number of new blocks to append
94 _allocate_before_rebuild = (extra + block_size_in_handles - 1) / block_size_in_handles;
95 }
96}
97
98void MetadataHandleBlock::metadata_do(void f(Metadata*)) {
99 for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
100 for (int index = 0; index < current->_top; index++) {
101 HandleRecord* root = &(current->_handles)[index];
102 Metadata* value = root->value();
103 // traverse heap pointers only, not deleted handles or free list
104 // pointers
105 if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
106 assert(value->is_valid(), "invalid metadata %s", get_name(index));
107 f(value);
108 }
109 }
110 // the next handle block is valid only if current block is full
111 if (current->_top < block_size_in_handles) {
112 break;
113 }
114 }
115}
116
117// Visit any live metadata handles and clean them up. Since clearing of these handles is driven by
118// weak references they will be cleared at some point in the future when the reference cleaning logic is run.
119void MetadataHandleBlock::do_unloading() {
120 for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
121 for (int index = 0; index < current->_top; index++) {
122 HandleRecord* handle = &(current->_handles)[index];
123 Metadata* value = handle->value();
124 // traverse heap pointers only, not deleted handles or free list
125 // pointers
126 if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
127 Klass* klass = NULL;
128 if (value->is_klass()) {
129 klass = (Klass*)value;
130 } else if (value->is_method()) {
131 Method* m = (Method*)value;
132 klass = m->method_holder();
133 } else if (value->is_constantPool()) {
134 ConstantPool* cp = (ConstantPool*)value;
135 klass = cp->pool_holder();
136 } else {
137 ShouldNotReachHere();
138 }
139 if (klass->class_loader_data()->is_unloading()) {
140 // This needs to be marked so that it's no longer scanned
141 // but can't be put on the free list yet. The
142 // HandleCleaner will set this to NULL and
143 // put it on the free list.
144 jlong old_value = Atomic::cmpxchg((jlong) (ptr_tag), (jlong*)handle, (jlong) value);
145 if (old_value == (jlong) value) {
146 // Success
147 } else {
148 guarantee(old_value == 0, "only other possible value");
149 }
150 }
151 }
152 }
153 // the next handle block is valid only if current block is full
154 if (current->_top < block_size_in_handles) {
155 break;
156 }
157 }
158}
159