Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/cds/lambdaFormInvokers.cpp
41144 views
1
/*
2
* Copyright (c) 2020, 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
25
#include "precompiled.hpp"
26
#include "cds/archiveBuilder.hpp"
27
#include "cds/lambdaFormInvokers.hpp"
28
#include "cds/metaspaceShared.hpp"
29
#include "classfile/classLoadInfo.hpp"
30
#include "classfile/classFileStream.hpp"
31
#include "classfile/javaClasses.inline.hpp"
32
#include "classfile/klassFactory.hpp"
33
#include "classfile/symbolTable.hpp"
34
#include "classfile/systemDictionary.hpp"
35
#include "classfile/systemDictionaryShared.hpp"
36
#include "classfile/vmClasses.hpp"
37
#include "classfile/vmSymbols.hpp"
38
#include "logging/log.hpp"
39
#include "memory/oopFactory.hpp"
40
#include "memory/resourceArea.hpp"
41
#include "oops/instanceKlass.hpp"
42
#include "oops/klass.hpp"
43
#include "oops/objArrayKlass.hpp"
44
#include "oops/objArrayOop.hpp"
45
#include "oops/oop.inline.hpp"
46
#include "oops/typeArrayOop.inline.hpp"
47
#include "runtime/handles.inline.hpp"
48
#include "runtime/javaCalls.hpp"
49
#include "runtime/mutexLocker.hpp"
50
51
GrowableArrayCHeap<char*, mtClassShared>* LambdaFormInvokers::_lambdaform_lines = nullptr;
52
Array<Array<char>*>* LambdaFormInvokers::_static_archive_invokers = nullptr;
53
54
#define NUM_FILTER 4
55
static const char* filter[NUM_FILTER] = {"java.lang.invoke.Invokers$Holder",
56
"java.lang.invoke.DirectMethodHandle$Holder",
57
"java.lang.invoke.DelegatingMethodHandle$Holder",
58
"java.lang.invoke.LambdaForm$Holder"};
59
60
static bool should_be_archived(char* line) {
61
for (int k = 0; k < NUM_FILTER; k++) {
62
if (strstr(line, filter[k]) != nullptr) {
63
return true;
64
}
65
}
66
return false;
67
}
68
69
void LambdaFormInvokers::append_filtered(char* line) {
70
if (should_be_archived(line)) {
71
append(line);
72
}
73
}
74
#undef NUM_FILTER
75
76
void LambdaFormInvokers::append(char* line) {
77
MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
78
if (_lambdaform_lines == NULL) {
79
_lambdaform_lines = new GrowableArrayCHeap<char*, mtClassShared>(150);
80
}
81
_lambdaform_lines->append(line);
82
}
83
84
// convenient output
85
class PrintLambdaFormMessage {
86
public:
87
PrintLambdaFormMessage() {
88
log_info(cds)("Regenerate MethodHandle Holder classes...");
89
}
90
~PrintLambdaFormMessage() {
91
log_info(cds)("Regenerate MethodHandle Holder classes...done");
92
}
93
};
94
95
void LambdaFormInvokers::regenerate_holder_classes(TRAPS) {
96
PrintLambdaFormMessage plm;
97
if (_lambdaform_lines == nullptr || _lambdaform_lines->length() == 0) {
98
log_info(cds)("Nothing to regenerate for holder classes");
99
return;
100
}
101
102
ResourceMark rm(THREAD);
103
104
Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();
105
Klass* cds_klass = SystemDictionary::resolve_or_null(cds_name, THREAD);
106
guarantee(cds_klass != NULL, "jdk/internal/misc/CDS must exist!");
107
108
HandleMark hm(THREAD);
109
int len = _lambdaform_lines->length();
110
objArrayHandle list_lines;
111
{
112
MutexLocker ml(Thread::current(), LambdaFormInvokers_lock);
113
list_lines = oopFactory::new_objArray_handle(vmClasses::String_klass(), len, CHECK);
114
for (int i = 0; i < len; i++) {
115
Handle h_line = java_lang_String::create_from_str(_lambdaform_lines->at(i), CHECK);
116
list_lines->obj_at_put(i, h_line());
117
}
118
} // Before calling into java, release vm lock.
119
//
120
// Object[] CDS.generateLambdaFormHolderClasses(String[] lines)
121
// the returned Object[] layout:
122
// name, byte[], name, byte[] ....
123
Symbol* method = vmSymbols::generateLambdaFormHolderClasses();
124
Symbol* signrs = vmSymbols::generateLambdaFormHolderClasses_signature();
125
126
JavaValue result(T_OBJECT);
127
JavaCalls::call_static(&result, cds_klass, method, signrs, list_lines, THREAD);
128
129
if (HAS_PENDING_EXCEPTION) {
130
if (!PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) {
131
log_error(cds)("%s: %s", PENDING_EXCEPTION->klass()->external_name(),
132
java_lang_String::as_utf8_string(java_lang_Throwable::message(PENDING_EXCEPTION)));
133
if (DumpSharedSpaces) {
134
log_error(cds)("Failed to generate LambdaForm holder classes. Is your classlist out of date?");
135
} else {
136
log_error(cds)("Failed to generate LambdaForm holder classes. Was the base archive generated with an outdated classlist?");
137
}
138
CLEAR_PENDING_EXCEPTION;
139
}
140
return;
141
}
142
143
objArrayHandle h_array(THREAD, (objArrayOop)result.get_oop());
144
int sz = h_array->length();
145
assert(sz % 2 == 0 && sz >= 2, "Must be even size of length");
146
for (int i = 0; i < sz; i+= 2) {
147
Handle h_name(THREAD, h_array->obj_at(i));
148
typeArrayHandle h_bytes(THREAD, (typeArrayOop)h_array->obj_at(i+1));
149
assert(h_name != NULL, "Class name is NULL");
150
assert(h_bytes != NULL, "Class bytes is NULL");
151
152
char *class_name = java_lang_String::as_utf8_string(h_name());
153
int len = h_bytes->length();
154
// make a copy of class bytes so GC will not affect us.
155
char *buf = NEW_RESOURCE_ARRAY(char, len);
156
memcpy(buf, (char*)h_bytes->byte_at_addr(0), len);
157
ClassFileStream st((u1*)buf, len, NULL, ClassFileStream::verify);
158
reload_class(class_name, st, CHECK);
159
}
160
}
161
162
// class_handle - the class name, bytes_handle - the class bytes
163
void LambdaFormInvokers::reload_class(char* name, ClassFileStream& st, TRAPS) {
164
Symbol* class_name = SymbolTable::new_symbol((const char*)name);
165
// the class must exist
166
Klass* klass = SystemDictionary::resolve_or_null(class_name, THREAD);
167
if (klass == NULL) {
168
log_info(cds)("Class %s not present, skip", name);
169
return;
170
}
171
assert(klass->is_instance_klass(), "Should be");
172
173
ClassLoaderData* cld = ClassLoaderData::the_null_class_loader_data();
174
Handle protection_domain;
175
ClassLoadInfo cl_info(protection_domain);
176
177
InstanceKlass* result = KlassFactory::create_from_stream(&st,
178
class_name,
179
cld,
180
cl_info,
181
CHECK);
182
183
{
184
MutexLocker mu_r(THREAD, Compile_lock); // add_to_hierarchy asserts this.
185
SystemDictionary::add_to_hierarchy(result);
186
}
187
// new class not linked yet.
188
MetaspaceShared::try_link_class(THREAD, result);
189
assert(!HAS_PENDING_EXCEPTION, "Invariant");
190
191
// exclude the existing class from dump
192
SystemDictionaryShared::set_excluded(InstanceKlass::cast(klass));
193
SystemDictionaryShared::init_dumptime_info(result);
194
log_info(cds, lambda)("Replaced class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT,
195
name, p2i(klass), p2i(result));
196
}
197
198
void LambdaFormInvokers::dump_static_archive_invokers() {
199
if (_lambdaform_lines != nullptr && _lambdaform_lines->length() > 0) {
200
int count = 0;
201
int len = _lambdaform_lines->length();
202
for (int i = 0; i < len; i++) {
203
char* str = _lambdaform_lines->at(i);
204
if (should_be_archived(str)) {
205
count++;
206
}
207
}
208
if (count > 0) {
209
_static_archive_invokers = ArchiveBuilder::new_ro_array<Array<char>*>(count);
210
int index = 0;
211
for (int i = 0; i < len; i++) {
212
char* str = _lambdaform_lines->at(i);
213
if (should_be_archived(str)) {
214
size_t str_len = strlen(str) + 1; // including terminating zero
215
Array<char>* line = ArchiveBuilder::new_ro_array<char>((int)str_len);
216
strncpy(line->adr_at(0), str, str_len);
217
218
_static_archive_invokers->at_put(index, line);
219
ArchivePtrMarker::mark_pointer(_static_archive_invokers->adr_at(index));
220
index++;
221
}
222
}
223
assert(index == count, "Should match");
224
}
225
log_debug(cds)("Total LF lines stored into static archive: %d", count);
226
}
227
}
228
229
void LambdaFormInvokers::read_static_archive_invokers() {
230
if (_static_archive_invokers != nullptr) {
231
for (int i = 0; i < _static_archive_invokers->length(); i++) {
232
Array<char>* line = _static_archive_invokers->at(i);
233
char* str = line->adr_at(0);
234
append(str);
235
}
236
log_debug(cds)("Total LF lines read from static archive: %d", _static_archive_invokers->length());
237
}
238
}
239
240
void LambdaFormInvokers::serialize(SerializeClosure* soc) {
241
soc->do_ptr((void**)&_static_archive_invokers);
242
}
243
244