annotate src/share/vm/prims/resolvedMethodTable.cpp @ 13526:f5dd157e3889

8186439: [MVT] ClassFileParser should ignore JVM_ACC_VALUE for class file version < 53.1 Reviewed-by: dsimms
author thartmann
date Mon, 21 Aug 2017 12:26:21 +0200
parents
children
rev   line source
coleenp@13112 1 /*
coleenp@13112 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
coleenp@13112 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
coleenp@13112 4 *
coleenp@13112 5 * This code is free software; you can redistribute it and/or modify it
coleenp@13112 6 * under the terms of the GNU General Public License version 2 only, as
coleenp@13112 7 * published by the Free Software Foundation.
coleenp@13112 8 *
coleenp@13112 9 * This code is distributed in the hope that it will be useful, but WITHOUT
coleenp@13112 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
coleenp@13112 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
coleenp@13112 12 * version 2 for more details (a copy is included in the LICENSE file that
coleenp@13112 13 * accompanied this code).
coleenp@13112 14 *
coleenp@13112 15 * You should have received a copy of the GNU General Public License version
coleenp@13112 16 * 2 along with this work; if not, write to the Free Software Foundation,
coleenp@13112 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
coleenp@13112 18 *
coleenp@13112 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
coleenp@13112 20 * or visit www.oracle.com if you need additional information or have any
coleenp@13112 21 * questions.
coleenp@13112 22 *
coleenp@13112 23 */
coleenp@13112 24
coleenp@13112 25 #include "precompiled.hpp"
coleenp@13112 26 #include "gc/shared/gcLocker.hpp"
coleenp@13112 27 #include "memory/allocation.hpp"
coleenp@13112 28 #include "oops/oop.inline.hpp"
coleenp@13112 29 #include "oops/method.hpp"
coleenp@13112 30 #include "oops/symbol.hpp"
coleenp@13112 31 #include "prims/resolvedMethodTable.hpp"
coleenp@13112 32 #include "runtime/handles.inline.hpp"
coleenp@13112 33 #include "runtime/mutexLocker.hpp"
coleenp@13112 34 #include "utilities/hashtable.inline.hpp"
coleenp@13112 35 #include "utilities/macros.hpp"
coleenp@13112 36 #if INCLUDE_ALL_GCS
coleenp@13112 37 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
coleenp@13112 38 #endif
coleenp@13112 39
coleenp@13112 40
coleenp@13112 41 ResolvedMethodTable::ResolvedMethodTable()
coleenp@13112 42 : Hashtable<oop, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { }
coleenp@13112 43
coleenp@13112 44 oop ResolvedMethodTable::lookup(int index, unsigned int hash, Method* method) {
coleenp@13112 45 for (ResolvedMethodEntry* p = bucket(index); p != NULL; p = p->next()) {
coleenp@13112 46 if (p->hash() == hash) {
coleenp@13112 47 oop target = p->literal();
coleenp@13112 48 // The method is in the table as a target already
coleenp@13112 49 if (java_lang_invoke_ResolvedMethodName::vmtarget(target) == method) {
coleenp@13112 50 ResourceMark rm;
coleenp@13112 51 log_debug(membername, table) ("ResolvedMethod entry found for %s index %d",
coleenp@13112 52 method->name_and_sig_as_C_string(), index);
coleenp@13112 53 return target;
coleenp@13112 54 }
coleenp@13112 55 }
coleenp@13112 56 }
coleenp@13112 57 return NULL;
coleenp@13112 58 }
coleenp@13112 59
coleenp@13112 60 unsigned int ResolvedMethodTable::compute_hash(Method* method) {
coleenp@13112 61 unsigned int name_hash = method->name()->identity_hash();
coleenp@13112 62 unsigned int signature_hash = method->signature()->identity_hash();
coleenp@13112 63 return name_hash ^ signature_hash;
coleenp@13112 64 }
coleenp@13112 65
coleenp@13112 66
coleenp@13112 67 oop ResolvedMethodTable::lookup(Method* method) {
coleenp@13112 68 unsigned int hash = compute_hash(method);
coleenp@13112 69 int index = hash_to_index(hash);
coleenp@13112 70 return lookup(index, hash, method);
coleenp@13112 71 }
coleenp@13112 72
coleenp@13112 73 // Tell the GC that this oop was looked up in the table
coleenp@13112 74 static void ensure_oop_alive(oop mname) {
coleenp@13112 75 // A lookup in the ResolvedMethodTable could return an object that was previously
coleenp@13112 76 // considered dead. The SATB part of G1 needs to get notified about this
coleenp@13112 77 // potential resurrection, otherwise the marking might not find the object.
coleenp@13112 78 #if INCLUDE_ALL_GCS
coleenp@13112 79 if (UseG1GC && mname != NULL) {
coleenp@13112 80 G1SATBCardTableModRefBS::enqueue(mname);
coleenp@13112 81 }
coleenp@13112 82 #endif
coleenp@13112 83 }
coleenp@13112 84
coleenp@13112 85 oop ResolvedMethodTable::basic_add(Method* method, oop rmethod_name) {
coleenp@13112 86 assert_locked_or_safepoint(ResolvedMethodTable_lock);
coleenp@13112 87
coleenp@13112 88 unsigned int hash = compute_hash(method);
coleenp@13112 89 int index = hash_to_index(hash);
coleenp@13112 90
coleenp@13112 91 // One was added while aquiring the lock
coleenp@13112 92 oop entry = lookup(index, hash, method);
coleenp@13112 93 if (entry != NULL) {
coleenp@13112 94 ensure_oop_alive(entry);
coleenp@13112 95 return entry;
coleenp@13112 96 }
coleenp@13112 97
coleenp@13112 98 ResolvedMethodEntry* p = (ResolvedMethodEntry*) Hashtable<oop, mtClass>::new_entry(hash, rmethod_name);
coleenp@13112 99 Hashtable<oop, mtClass>::add_entry(index, p);
coleenp@13112 100 ResourceMark rm;
coleenp@13112 101 log_debug(membername, table) ("ResolvedMethod entry added for %s index %d",
coleenp@13112 102 method->name_and_sig_as_C_string(), index);
coleenp@13112 103 return p->literal();
coleenp@13112 104 }
coleenp@13112 105
coleenp@13112 106 ResolvedMethodTable* ResolvedMethodTable::_the_table = NULL;
coleenp@13112 107
coleenp@13112 108 oop ResolvedMethodTable::find_method(Method* method) {
coleenp@13112 109 oop entry = _the_table->lookup(method);
coleenp@13112 110 ensure_oop_alive(entry);
coleenp@13112 111 return entry;
coleenp@13112 112 }
coleenp@13112 113
coleenp@13112 114 oop ResolvedMethodTable::add_method(Handle resolved_method_name) {
coleenp@13112 115 MutexLocker ml(ResolvedMethodTable_lock);
coleenp@13112 116 DEBUG_ONLY(NoSafepointVerifier nsv);
coleenp@13112 117
coleenp@13112 118 // Check if method has been redefined while taking out ResolvedMethodTable_lock, if so
coleenp@13112 119 // use new method.
coleenp@13112 120 Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(resolved_method_name());
coleenp@13112 121 assert(method->is_method(), "must be method");
coleenp@13112 122 if (method->is_old()) {
coleenp@13112 123 // Replace method with redefined version
coleenp@13112 124 InstanceKlass* holder = method->method_holder();
coleenp@13112 125 method = holder->method_with_idnum(method->method_idnum());
coleenp@13112 126 java_lang_invoke_ResolvedMethodName::set_vmtarget(resolved_method_name(), method);
coleenp@13112 127 }
coleenp@13112 128 // Set flag in class to indicate this InstanceKlass has entries in the table
coleenp@13112 129 // to avoid walking table during redefinition if none of the redefined classes
coleenp@13112 130 // have any membernames in the table.
coleenp@13112 131 method->method_holder()->set_has_resolved_methods();
coleenp@13112 132
coleenp@13112 133 return _the_table->basic_add(method, resolved_method_name());
coleenp@13112 134 }
coleenp@13112 135
coleenp@13112 136 // Removing entries
coleenp@13112 137 int ResolvedMethodTable::_oops_removed = 0;
coleenp@13112 138 int ResolvedMethodTable::_oops_counted = 0;
coleenp@13112 139
coleenp@13112 140 // Serially invoke removed unused oops from the table.
coleenp@13112 141 // This is done late during GC.
coleenp@13112 142 void ResolvedMethodTable::unlink(BoolObjectClosure* is_alive) {
coleenp@13112 143 _oops_removed = 0;
coleenp@13112 144 _oops_counted = 0;
coleenp@13112 145 for (int i = 0; i < _the_table->table_size(); ++i) {
coleenp@13112 146 ResolvedMethodEntry** p = _the_table->bucket_addr(i);
coleenp@13112 147 ResolvedMethodEntry* entry = _the_table->bucket(i);
coleenp@13112 148 while (entry != NULL) {
coleenp@13112 149 _oops_counted++;
coleenp@13112 150 if (is_alive->do_object_b(entry->literal())) {
coleenp@13112 151 p = entry->next_addr();
coleenp@13112 152 } else {
coleenp@13112 153 _oops_removed++;
coleenp@13112 154 if (log_is_enabled(Debug, membername, table)) {
coleenp@13112 155 Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(entry->literal());
coleenp@13112 156 ResourceMark rm;
coleenp@13112 157 log_debug(membername, table) ("ResolvedMethod entry removed for %s index %d",
coleenp@13112 158 m->name_and_sig_as_C_string(), i);
coleenp@13112 159 }
coleenp@13112 160 *p = entry->next();
coleenp@13112 161 _the_table->free_entry(entry);
coleenp@13112 162 }
coleenp@13112 163 // get next entry
coleenp@13112 164 entry = (ResolvedMethodEntry*)HashtableEntry<oop, mtClass>::make_ptr(*p);
coleenp@13112 165 }
coleenp@13112 166 }
coleenp@13112 167 log_debug(membername, table) ("ResolvedMethod entries counted %d removed %d",
coleenp@13112 168 _oops_counted, _oops_removed);
coleenp@13112 169 }
coleenp@13112 170
coleenp@13112 171 // Serially invoke "f->do_oop" on the locations of all oops in the table.
coleenp@13112 172 void ResolvedMethodTable::oops_do(OopClosure* f) {
coleenp@13112 173 for (int i = 0; i < _the_table->table_size(); ++i) {
coleenp@13112 174 ResolvedMethodEntry* entry = _the_table->bucket(i);
coleenp@13112 175 while (entry != NULL) {
coleenp@13112 176 f->do_oop(entry->literal_addr());
coleenp@13112 177 entry = entry->next();
coleenp@13112 178 }
coleenp@13112 179 }
coleenp@13112 180 }
coleenp@13112 181
coleenp@13112 182 #ifndef PRODUCT
coleenp@13112 183 void ResolvedMethodTable::print() {
coleenp@13112 184 for (int i = 0; i < table_size(); ++i) {
coleenp@13112 185 ResolvedMethodEntry* entry = bucket(i);
coleenp@13112 186 while (entry != NULL) {
coleenp@13112 187 tty->print("%d : ", i);
coleenp@13112 188 oop rmethod_name = entry->literal();
coleenp@13112 189 rmethod_name->print();
coleenp@13112 190 Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(rmethod_name);
coleenp@13112 191 m->print();
coleenp@13112 192 entry = entry->next();
coleenp@13112 193 }
coleenp@13112 194 }
coleenp@13112 195 }
coleenp@13112 196 #endif // PRODUCT
coleenp@13112 197
coleenp@13112 198 #if INCLUDE_JVMTI
coleenp@13112 199 // It is called at safepoint only for RedefineClasses
coleenp@13112 200 void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
coleenp@13112 201 assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
coleenp@13112 202 // For each entry in RMT, change to new method
coleenp@13112 203 for (int i = 0; i < _the_table->table_size(); ++i) {
coleenp@13112 204 ResolvedMethodEntry* entry = _the_table->bucket(i);
coleenp@13112 205 while (entry != NULL) {
coleenp@13112 206
coleenp@13112 207 oop mem_name = entry->literal();
coleenp@13112 208 Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
coleenp@13112 209
coleenp@13112 210 if (old_method->is_old()) {
coleenp@13112 211
coleenp@13112 212 if (old_method->is_deleted()) {
coleenp@13112 213 // leave deleted method in ResolvedMethod for now (this is a bug that we don't mark
coleenp@13112 214 // these on_stack)
coleenp@13112 215 continue;
coleenp@13112 216 }
coleenp@13112 217
coleenp@13112 218 InstanceKlass* holder = old_method->method_holder();
coleenp@13112 219 Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
coleenp@13112 220 assert(holder == new_method->method_holder(), "call after swapping redefined guts");
coleenp@13112 221 assert(new_method != NULL, "method_with_idnum() should not be NULL");
coleenp@13112 222 assert(old_method != new_method, "sanity check");
coleenp@13112 223
coleenp@13112 224 java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method);
coleenp@13112 225
coleenp@13112 226 ResourceMark rm;
coleenp@13112 227 if (!(*trace_name_printed)) {
coleenp@13112 228 log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
coleenp@13112 229 *trace_name_printed = true;
coleenp@13112 230 }
coleenp@13112 231 log_debug(redefine, class, update, constantpool)
coleenp@13112 232 ("ResolvedMethod method update: %s(%s)",
coleenp@13112 233 new_method->name()->as_C_string(), new_method->signature()->as_C_string());
coleenp@13112 234 }
coleenp@13112 235 entry = entry->next();
coleenp@13112 236 }
coleenp@13112 237 }
coleenp@13112 238 }
coleenp@13112 239 #endif // INCLUDE_JVMTI