1 /*
2 * Copyright (c) 2019, 2025, 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 "classfile/javaClasses.inline.hpp"
26 #include "classfile/resolutionErrors.hpp"
27 #include "classfile/systemDictionary.hpp"
28 #include "classfile/vmClasses.hpp"
29 #include "interpreter/bootstrapInfo.hpp"
30 #include "interpreter/linkResolver.hpp"
31 #include "jvm.h"
32 #include "logging/log.hpp"
33 #include "logging/logStream.hpp"
34 #include "memory/oopFactory.hpp"
35 #include "memory/resourceArea.hpp"
36 #include "oops/constantPool.inline.hpp"
37 #include "oops/cpCache.inline.hpp"
38 #include "oops/objArrayOop.inline.hpp"
39 #include "oops/resolvedIndyEntry.hpp"
40 #include "oops/typeArrayOop.inline.hpp"
41 #include "runtime/handles.inline.hpp"
42 #include "runtime/javaThread.hpp"
43 #include "runtime/vmThread.hpp"
44
45 //------------------------------------------------------------------------------------------------------------------------
46 // Implementation of BootstrapInfo
47
48 BootstrapInfo::BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index)
49 : _pool(pool),
50 _bss_index(bss_index),
51 _indy_index(indy_index),
52 // derived and eagerly cached:
53 _argc( pool->bootstrap_argument_count_at(bss_index) ),
54 _name( pool->uncached_name_ref_at(bss_index) ),
55 _signature( pool->uncached_signature_ref_at(bss_index) )
56 {
57 _is_resolved = false;
58 assert(pool->tag_at(bss_index).has_bootstrap(), "");
170 }
171
172 const int SMALL_ARITY = 5;
173 if (use_BSCI && _argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) {
174 // If there are only a few arguments, and none of them need linking,
175 // push them, instead of asking the JDK runtime to turn around and
176 // pull them, saving a JVM/JDK transition in some simple cases.
177 bool all_resolved = true;
178 for (int i = 0; i < _argc; i++) {
179 bool found_it = false;
180 int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i);
181 _pool->find_cached_constant_at(arg_index, found_it, CHECK);
182 if (!found_it) { all_resolved = false; break; }
183 }
184 if (all_resolved)
185 use_BSCI = false;
186 }
187
188 if (!use_BSCI) {
189 // return {arg...}; resolution of arguments is done immediately, before JDK code is called
190 objArrayOop args_oop = oopFactory::new_objArray(vmClasses::Object_klass(), _argc, CHECK);
191 objArrayHandle args(THREAD, args_oop);
192 _pool->copy_bootstrap_arguments_at(_bss_index, 0, _argc, args, 0, true, Handle(), CHECK);
193 oop arg_oop = ((_argc == 1) ? args->obj_at(0) : (oop)nullptr);
194 // try to discard the singleton array
195 if (arg_oop != nullptr && !arg_oop->is_array()) {
196 // JVM treats arrays and nulls specially in this position,
197 // but other things are just single arguments
198 _arg_values = Handle(THREAD, arg_oop);
199 } else {
200 _arg_values = args;
201 }
202 } else {
203 // return {arg_count, pool_index}; JDK code must pull the arguments as needed
204 typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK);
205 ints_oop->int_at_put(0, _argc);
206 ints_oop->int_at_put(1, _bss_index);
207 _arg_values = Handle(THREAD, ints_oop);
208 }
209 }
210
211 // there must be a LinkageError pending; try to save it and then throw
253 for (int i = 0; i < _argc; i++) {
254 int pos = (int) strlen(argbuf);
255 if (pos + 20 > (int)sizeof(argbuf)) {
256 os::snprintf_checked(argbuf + pos, sizeof(argbuf) - pos, "...");
257 break;
258 }
259 if (i > 0) argbuf[pos++] = ',';
260 os::snprintf_checked(argbuf+pos, sizeof(argbuf) - pos, "%d", arg_index(i));
261 }
262 st->print_cr(" argument indexes: {%s}", argbuf);
263 }
264 if (_bsm.not_null()) {
265 st->print(" resolved BSM: "); _bsm->print_on(st);
266 }
267
268 // How the array of resolved arguments is printed depends highly
269 // on how BootstrapInfo::resolve_args structures the array based on
270 // the use_BSCI setting.
271 if (_arg_values.not_null()) {
272 // Find the static arguments within the first element of _arg_values.
273 objArrayOop static_args = (objArrayOop)_arg_values();
274 if (!static_args->is_array()) {
275 assert(_argc == 1, "Invalid BSM _arg_values for non-array");
276 st->print(" resolved arg[0]: "); static_args->print_on(st);
277 } else if (static_args->is_objArray()) {
278 int lines = 0;
279 for (int i = 0; i < _argc; i++) {
280 oop x = static_args->obj_at(i);
281 if (x != nullptr) {
282 if (++lines > 6) {
283 st->print_cr(" resolved arg[%d]: ...", i);
284 break;
285 }
286 st->print(" resolved arg[%d]: ", i); x->print_on(st);
287 }
288 }
289 } else if (static_args->is_typeArray()) {
290 typeArrayOop tmp_array = (typeArrayOop) static_args;
291 assert(tmp_array->length() == 2, "Invalid BSM _arg_values type array");
292 st->print_cr(" resolved arg[0]: %d", tmp_array->int_at(0));
293 st->print_cr(" resolved arg[1]: %d", tmp_array->int_at(1));
294 }
295 }
296 }
|
1 /*
2 * Copyright (c) 2019, 2026, 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 "classfile/javaClasses.inline.hpp"
26 #include "classfile/resolutionErrors.hpp"
27 #include "classfile/systemDictionary.hpp"
28 #include "classfile/vmClasses.hpp"
29 #include "interpreter/bootstrapInfo.hpp"
30 #include "interpreter/linkResolver.hpp"
31 #include "jvm.h"
32 #include "logging/log.hpp"
33 #include "logging/logStream.hpp"
34 #include "memory/oopFactory.hpp"
35 #include "memory/resourceArea.hpp"
36 #include "oops/constantPool.inline.hpp"
37 #include "oops/cpCache.inline.hpp"
38 #include "oops/objArrayOop.inline.hpp"
39 #include "oops/oopCast.inline.hpp"
40 #include "oops/resolvedIndyEntry.hpp"
41 #include "oops/typeArrayOop.inline.hpp"
42 #include "runtime/handles.inline.hpp"
43 #include "runtime/javaThread.hpp"
44 #include "runtime/vmThread.hpp"
45
46 //------------------------------------------------------------------------------------------------------------------------
47 // Implementation of BootstrapInfo
48
49 BootstrapInfo::BootstrapInfo(const constantPoolHandle& pool, int bss_index, int indy_index)
50 : _pool(pool),
51 _bss_index(bss_index),
52 _indy_index(indy_index),
53 // derived and eagerly cached:
54 _argc( pool->bootstrap_argument_count_at(bss_index) ),
55 _name( pool->uncached_name_ref_at(bss_index) ),
56 _signature( pool->uncached_signature_ref_at(bss_index) )
57 {
58 _is_resolved = false;
59 assert(pool->tag_at(bss_index).has_bootstrap(), "");
171 }
172
173 const int SMALL_ARITY = 5;
174 if (use_BSCI && _argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) {
175 // If there are only a few arguments, and none of them need linking,
176 // push them, instead of asking the JDK runtime to turn around and
177 // pull them, saving a JVM/JDK transition in some simple cases.
178 bool all_resolved = true;
179 for (int i = 0; i < _argc; i++) {
180 bool found_it = false;
181 int arg_index = _pool->bootstrap_argument_index_at(_bss_index, i);
182 _pool->find_cached_constant_at(arg_index, found_it, CHECK);
183 if (!found_it) { all_resolved = false; break; }
184 }
185 if (all_resolved)
186 use_BSCI = false;
187 }
188
189 if (!use_BSCI) {
190 // return {arg...}; resolution of arguments is done immediately, before JDK code is called
191 refArrayOop args_oop = oopFactory::new_refArray(vmClasses::Object_klass(),_argc, CHECK);
192 refArrayHandle args(THREAD, args_oop);
193 _pool->copy_bootstrap_arguments_at(_bss_index, 0, _argc, args, 0, true, Handle(), CHECK);
194 oop arg_oop = ((_argc == 1) ? args->obj_at(0) : (oop)nullptr);
195 // try to discard the singleton array
196 if (arg_oop != nullptr && !arg_oop->is_array()) {
197 // JVM treats arrays and nulls specially in this position,
198 // but other things are just single arguments
199 _arg_values = Handle(THREAD, arg_oop);
200 } else {
201 _arg_values = args;
202 }
203 } else {
204 // return {arg_count, pool_index}; JDK code must pull the arguments as needed
205 typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK);
206 ints_oop->int_at_put(0, _argc);
207 ints_oop->int_at_put(1, _bss_index);
208 _arg_values = Handle(THREAD, ints_oop);
209 }
210 }
211
212 // there must be a LinkageError pending; try to save it and then throw
254 for (int i = 0; i < _argc; i++) {
255 int pos = (int) strlen(argbuf);
256 if (pos + 20 > (int)sizeof(argbuf)) {
257 os::snprintf_checked(argbuf + pos, sizeof(argbuf) - pos, "...");
258 break;
259 }
260 if (i > 0) argbuf[pos++] = ',';
261 os::snprintf_checked(argbuf+pos, sizeof(argbuf) - pos, "%d", arg_index(i));
262 }
263 st->print_cr(" argument indexes: {%s}", argbuf);
264 }
265 if (_bsm.not_null()) {
266 st->print(" resolved BSM: "); _bsm->print_on(st);
267 }
268
269 // How the array of resolved arguments is printed depends highly
270 // on how BootstrapInfo::resolve_args structures the array based on
271 // the use_BSCI setting.
272 if (_arg_values.not_null()) {
273 // Find the static arguments within the first element of _arg_values.
274 oop static_args = _arg_values();
275 if (!static_args->is_array()) {
276 assert(_argc == 1, "Invalid BSM _arg_values for non-array");
277 st->print(" resolved arg[0]: "); static_args->print_on(st);
278 } else if (static_args->is_refArray()) {
279 refArrayOop static_args_array = oop_cast<refArrayOop>(static_args);
280 int lines = 0;
281 for (int i = 0; i < _argc; i++) {
282 oop x = static_args_array->obj_at(i);
283 if (x != nullptr) {
284 if (++lines > 6) {
285 st->print_cr(" resolved arg[%d]: ...", i);
286 break;
287 }
288 st->print(" resolved arg[%d]: ", i); x->print_on(st);
289 }
290 }
291 } else if (static_args->is_typeArray()) {
292 typeArrayOop tmp_array = (typeArrayOop) static_args;
293 assert(tmp_array->length() == 2, "Invalid BSM _arg_values type array");
294 st->print_cr(" resolved arg[0]: %d", tmp_array->int_at(0));
295 st->print_cr(" resolved arg[1]: %d", tmp_array->int_at(1));
296 } else if (static_args->is_flatArray()) {
297 ShouldNotReachHere();
298 }
299 }
300 }
|