Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp
32285 views
1
/*
2
* Copyright (c) 2013, 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 "classfile/metadataOnStackMark.hpp"
27
#include "code/codeCache.hpp"
28
#include "compiler/compileBroker.hpp"
29
#include "oops/metadata.hpp"
30
#include "prims/jvmtiImpl.hpp"
31
#include "runtime/synchronizer.hpp"
32
#include "runtime/thread.hpp"
33
#include "services/threadService.hpp"
34
#include "utilities/chunkedList.hpp"
35
36
volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;
37
volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;
38
39
NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
40
41
// Walk metadata on the stack and mark it so that redefinition doesn't delete
42
// it. Class unloading also walks the previous versions and might try to
43
// delete it, so this class is used by class unloading also.
44
MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) {
45
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
46
assert(_used_buffers == NULL, "sanity check");
47
NOT_PRODUCT(_is_active = true;)
48
49
Threads::metadata_do(Metadata::mark_on_stack);
50
if (has_redefined_a_class) {
51
CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
52
}
53
CompileBroker::mark_on_stack();
54
JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
55
ThreadService::metadata_do(Metadata::mark_on_stack);
56
}
57
58
MetadataOnStackMark::~MetadataOnStackMark() {
59
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
60
// Unmark everything that was marked. Can't do the same walk because
61
// redefine classes messes up the code cache so the set of methods
62
// might not be the same.
63
64
retire_buffer_for_thread(Thread::current());
65
66
MetadataOnStackBuffer* buffer = const_cast<MetadataOnStackBuffer* >(_used_buffers);
67
while (buffer != NULL) {
68
// Clear on stack state for all metadata.
69
size_t size = buffer->size();
70
for (size_t i = 0; i < size; i++) {
71
Metadata* md = buffer->at(i);
72
md->set_on_stack(false);
73
}
74
75
MetadataOnStackBuffer* next = buffer->next_used();
76
77
// Move the buffer to the free list.
78
buffer->clear();
79
buffer->set_next_used(NULL);
80
buffer->set_next_free(const_cast<MetadataOnStackBuffer*>(_free_buffers));
81
_free_buffers = buffer;
82
83
// Step to next used buffer.
84
buffer = next;
85
}
86
87
_used_buffers = NULL;
88
89
NOT_PRODUCT(_is_active = false;)
90
}
91
92
void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) {
93
if (buffer == NULL) {
94
return;
95
}
96
97
MetadataOnStackBuffer* old_head;
98
99
do {
100
old_head = const_cast<MetadataOnStackBuffer*>(_used_buffers);
101
buffer->set_next_used(old_head);
102
} while (Atomic::cmpxchg_ptr(buffer, &_used_buffers, old_head) != old_head);
103
}
104
105
void MetadataOnStackMark::retire_buffer_for_thread(Thread* thread) {
106
retire_buffer(thread->metadata_on_stack_buffer());
107
thread->set_metadata_on_stack_buffer(NULL);
108
}
109
110
bool MetadataOnStackMark::has_buffer_for_thread(Thread* thread) {
111
return thread->metadata_on_stack_buffer() != NULL;
112
}
113
114
MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() {
115
MetadataOnStackBuffer* allocated;
116
MetadataOnStackBuffer* new_head;
117
118
do {
119
allocated = const_cast<MetadataOnStackBuffer*>(_free_buffers);
120
if (allocated == NULL) {
121
break;
122
}
123
new_head = allocated->next_free();
124
} while (Atomic::cmpxchg_ptr(new_head, &_free_buffers, allocated) != allocated);
125
126
if (allocated == NULL) {
127
allocated = new MetadataOnStackBuffer();
128
}
129
130
assert(!allocated->is_full(), err_msg("Should not be full: " PTR_FORMAT, p2i(allocated)));
131
132
return allocated;
133
}
134
135
// Record which objects are marked so we can unmark the same objects.
136
void MetadataOnStackMark::record(Metadata* m, Thread* thread) {
137
assert(_is_active, "metadata on stack marking is active");
138
139
MetadataOnStackBuffer* buffer = thread->metadata_on_stack_buffer();
140
141
if (buffer != NULL && buffer->is_full()) {
142
retire_buffer(buffer);
143
buffer = NULL;
144
}
145
146
if (buffer == NULL) {
147
buffer = allocate_buffer();
148
thread->set_metadata_on_stack_buffer(buffer);
149
}
150
151
buffer->push(m);
152
}
153
154