mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8046246: the constantPoolCacheOopDesc::adjust_method_entries() used in RedefineClasses does not scale
Optimize the adjust_method_entries functions by using the orig_method_idnum() function Reviewed-by: coleenp, dcubed
This commit is contained in:
parent
07a6ab00bc
commit
942d1f7f32
11 changed files with 154 additions and 132 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1091,6 +1091,7 @@ static void merge_in_new_methods(InstanceKlass* klass,
|
|||
}
|
||||
// update idnum for new location
|
||||
merged_methods->at(i)->set_method_idnum(i);
|
||||
merged_methods->at(i)->set_orig_method_idnum(i);
|
||||
}
|
||||
|
||||
// Verify correct order
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -215,6 +215,7 @@ private:
|
|||
u2 _max_stack; // Maximum number of entries on the expression stack
|
||||
u2 _max_locals; // Number of local variables used by this method
|
||||
u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words
|
||||
u2 _orig_method_idnum; // Original unique identification number for the method
|
||||
|
||||
// Constructor
|
||||
ConstMethod(int byte_code_size,
|
||||
|
@ -473,6 +474,9 @@ public:
|
|||
u2 method_idnum() const { return _method_idnum; }
|
||||
void set_method_idnum(u2 idnum) { _method_idnum = idnum; }
|
||||
|
||||
u2 orig_method_idnum() const { return _orig_method_idnum; }
|
||||
void set_orig_method_idnum(u2 idnum) { _orig_method_idnum = idnum; }
|
||||
|
||||
// max stack
|
||||
int max_stack() const { return _max_stack; }
|
||||
void set_max_stack(int size) { _max_stack = size; }
|
||||
|
|
|
@ -455,7 +455,6 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
|||
new_method->name()->as_C_string(),
|
||||
new_method->signature()->as_C_string()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -483,7 +482,6 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
|||
new_method->name()->as_C_string(),
|
||||
new_method->signature()->as_C_string()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -510,36 +508,33 @@ bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
|
|||
(!f1_as_method()->is_old() && !f1_as_method()->is_obsolete())));
|
||||
}
|
||||
|
||||
bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
|
||||
Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) {
|
||||
if (!is_method_entry()) {
|
||||
// not a method entry so not interesting by default
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Method* m = NULL;
|
||||
if (is_vfinal()) {
|
||||
// virtual and final so _f2 contains method ptr instead of vtable index
|
||||
m = f2_as_vfinal_method();
|
||||
} else if (is_f1_null()) {
|
||||
// NULL _f1 means this is a virtual entry so also not interesting
|
||||
return false;
|
||||
return NULL;
|
||||
} else {
|
||||
if (!(_f1->is_method())) {
|
||||
// _f1 can also contain a Klass* for an interface
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
m = f1_as_method();
|
||||
}
|
||||
|
||||
assert(m != NULL && m->is_method(), "sanity check");
|
||||
if (m == NULL || !m->is_method() || (k != NULL && m->method_holder() != k)) {
|
||||
// robustness for above sanity checks or method is not in
|
||||
// the interesting class
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// the method is in the interesting class so the entry is interesting
|
||||
return true;
|
||||
return m;
|
||||
}
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
|
@ -616,7 +611,7 @@ void ConstantPoolCache::initialize(const intArray& inverse_index_map,
|
|||
// If any entry of this ConstantPoolCache points to any of
|
||||
// old_methods, replace it with the corresponding new_method.
|
||||
void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||
int methods_length, bool * trace_name_printed) {
|
||||
int methods_length, bool * trace_name_printed) {
|
||||
|
||||
if (methods_length == 0) {
|
||||
// nothing to do if there are no methods
|
||||
|
@ -627,7 +622,7 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new
|
|||
Klass* old_holder = old_methods[0]->method_holder();
|
||||
|
||||
for (int i = 0; i < length(); i++) {
|
||||
if (!entry_at(i)->is_interesting_method_entry(old_holder)) {
|
||||
if (entry_at(i)->get_interesting_method_entry(old_holder) == NULL) {
|
||||
// skip uninteresting methods
|
||||
continue;
|
||||
}
|
||||
|
@ -651,10 +646,33 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new
|
|||
}
|
||||
}
|
||||
|
||||
// If any entry of this ConstantPoolCache points to any of
|
||||
// old_methods, replace it with the corresponding new_method.
|
||||
void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
|
||||
for (int i = 0; i < length(); i++) {
|
||||
ConstantPoolCacheEntry* entry = entry_at(i);
|
||||
Method* old_method = entry->get_interesting_method_entry(holder);
|
||||
if (old_method == NULL || !old_method->is_old()) {
|
||||
continue; // skip uninteresting entries
|
||||
}
|
||||
if (old_method->is_deleted()) {
|
||||
// clean up entries with deleted methods
|
||||
entry->initialize_entry(entry->constant_pool_index());
|
||||
continue;
|
||||
}
|
||||
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != new_method, "sanity check");
|
||||
|
||||
entry_at(i)->adjust_method_entry(old_method, new_method, trace_name_printed);
|
||||
}
|
||||
}
|
||||
|
||||
// the constant pool cache should never contain old or obsolete methods
|
||||
bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
|
||||
for (int i = 1; i < length(); i++) {
|
||||
if (entry_at(i)->is_interesting_method_entry(NULL) &&
|
||||
if (entry_at(i)->get_interesting_method_entry(NULL) != NULL &&
|
||||
!entry_at(i)->check_no_old_or_obsolete_entries()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -664,7 +682,7 @@ bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
|
|||
|
||||
void ConstantPoolCache::dump_cache() {
|
||||
for (int i = 1; i < length(); i++) {
|
||||
if (entry_at(i)->is_interesting_method_entry(NULL)) {
|
||||
if (entry_at(i)->get_interesting_method_entry(NULL) != NULL) {
|
||||
entry_at(i)->print(tty, i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -379,9 +379,9 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
|||
// printed the klass name so that other routines in the adjust_*
|
||||
// group don't print the klass name.
|
||||
bool adjust_method_entry(Method* old_method, Method* new_method,
|
||||
bool * trace_name_printed);
|
||||
bool* trace_name_printed);
|
||||
bool check_no_old_or_obsolete_entries();
|
||||
bool is_interesting_method_entry(Klass* k);
|
||||
Method* get_interesting_method_entry(Klass* k);
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
// Debugging & Printing
|
||||
|
@ -478,7 +478,8 @@ class ConstantPoolCache: public MetaspaceObj {
|
|||
// printed the klass name so that other routines in the adjust_*
|
||||
// group don't print the klass name.
|
||||
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||
int methods_length, bool * trace_name_printed);
|
||||
int methods_length, bool* trace_name_printed);
|
||||
void adjust_method_entries(InstanceKlass* holder, bool* trace_name_printed);
|
||||
bool check_no_old_or_obsolete_entries();
|
||||
void dump_cache();
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
|
|
@ -2793,30 +2793,33 @@ Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) {
|
|||
// not yet in the vtable due to concurrent subclass define and superinterface
|
||||
// redefinition
|
||||
// Note: those in the vtable, should have been updated via adjust_method_entries
|
||||
void InstanceKlass::adjust_default_methods(Method** old_methods, Method** new_methods,
|
||||
int methods_length, bool* trace_name_printed) {
|
||||
void InstanceKlass::adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed) {
|
||||
// search the default_methods for uses of either obsolete or EMCP methods
|
||||
if (default_methods() != NULL) {
|
||||
for (int j = 0; j < methods_length; j++) {
|
||||
Method* old_method = old_methods[j];
|
||||
Method* new_method = new_methods[j];
|
||||
for (int index = 0; index < default_methods()->length(); index ++) {
|
||||
Method* old_method = default_methods()->at(index);
|
||||
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
|
||||
continue; // skip uninteresting entries
|
||||
}
|
||||
assert(!old_method->is_deleted(), "default methods may not be deleted");
|
||||
|
||||
for (int index = 0; index < default_methods()->length(); index ++) {
|
||||
if (default_methods()->at(index) == old_method) {
|
||||
default_methods()->at_put(index, new_method);
|
||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
||||
if (!(*trace_name_printed)) {
|
||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||
RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s",
|
||||
external_name(),
|
||||
old_method->method_holder()->external_name()));
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
RC_TRACE(0x00100000, ("default method update: %s(%s) ",
|
||||
new_method->name()->as_C_string(),
|
||||
new_method->signature()->as_C_string()));
|
||||
}
|
||||
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != new_method, "sanity check");
|
||||
|
||||
default_methods()->at_put(index, new_method);
|
||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
||||
if (!(*trace_name_printed)) {
|
||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||
RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s",
|
||||
external_name(),
|
||||
old_method->method_holder()->external_name()));
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
RC_TRACE(0x00100000, ("default method update: %s(%s) ",
|
||||
new_method->name()->as_C_string(),
|
||||
new_method->signature()->as_C_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -937,8 +937,7 @@ class InstanceKlass: public Klass {
|
|||
Method* method_at_itable(Klass* holder, int index, TRAPS);
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
void adjust_default_methods(Method** old_methods, Method** new_methods,
|
||||
int methods_length, bool* trace_name_printed);
|
||||
void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed);
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
// Garbage collection
|
||||
|
|
|
@ -864,44 +864,43 @@ bool klassVtable::adjust_default_method(int vtable_index, Method* old_method, Me
|
|||
}
|
||||
return updated;
|
||||
}
|
||||
void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||
int methods_length, bool * trace_name_printed) {
|
||||
// search the vtable for uses of either obsolete or EMCP methods
|
||||
for (int j = 0; j < methods_length; j++) {
|
||||
Method* old_method = old_methods[j];
|
||||
Method* new_method = new_methods[j];
|
||||
|
||||
// In the vast majority of cases we could get the vtable index
|
||||
// by using: old_method->vtable_index()
|
||||
// However, there are rare cases, eg. sun.awt.X11.XDecoratedPeer.getX()
|
||||
// in sun.awt.X11.XFramePeer where methods occur more than once in the
|
||||
// vtable, so, alas, we must do an exhaustive search.
|
||||
for (int index = 0; index < length(); index++) {
|
||||
if (unchecked_method_at(index) == old_method) {
|
||||
put_method_at(new_method, index);
|
||||
// For default methods, need to update the _default_methods array
|
||||
// which can only have one method entry for a given signature
|
||||
bool updated_default = false;
|
||||
if (old_method->is_default_method()) {
|
||||
updated_default = adjust_default_method(index, old_method, new_method);
|
||||
}
|
||||
// search the vtable for uses of either obsolete or EMCP methods
|
||||
void klassVtable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
|
||||
int prn_enabled = 0;
|
||||
for (int index = 0; index < length(); index++) {
|
||||
Method* old_method = unchecked_method_at(index);
|
||||
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
|
||||
continue; // skip uninteresting entries
|
||||
}
|
||||
assert(!old_method->is_deleted(), "vtable methods may not be deleted");
|
||||
|
||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
||||
if (!(*trace_name_printed)) {
|
||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||
RC_TRACE_MESG(("adjust: klassname=%s for methods from name=%s",
|
||||
klass()->external_name(),
|
||||
old_method->method_holder()->external_name()));
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
// RC_TRACE macro has an embedded ResourceMark
|
||||
RC_TRACE(0x00100000, ("vtable method update: %s(%s), updated default = %s",
|
||||
new_method->name()->as_C_string(),
|
||||
new_method->signature()->as_C_string(),
|
||||
updated_default ? "true" : "false"));
|
||||
}
|
||||
// cannot 'break' here; see for-loop comment above.
|
||||
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != new_method, "sanity check");
|
||||
|
||||
put_method_at(new_method, index);
|
||||
// For default methods, need to update the _default_methods array
|
||||
// which can only have one method entry for a given signature
|
||||
bool updated_default = false;
|
||||
if (old_method->is_default_method()) {
|
||||
updated_default = adjust_default_method(index, old_method, new_method);
|
||||
}
|
||||
|
||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
||||
if (!(*trace_name_printed)) {
|
||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||
RC_TRACE_MESG(("adjust: klassname=%s for methods from name=%s",
|
||||
klass()->external_name(),
|
||||
old_method->method_holder()->external_name()));
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
// RC_TRACE macro has an embedded ResourceMark
|
||||
RC_TRACE(0x00100000, ("vtable method update: %s(%s), updated default = %s",
|
||||
new_method->name()->as_C_string(),
|
||||
new_method->signature()->as_C_string(),
|
||||
updated_default ? "true" : "false"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1194,37 +1193,35 @@ void klassItable::initialize_with_method(Method* m) {
|
|||
}
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
void klassItable::adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||
int methods_length, bool * trace_name_printed) {
|
||||
// search the itable for uses of either obsolete or EMCP methods
|
||||
for (int j = 0; j < methods_length; j++) {
|
||||
Method* old_method = old_methods[j];
|
||||
Method* new_method = new_methods[j];
|
||||
itableMethodEntry* ime = method_entry(0);
|
||||
// search the itable for uses of either obsolete or EMCP methods
|
||||
void klassItable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) {
|
||||
|
||||
// The itable can describe more than one interface and the same
|
||||
// method signature can be specified by more than one interface.
|
||||
// This means we have to do an exhaustive search to find all the
|
||||
// old_method references.
|
||||
for (int i = 0; i < _size_method_table; i++) {
|
||||
if (ime->method() == old_method) {
|
||||
ime->initialize(new_method);
|
||||
itableMethodEntry* ime = method_entry(0);
|
||||
for (int i = 0; i < _size_method_table; i++, ime++) {
|
||||
Method* old_method = ime->method();
|
||||
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
|
||||
continue; // skip uninteresting entries
|
||||
}
|
||||
assert(!old_method->is_deleted(), "itable methods may not be deleted");
|
||||
|
||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
||||
if (!(*trace_name_printed)) {
|
||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||
RC_TRACE_MESG(("adjust: name=%s",
|
||||
old_method->method_holder()->external_name()));
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
// RC_TRACE macro has an embedded ResourceMark
|
||||
RC_TRACE(0x00200000, ("itable method update: %s(%s)",
|
||||
new_method->name()->as_C_string(),
|
||||
new_method->signature()->as_C_string()));
|
||||
}
|
||||
// cannot 'break' here; see for-loop comment above.
|
||||
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
|
||||
|
||||
assert(new_method != NULL, "method_with_idnum() should not be NULL");
|
||||
assert(old_method != new_method, "sanity check");
|
||||
|
||||
ime->initialize(new_method);
|
||||
|
||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
||||
if (!(*trace_name_printed)) {
|
||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||
RC_TRACE_MESG(("adjust: name=%s",
|
||||
old_method->method_holder()->external_name()));
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
ime++;
|
||||
// RC_TRACE macro has an embedded ResourceMark
|
||||
RC_TRACE(0x00200000, ("itable method update: %s(%s)",
|
||||
new_method->name()->as_C_string(),
|
||||
new_method->signature()->as_C_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -98,8 +98,7 @@ class klassVtable : public ResourceObj {
|
|||
// printed the klass name so that other routines in the adjust_*
|
||||
// group don't print the klass name.
|
||||
bool adjust_default_method(int vtable_index, Method* old_method, Method* new_method);
|
||||
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||
int methods_length, bool * trace_name_printed);
|
||||
void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed);
|
||||
bool check_no_old_or_obsolete_entries();
|
||||
void dump_vtable();
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
@ -288,8 +287,7 @@ class klassItable : public ResourceObj {
|
|||
// trace_name_printed is set to true if the current call has
|
||||
// printed the klass name so that other routines in the adjust_*
|
||||
// group don't print the klass name.
|
||||
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||
int methods_length, bool * trace_name_printed);
|
||||
void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed);
|
||||
bool check_no_old_or_obsolete_entries();
|
||||
void dump_itable();
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
|
|
@ -1450,6 +1450,7 @@ void Method::sort_methods(Array<Method*>* methods, bool idempotent, bool set_idn
|
|||
for (int i = 0; i < length; i++) {
|
||||
Method* m = methods->at(i);
|
||||
m->set_method_idnum(i);
|
||||
m->set_orig_method_idnum(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -233,6 +233,9 @@ class Method : public Metadata {
|
|||
u2 method_idnum() const { return constMethod()->method_idnum(); }
|
||||
void set_method_idnum(u2 idnum) { constMethod()->set_method_idnum(idnum); }
|
||||
|
||||
u2 orig_method_idnum() const { return constMethod()->orig_method_idnum(); }
|
||||
void set_orig_method_idnum(u2 idnum) { constMethod()->set_orig_method_idnum(idnum); }
|
||||
|
||||
// code size
|
||||
int code_size() const { return constMethod()->code_size(); }
|
||||
|
||||
|
|
|
@ -782,9 +782,13 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
|||
Method* idnum_owner = scratch_class->method_with_idnum(old_num);
|
||||
if (idnum_owner != NULL) {
|
||||
// There is already a method assigned this idnum -- switch them
|
||||
// Take current and original idnum from the new_method
|
||||
idnum_owner->set_method_idnum(new_num);
|
||||
idnum_owner->set_orig_method_idnum(k_new_method->orig_method_idnum());
|
||||
}
|
||||
// Take current and original idnum from the old_method
|
||||
k_new_method->set_method_idnum(old_num);
|
||||
k_new_method->set_orig_method_idnum(k_old_method->orig_method_idnum());
|
||||
if (thread->has_pending_exception()) {
|
||||
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -817,9 +821,12 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
|||
Method* idnum_owner = scratch_class->method_with_idnum(num);
|
||||
if (idnum_owner != NULL) {
|
||||
// There is already a method assigned this idnum -- switch them
|
||||
// Take current and original idnum from the new_method
|
||||
idnum_owner->set_method_idnum(new_num);
|
||||
idnum_owner->set_orig_method_idnum(k_new_method->orig_method_idnum());
|
||||
}
|
||||
k_new_method->set_method_idnum(num);
|
||||
k_new_method->set_orig_method_idnum(num);
|
||||
if (thread->has_pending_exception()) {
|
||||
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -3327,6 +3334,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
|||
// This is a very busy routine. We don't want too much tracing
|
||||
// printed out.
|
||||
bool trace_name_printed = false;
|
||||
InstanceKlass *the_class = InstanceKlass::cast(_the_class_oop);
|
||||
|
||||
// Very noisy: only enable this call if you are trying to determine
|
||||
// that a specific class gets found by this routine.
|
||||
|
@ -3338,10 +3346,8 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
|||
// If the class being redefined is java.lang.Object, we need to fix all
|
||||
// array class vtables also
|
||||
if (k->oop_is_array() && _the_class_oop == SystemDictionary::Object_klass()) {
|
||||
k->vtable()->adjust_method_entries(_matching_old_methods,
|
||||
_matching_new_methods,
|
||||
_matching_methods_length,
|
||||
&trace_name_printed);
|
||||
k->vtable()->adjust_method_entries(the_class, &trace_name_printed);
|
||||
|
||||
} else if (k->oop_is_instance()) {
|
||||
HandleMark hm(_thread);
|
||||
InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
|
@ -3383,14 +3389,9 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
|||
|| ik->is_subtype_of(_the_class_oop))) {
|
||||
// ik->vtable() creates a wrapper object; rm cleans it up
|
||||
ResourceMark rm(_thread);
|
||||
ik->vtable()->adjust_method_entries(_matching_old_methods,
|
||||
_matching_new_methods,
|
||||
_matching_methods_length,
|
||||
&trace_name_printed);
|
||||
ik->adjust_default_methods(_matching_old_methods,
|
||||
_matching_new_methods,
|
||||
_matching_methods_length,
|
||||
&trace_name_printed);
|
||||
|
||||
ik->vtable()->adjust_method_entries(the_class, &trace_name_printed);
|
||||
ik->adjust_default_methods(the_class, &trace_name_printed);
|
||||
}
|
||||
|
||||
// If the current class has an itable and we are either redefining an
|
||||
|
@ -3405,10 +3406,8 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
|||
|| ik->is_subclass_of(_the_class_oop))) {
|
||||
// ik->itable() creates a wrapper object; rm cleans it up
|
||||
ResourceMark rm(_thread);
|
||||
ik->itable()->adjust_method_entries(_matching_old_methods,
|
||||
_matching_new_methods,
|
||||
_matching_methods_length,
|
||||
&trace_name_printed);
|
||||
|
||||
ik->itable()->adjust_method_entries(the_class, &trace_name_printed);
|
||||
}
|
||||
|
||||
// The constant pools in other classes (other_cp) can refer to
|
||||
|
@ -3432,10 +3431,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
|
|||
other_cp = constantPoolHandle(ik->constants());
|
||||
cp_cache = other_cp->cache();
|
||||
if (cp_cache != NULL) {
|
||||
cp_cache->adjust_method_entries(_matching_old_methods,
|
||||
_matching_new_methods,
|
||||
_matching_methods_length,
|
||||
&trace_name_printed);
|
||||
cp_cache->adjust_method_entries(the_class, &trace_name_printed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3578,6 +3574,7 @@ int VM_RedefineClasses::check_methods_and_mark_as_obsolete() {
|
|||
|
||||
// obsolete methods need a unique idnum so they become new entries in
|
||||
// the jmethodID cache in InstanceKlass
|
||||
assert(old_method->method_idnum() == new_method->method_idnum(), "must match");
|
||||
u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum();
|
||||
if (num != ConstMethod::UNSET_IDNUM) {
|
||||
old_method->set_method_idnum(num);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue