Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/interpreter/bootstrapInfo.cpp
40949 views
1
/*
2
* Copyright (c) 2019, 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 "jvm.h"
27
#include "classfile/javaClasses.inline.hpp"
28
#include "classfile/resolutionErrors.hpp"
29
#include "classfile/systemDictionary.hpp"
30
#include "classfile/vmClasses.hpp"
31
#include "interpreter/bootstrapInfo.hpp"
32
#include "interpreter/linkResolver.hpp"
33
#include "logging/log.hpp"
34
#include "logging/logStream.hpp"
35
#include "memory/oopFactory.hpp"
36
#include "memory/resourceArea.hpp"
37
#include "oops/cpCache.inline.hpp"
38
#include "oops/objArrayOop.inline.hpp"
39
#include "oops/typeArrayOop.inline.hpp"
40
#include "runtime/handles.inline.hpp"
41
#include "runtime/thread.inline.hpp"
42
#include "runtime/vmThread.hpp"
43
44
//------------------------------------------------------------------------------------------------------------------------
45
// Implementation of BootstrapInfo
46
47
BootstrapInfo::BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index)
48
: _pool(pool),
49
_bss_index(bss_index),
50
_indy_index(indy_index),
51
// derived and eagerly cached:
52
_argc( pool->bootstrap_argument_count_at(bss_index) ),
53
_name( pool->uncached_name_ref_at(bss_index) ),
54
_signature( pool->uncached_signature_ref_at(bss_index) )
55
{
56
_is_resolved = false;
57
assert(pool->tag_at(bss_index).has_bootstrap(), "");
58
assert(indy_index == -1 || pool->invokedynamic_bootstrap_ref_index_at(indy_index) == bss_index, "invalid bootstrap specifier index");
59
}
60
61
// If there is evidence this call site was already linked, set the
62
// existing linkage data into result, or throw previous exception.
63
// Return true if either action is taken, else false.
64
bool BootstrapInfo::resolve_previously_linked_invokedynamic(CallInfo& result, TRAPS) {
65
assert(_indy_index != -1, "");
66
ConstantPoolCacheEntry* cpce = invokedynamic_cp_cache_entry();
67
if (!cpce->is_f1_null()) {
68
methodHandle method( THREAD, cpce->f1_as_method());
69
Handle appendix( THREAD, cpce->appendix_if_resolved(_pool));
70
result.set_handle(method, appendix, THREAD);
71
Exceptions::wrap_dynamic_exception(/* is_indy */ true, CHECK_false);
72
return true;
73
} else if (cpce->indy_resolution_failed()) {
74
int encoded_index = ResolutionErrorTable::encode_cpcache_index(_indy_index);
75
ConstantPool::throw_resolution_error(_pool, encoded_index, CHECK_false);
76
return true;
77
} else {
78
return false;
79
}
80
}
81
82
// Resolve the bootstrap specifier in 3 steps:
83
// - unpack the BSM by resolving the MH constant
84
// - obtain the NameAndType description for the condy/indy
85
// - prepare the BSM's static arguments
86
Handle BootstrapInfo::resolve_bsm(TRAPS) {
87
if (_bsm.not_null()) {
88
return _bsm;
89
}
90
91
bool is_indy = is_method_call();
92
// The tag at the bootstrap method index must be a valid method handle or a method handle in error.
93
// If it is a MethodHandleInError, a resolution error will be thrown which will be wrapped if necessary
94
// with a BootstrapMethodError.
95
assert(_pool->tag_at(bsm_index()).is_method_handle() ||
96
_pool->tag_at(bsm_index()).is_method_handle_in_error(), "MH not present, classfile structural constraint");
97
oop bsm_oop = _pool->resolve_possibly_cached_constant_at(bsm_index(), THREAD);
98
Exceptions::wrap_dynamic_exception(is_indy, CHECK_NH);
99
guarantee(java_lang_invoke_MethodHandle::is_instance(bsm_oop), "classfile must supply a valid BSM");
100
_bsm = Handle(THREAD, bsm_oop);
101
102
// Obtain NameAndType information
103
resolve_bss_name_and_type(THREAD);
104
Exceptions::wrap_dynamic_exception(is_indy, CHECK_NH);
105
106
// Prepare static arguments
107
resolve_args(THREAD);
108
Exceptions::wrap_dynamic_exception(is_indy, CHECK_NH);
109
110
return _bsm;
111
}
112
113
// Resolve metadata from the JVM_Dynamic_info or JVM_InvokeDynamic_info's name and type information.
114
void BootstrapInfo::resolve_bss_name_and_type(TRAPS) {
115
assert(_bsm.not_null(), "resolve_bsm first");
116
Symbol* name = this->name();
117
Symbol* type = this->signature();
118
_name_arg = java_lang_String::create_from_symbol(name, CHECK);
119
if (type->char_at(0) == '(') {
120
_type_arg = SystemDictionary::find_method_handle_type(type, caller(), CHECK);
121
} else {
122
_type_arg = SystemDictionary::find_java_mirror_for_type(type, caller(), SignatureStream::NCDFError, CHECK);
123
}
124
}
125
126
// Resolve the bootstrap method's static arguments and store the result in _arg_values.
127
void BootstrapInfo::resolve_args(TRAPS) {
128
assert(_bsm.not_null(), "resolve_bsm first");
129
130
// if there are no static arguments, return leaving _arg_values as null
131
if (_argc == 0 && UseBootstrapCallInfo < 2) return;
132
133
bool use_BSCI;
134
switch (UseBootstrapCallInfo) {
135
default: use_BSCI = true; break; // stress mode
136
case 0: use_BSCI = false; break; // stress mode
137
case 1: // normal mode
138
// If we were to support an alternative mode of BSM invocation,
139
// we'd convert to pull mode here if the BSM could be a candidate
140
// for that alternative mode. We can't easily test for things
141
// like varargs here, but we can get away with approximate testing,
142
// since the JDK runtime will make up the difference either way.
143
// For now, exercise the pull-mode path if the BSM is of arity 2,
144
// or if there is a potential condy loop (see below).
145
oop mt_oop = java_lang_invoke_MethodHandle::type(_bsm());
146
use_BSCI = (java_lang_invoke_MethodType::ptype_count(mt_oop) == 2);
147
break;
148
}
149
150
// Here's a reason to use BSCI even if it wasn't requested:
151
// If a condy uses a condy argument, we want to avoid infinite
152
// recursion (condy loops) in the C code. It's OK in Java,
153
// because Java has stack overflow checking, so we punt
154
// potentially cyclic cases from C to Java.
155
if (!use_BSCI && _pool->tag_at(_bss_index).is_dynamic_constant()) {
156
bool found_unresolved_condy = false;
157
for (int i = 0; i < _argc; i++) {
158
int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i);
159
if (_pool->tag_at(arg_index).is_dynamic_constant()) {
160
// potential recursion point condy -> condy
161
bool found_it = false;
162
_pool->find_cached_constant_at(arg_index, found_it, CHECK);
163
if (!found_it) { found_unresolved_condy = true; break; }
164
}
165
}
166
if (found_unresolved_condy)
167
use_BSCI = true;
168
}
169
170
const int SMALL_ARITY = 5;
171
if (use_BSCI && _argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) {
172
// If there are only a few arguments, and none of them need linking,
173
// push them, instead of asking the JDK runtime to turn around and
174
// pull them, saving a JVM/JDK transition in some simple cases.
175
bool all_resolved = true;
176
for (int i = 0; i < _argc; i++) {
177
bool found_it = false;
178
int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i);
179
_pool->find_cached_constant_at(arg_index, found_it, CHECK);
180
if (!found_it) { all_resolved = false; break; }
181
}
182
if (all_resolved)
183
use_BSCI = false;
184
}
185
186
if (!use_BSCI) {
187
// return {arg...}; resolution of arguments is done immediately, before JDK code is called
188
objArrayOop args_oop = oopFactory::new_objArray(vmClasses::Object_klass(), _argc, CHECK);
189
objArrayHandle args(THREAD, args_oop);
190
_pool->copy_bootstrap_arguments_at(_bss_index, 0, _argc, args, 0, true, Handle(), CHECK);
191
oop arg_oop = ((_argc == 1) ? args->obj_at(0) : (oop)NULL);
192
// try to discard the singleton array
193
if (arg_oop != NULL && !arg_oop->is_array()) {
194
// JVM treats arrays and nulls specially in this position,
195
// but other things are just single arguments
196
_arg_values = Handle(THREAD, arg_oop);
197
} else {
198
_arg_values = args;
199
}
200
} else {
201
// return {arg_count, pool_index}; JDK code must pull the arguments as needed
202
typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK);
203
ints_oop->int_at_put(0, _argc);
204
ints_oop->int_at_put(1, _bss_index);
205
_arg_values = Handle(THREAD, ints_oop);
206
}
207
}
208
209
// there must be a LinkageError pending; try to save it and then throw
210
bool BootstrapInfo::save_and_throw_indy_exc(TRAPS) {
211
assert(HAS_PENDING_EXCEPTION, "");
212
assert(_indy_index != -1, "");
213
ConstantPoolCacheEntry* cpce = invokedynamic_cp_cache_entry();
214
int encoded_index = ResolutionErrorTable::encode_cpcache_index(_indy_index);
215
bool recorded_res_status = cpce->save_and_throw_indy_exc(_pool, _bss_index,
216
encoded_index,
217
pool()->tag_at(_bss_index),
218
CHECK_false);
219
return recorded_res_status;
220
}
221
222
void BootstrapInfo::resolve_newly_linked_invokedynamic(CallInfo& result, TRAPS) {
223
assert(is_resolved(), "");
224
result.set_handle(resolved_method(), resolved_appendix(), CHECK);
225
}
226
227
void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) {
228
ResourceMark rm;
229
char what[20];
230
st = st ? st : tty;
231
232
if (_indy_index != -1)
233
sprintf(what, "indy#%d", decode_indy_index());
234
else
235
sprintf(what, "condy");
236
bool have_msg = (msg != NULL && strlen(msg) > 0);
237
st->print_cr("%s%sBootstrap in %s %s@CP[%d] %s:%s%s BSMS[%d] BSM@CP[%d]%s argc=%d%s",
238
(have_msg ? msg : ""), (have_msg ? " " : ""),
239
caller()->name()->as_C_string(),
240
what, // "indy#42" or "condy"
241
_bss_index,
242
_name->as_C_string(),
243
_signature->as_C_string(),
244
(_type_arg.is_null() ? "" : "(resolved)"),
245
bsms_attr_index(),
246
bsm_index(), (_bsm.is_null() ? "" : "(resolved)"),
247
_argc, (_arg_values.is_null() ? "" : "(resolved)"));
248
if (_argc > 0) {
249
char argbuf[80];
250
argbuf[0] = 0;
251
for (int i = 0; i < _argc; i++) {
252
int pos = (int) strlen(argbuf);
253
if (pos + 20 > (int)sizeof(argbuf)) {
254
sprintf(argbuf + pos, "...");
255
break;
256
}
257
if (i > 0) argbuf[pos++] = ',';
258
sprintf(argbuf+pos, "%d", arg_index(i));
259
}
260
st->print_cr(" argument indexes: {%s}", argbuf);
261
}
262
if (_bsm.not_null()) {
263
st->print(" resolved BSM: "); _bsm->print_on(st);
264
}
265
266
// How the array of resolved arguments is printed depends highly
267
// on how BootstrapInfo::resolve_args structures the array based on
268
// the use_BSCI setting.
269
if (_arg_values.not_null()) {
270
// Find the static arguments within the first element of _arg_values.
271
objArrayOop static_args = (objArrayOop)_arg_values();
272
if (!static_args->is_array()) {
273
assert(_argc == 1, "Invalid BSM _arg_values for non-array");
274
st->print(" resolved arg[0]: "); static_args->print_on(st);
275
} else if (static_args->is_objArray()) {
276
int lines = 0;
277
for (int i = 0; i < _argc; i++) {
278
oop x = static_args->obj_at(i);
279
if (x != NULL) {
280
if (++lines > 6) {
281
st->print_cr(" resolved arg[%d]: ...", i);
282
break;
283
}
284
st->print(" resolved arg[%d]: ", i); x->print_on(st);
285
}
286
}
287
} else if (static_args->is_typeArray()) {
288
typeArrayOop tmp_array = (typeArrayOop) static_args;
289
assert(tmp_array->length() == 2, "Invalid BSM _arg_values type array");
290
st->print_cr(" resolved arg[0]: %d", tmp_array->int_at(0));
291
st->print_cr(" resolved arg[1]: %d", tmp_array->int_at(1));
292
}
293
}
294
}
295
296