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