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#ifndef SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
25#define SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
26
27#include "oops/constantPool.hpp"
28#include "oops/metadata.hpp"
29#include "oops/method.hpp"
30#include "runtime/handles.hpp"
31#include "runtime/os.hpp"
32
33#ifdef ASSERT
34#define METADATA_TRACK_NAMES
35#endif
36
37struct _jmetadata {
38 private:
39 Metadata* _value;
40#ifdef METADATA_TRACK_NAMES
41 // Debug data for tracking stale metadata
42 const char* _name;
43#endif
44
45 public:
46 Metadata* value() { return _value; }
47
48#ifdef METADATA_TRACK_NAMES
49 void initialize() {
50 _value = NULL;
51 _name = NULL;
52 }
53#endif
54
55 void set_value(Metadata* value) {
56 _value = value;
57 }
58
59#ifdef METADATA_TRACK_NAMES
60 const char* name() { return _name; }
61 void set_name(const char* name) {
62 if (_name != NULL) {
63 os::free((void*) _name);
64 _name = NULL;
65 }
66 if (name != NULL) {
67 _name = os::strdup(name);
68 }
69 }
70#endif
71};
72
73typedef struct _jmetadata HandleRecord;
74typedef struct _jmetadata *jmetadata;
75
76// JVMCI maintains direct references to metadata. To make these references safe in the face of
77// class redefinition, they are held in handles so they can be scanned during GC. They are
78// managed in a cooperative way between the Java code and HotSpot. A handle is filled in and
79// passed back to the Java code which is responsible for setting the handle to NULL when it
80// is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The
81// rebuild_free_list function notices when the handle is clear and reclaims it for re-use.
82class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
83 private:
84 enum SomeConstants {
85 block_size_in_handles = 32, // Number of handles per handle block
86 ptr_tag = 1,
87 ptr_mask = ~((intptr_t)ptr_tag)
88 };
89
90
91 // Free handles always have their low bit set so those pointers can
92 // be distinguished from handles which are in use. The last handle
93 // on the free list has a NULL pointer with the tag bit set, so it's
94 // clear that the handle has been reclaimed. The _free_list is
95 // always a real pointer to a handle.
96
97 HandleRecord _handles[block_size_in_handles]; // The handles
98 int _top; // Index of next unused handle
99 MetadataHandleBlock* _next; // Link to next block
100
101 // The following instance variables are only used by the first block in a chain.
102 // Having two types of blocks complicates the code and the space overhead is negligible.
103 static MetadataHandleBlock* _last; // Last block in use
104 static intptr_t _free_list; // Handle free list
105 static int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
106
107 MetadataHandleBlock() {
108 _top = 0;
109 _next = NULL;
110#ifdef METADATA_TRACK_NAMES
111 for (int i = 0; i < block_size_in_handles; i++) {
112 _handles[i].initialize();
113 }
114#endif
115 }
116
117 const char* get_name(int index) {
118#ifdef METADATA_TRACK_NAMES
119 return _handles[index].name();
120#else
121 return "<missing>";
122#endif
123 }
124
125 static HandleRecord* get_free_handle() {
126 assert(_free_list != 0, "should check before calling");
127 HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask);
128 _free_list = (ptr_mask & (intptr_t) (handle->value()));
129 assert(_free_list != ptr_tag, "should be null");
130 handle->set_value(NULL);
131 return handle;
132 }
133
134 static HandleRecord* get_handle() {
135 assert(_last != NULL, "sanity");
136 // Try last block
137 if (_last->_top < block_size_in_handles) {
138 return &(_last->_handles)[_last->_top++];
139 } else if (_free_list != 0) {
140 // Try free list
141 return get_free_handle();
142 }
143 return NULL;
144 }
145
146 void rebuild_free_list();
147
148 jmetadata allocate_metadata_handle(Metadata* metadata);
149
150 public:
151 jmetadata allocate_handle(const methodHandle& handle) { return allocate_metadata_handle(handle()); }
152 jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); }
153
154 static MetadataHandleBlock* allocate_block() { return new MetadataHandleBlock(); }
155
156 // Adds `handle` to the free list in this block
157 static void chain_free_list(HandleRecord* handle) {
158 handle->set_value((Metadata*) (ptr_tag | _free_list));
159#ifdef METADATA_TRACK_NAMES
160 handle->set_name(NULL);
161#endif
162 _free_list = (intptr_t) handle;
163 }
164
165 void metadata_do(void f(Metadata*));
166
167 void do_unloading();
168};
169
170#endif // SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
171