1 /* 2 * Copyright (c) 2023, 2024, 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 "oops/method.hpp" 28 #include "oops/resolvedMethodEntry.hpp" 29 30 bool ResolvedMethodEntry::check_no_old_or_obsolete_entry() { 31 // return false if m refers to a non-deleted old or obsolete method 32 if (_method != nullptr) { 33 assert(_method->is_valid() && _method->is_method(), "m is a valid method"); 34 return !_method->is_old() && !_method->is_obsolete(); // old is always set for old and obsolete 35 } else { 36 return true; 37 } 38 } 39 40 void ResolvedMethodEntry::reset_entry() { 41 if (has_resolved_references_index()) { 42 u2 saved_resolved_references_index = _entry_specific._resolved_references_index; 43 u2 saved_cpool_index = _cpool_index; 44 memset(this, 0, sizeof(*this)); 45 set_resolved_references_index(saved_resolved_references_index); 46 _cpool_index = saved_cpool_index; 47 } else { 48 u2 saved_cpool_index = _cpool_index; 49 memset(this, 0, sizeof(*this)); 50 _cpool_index = saved_cpool_index; 51 } 52 } 53 54 #if INCLUDE_CDS 55 void ResolvedMethodEntry::remove_unshareable_info() { 56 reset_entry(); 57 } 58 59 void ResolvedMethodEntry::mark_and_relocate(ConstantPool* src_cp) { 60 if (_method == nullptr) { 61 assert(bytecode2() == Bytecodes::_invokevirtual, ""); 62 } else { 63 ArchiveBuilder::current()->mark_and_relocate_to_buffered_addr(&_method); 64 } 65 if (bytecode1() == Bytecodes::_invokeinterface) { 66 ArchiveBuilder::current()->mark_and_relocate_to_buffered_addr(&_entry_specific._interface_klass); 67 } 68 #if 0 69 // OLD CODE ... some of it may need to be salvaged. 70 Bytecodes::Code invoke_code = bytecode_1(); 71 if (invoke_code != (Bytecodes::Code)0) { 72 Metadata* f1 = f1_ord(); 73 if (f1 != nullptr) { 74 ArchiveBuilder::current()->mark_and_relocate_to_buffered_addr(&_f1); 75 switch (invoke_code) { 76 case Bytecodes::_invokeinterface: 77 assert(0, "not implemented"); 78 //assert(f1->is_klass(), ""); 79 //ArchiveBuilder::current()->mark_and_relocate_to_buffered_addr(&_f2); // f2 is interface method 80 return false; 81 case Bytecodes::_invokestatic: 82 // For safety, we support invokestatic only for invoking methods in MethodHandle. 83 // FIXME -- further restrict it to linkToStatic(), etc? 84 assert(bytecode_2() == (Bytecodes::Code)0, "must be"); 85 assert(f1->is_method(), ""); 86 assert(f1_as_method()->method_holder()->name()->equals("java/lang/invoke/MethodHandle") || 87 f1_as_method()->method_holder()->name()->equals("java/lang/invoke/MethodHandleNatives"), "sanity"); 88 return true; 89 case Bytecodes::_invokespecial: 90 assert(f1->is_method(), "must be"); 91 // Also need to work on bytecode_2() below. 92 break; 93 case Bytecodes::_invokehandle: 94 assert(bytecode_2() == (Bytecodes::Code)0, "must be"); 95 assert(f1->is_method(), ""); 96 return true; 97 default: 98 ShouldNotReachHere(); 99 break; 100 } 101 } 102 } 103 104 // TODO test case: can invokespecial and invokevirtual share the same CP? 105 invoke_code = bytecode_2(); 106 if (invoke_code != (Bytecodes::Code)0) { 107 assert(invoke_code == Bytecodes::_invokevirtual, "must be"); 108 if (is_vfinal()) { 109 // f2 is vfinal method 110 ArchiveBuilder::current()->mark_and_relocate_to_buffered_addr(&_f2); // f2 is final method 111 } else { 112 // f2 is vtable index, no need to mark 113 if (DynamicDumpSharedSpaces) { 114 // InstanceKlass::methods() is has been resorted, so we need to 115 // update the vtable_index. 116 int holder_index = src_cp->uncached_klass_ref_index_at(constant_pool_index()); 117 Klass* src_klass = src_cp->resolved_klass_at(holder_index); 118 Method* src_m = src_klass->method_at_vtable(f2_as_index()); 119 if (!ArchiveBuilder::current()->is_in_mapped_static_archive(src_m->method_holder()) && 120 !ArchiveBuilder::current()->is_in_mapped_static_archive(src_m)) { 121 Klass* buffered_klass = ArchiveBuilder::current()->get_buffered_addr(src_klass); 122 Method* buffered_m = ArchiveBuilder::current()->get_buffered_addr(src_m); 123 int vtable_index; 124 if (src_m->method_holder()->is_interface()) { // default or miranda method 125 assert(src_m->vtable_index() < 0, "must be"); 126 assert(buffered_klass->is_instance_klass(), "must be"); 127 vtable_index = InstanceKlass::cast(buffered_klass)->vtable_index_of_interface_method(buffered_m); 128 assert(vtable_index >= 0, "must be"); 129 } else { 130 vtable_index = buffered_m->vtable_index(); 131 assert(vtable_index >= 0, "must be"); 132 } 133 if (_f2 != vtable_index) { 134 log_trace(cds, resolve)("vtable_index changed %d => %d", (int)_f2, vtable_index); 135 _f2 = vtable_index; 136 } 137 } 138 } 139 } 140 } 141 142 #endif 143 } 144 #endif 145 146 void ResolvedMethodEntry::print_on(outputStream* st) const { 147 st->print_cr("Method Entry:"); 148 149 if (method() != nullptr) { 150 st->print_cr(" - Method: " INTPTR_FORMAT " %s", p2i(method()), method()->external_name()); 151 } else { 152 st->print_cr("- Method: null"); 153 } 154 // Some fields are mutually exclusive and are only used by certain invoke codes 155 if (bytecode1() == Bytecodes::_invokeinterface && interface_klass() != nullptr) { 156 st->print_cr(" - Klass: " INTPTR_FORMAT " %s", p2i(interface_klass()), interface_klass()->external_name()); 157 } else { 158 st->print_cr("- Klass: null"); 159 } 160 if (bytecode1() == Bytecodes::_invokehandle) { 161 st->print_cr(" - Resolved References Index: %d", resolved_references_index()); 162 } else { 163 st->print_cr(" - Resolved References Index: none"); 164 } 165 if (bytecode2() == Bytecodes::_invokevirtual) { 166 #ifdef ASSERT 167 if (_has_table_index) { 168 st->print_cr(" - Table Index: %d", table_index()); 169 } 170 #else 171 st->print_cr(" - Table Index: %d", table_index()); 172 #endif 173 } else { 174 st->print_cr(" - Table Index: none"); 175 } 176 st->print_cr(" - CP Index: %d", constant_pool_index()); 177 st->print_cr(" - TOS: %s", type2name(as_BasicType((TosState)tos_state()))); 178 st->print_cr(" - Number of Parameters: %d", number_of_parameters()); 179 st->print_cr(" - Is Virtual Final: %d", is_vfinal()); 180 st->print_cr(" - Is Final: %d", is_final()); 181 st->print_cr(" - Is Forced Virtual: %d", is_forced_virtual()); 182 st->print_cr(" - Has Appendix: %d", has_appendix()); 183 st->print_cr(" - Has Local Signature: %d", has_local_signature()); 184 st->print_cr(" - Bytecode 1: %s", Bytecodes::name((Bytecodes::Code)bytecode1())); 185 st->print_cr(" - Bytecode 2: %s", Bytecodes::name((Bytecodes::Code)bytecode2())); 186 }