--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java Wed Oct 09 22:01:59 2013 -0400
@@ -44,12 +44,10 @@
private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("SymbolTable");
theTableField = type.getAddressField("_the_table");
- symbolTableSize = db.lookupIntConstant("SymbolTable::symbol_table_size").intValue();
}
// Fields
private static AddressField theTableField;
- private static int symbolTableSize;
// Accessors
public static SymbolTable getTheTable() {
@@ -57,10 +55,6 @@
return (SymbolTable) VMObjectFactory.newObject(SymbolTable.class, tmp);
}
- public static int getSymbolTableSize() {
- return symbolTableSize;
- }
-
public SymbolTable(Address addr) {
super(addr);
}
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -4080,8 +4080,7 @@
// Generate any default methods - default methods are interface methods
// that have a default implementation. This is new with Lambda project.
- if (has_default_methods && !access_flags.is_interface() &&
- local_interfaces->length() > 0) {
+ if (has_default_methods && !access_flags.is_interface() ) {
DefaultMethods::generate_default_methods(
this_klass(), &all_mirandas, CHECK_(nullHandle));
}
--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -345,7 +345,6 @@
}
Symbol* generate_no_defaults_message(TRAPS) const;
- Symbol* generate_abstract_method_message(Method* method, TRAPS) const;
Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const;
public:
@@ -404,20 +403,19 @@
_exception_message = generate_no_defaults_message(CHECK);
_exception_name = vmSymbols::java_lang_AbstractMethodError();
} else if (qualified_methods.length() == 1) {
+ // leave abstract methods alone, they will be found via normal search path
Method* method = qualified_methods.at(0);
- if (method->is_abstract()) {
- _exception_message = generate_abstract_method_message(method, CHECK);
- _exception_name = vmSymbols::java_lang_AbstractMethodError();
- } else {
+ if (!method->is_abstract()) {
_selected_target = qualified_methods.at(0);
}
} else {
_exception_message = generate_conflicts_message(&qualified_methods,CHECK);
_exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
+ if (TraceDefaultMethods) {
+ _exception_message->print_value_on(tty);
+ tty->print_cr("");
+ }
}
-
- assert((has_target() ^ throws_exception()) == 1,
- "One and only one must be true");
}
bool contains_signature(Symbol* query) {
@@ -475,20 +473,6 @@
return SymbolTable::new_symbol("No qualifying defaults found", CHECK_NULL);
}
-Symbol* MethodFamily::generate_abstract_method_message(Method* method, TRAPS) const {
- Symbol* klass = method->klass_name();
- Symbol* name = method->name();
- Symbol* sig = method->signature();
- stringStream ss;
- ss.print("Method ");
- ss.write((const char*)klass->bytes(), klass->utf8_length());
- ss.print(".");
- ss.write((const char*)name->bytes(), name->utf8_length());
- ss.write((const char*)sig->bytes(), sig->utf8_length());
- ss.print(" is abstract");
- return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL);
-}
-
Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const {
stringStream ss;
ss.print("Conflicting default methods:");
@@ -595,6 +579,18 @@
#endif // ndef PRODUCT
};
+static bool already_in_vtable_slots(GrowableArray<EmptyVtableSlot*>* slots, Method* m) {
+ bool found = false;
+ for (int j = 0; j < slots->length(); ++j) {
+ if (slots->at(j)->name() == m->name() &&
+ slots->at(j)->signature() == m->signature() ) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+}
+
static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) {
@@ -604,8 +600,10 @@
// All miranda methods are obvious candidates
for (int i = 0; i < mirandas->length(); ++i) {
- EmptyVtableSlot* slot = new EmptyVtableSlot(mirandas->at(i));
- slots->append(slot);
+ Method* m = mirandas->at(i);
+ if (!already_in_vtable_slots(slots, m)) {
+ slots->append(new EmptyVtableSlot(m));
+ }
}
// Also any overpasses in our superclasses, that we haven't implemented.
@@ -621,7 +619,26 @@
// unless we have a real implementation of it in the current class.
Method* impl = klass->lookup_method(m->name(), m->signature());
if (impl == NULL || impl->is_overpass()) {
- slots->append(new EmptyVtableSlot(m));
+ if (!already_in_vtable_slots(slots, m)) {
+ slots->append(new EmptyVtableSlot(m));
+ }
+ }
+ }
+ }
+
+ // also any default methods in our superclasses
+ if (super->default_methods() != NULL) {
+ for (int i = 0; i < super->default_methods()->length(); ++i) {
+ Method* m = super->default_methods()->at(i);
+ // m is a method that would have been a miranda if not for the
+ // default method processing that occurred on behalf of our superclass,
+ // so it's a method we want to re-examine in this new context. That is,
+ // unless we have a real implementation of it in the current class.
+ Method* impl = klass->lookup_method(m->name(), m->signature());
+ if (impl == NULL || impl->is_overpass()) {
+ if (!already_in_vtable_slots(slots, m)) {
+ slots->append(new EmptyVtableSlot(m));
+ }
}
}
}
@@ -679,7 +696,7 @@
// private interface methods are not candidates for default methods
// invokespecial to private interface methods doesn't use default method logic
// future: take access controls into account for superclass methods
- if (m != NULL && (!iklass->is_interface() || m->is_public())) {
+ if (m != NULL && !m->is_static() && (!iklass->is_interface() || m->is_public())) {
if (_family == NULL) {
_family = new StatefulMethodFamily();
}
@@ -700,7 +717,7 @@
-static void create_overpasses(
+static void create_defaults_and_exceptions(
GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS);
static void generate_erased_defaults(
@@ -721,6 +738,8 @@
static void merge_in_new_methods(InstanceKlass* klass,
GrowableArray<Method*>* new_methods, TRAPS);
+static void create_default_methods( InstanceKlass* klass,
+ GrowableArray<Method*>* new_methods, TRAPS);
// This is the guts of the default methods implementation. This is called just
// after the classfile has been parsed if some ancestor has default methods.
@@ -782,7 +801,7 @@
}
#endif // ndef PRODUCT
- create_overpasses(empty_slots, klass, CHECK);
+ create_defaults_and_exceptions(empty_slots, klass, CHECK);
#ifndef PRODUCT
if (TraceDefaultMethods) {
@@ -791,66 +810,6 @@
#endif // ndef PRODUCT
}
-
-
-#ifdef ASSERT
-// Return true is broad type is a covariant return of narrow type
-static bool covariant_return_type(BasicType narrow, BasicType broad) {
- if (narrow == broad) {
- return true;
- }
- if (broad == T_OBJECT) {
- return true;
- }
- return false;
-}
-#endif
-
-static int assemble_redirect(
- BytecodeConstantPool* cp, BytecodeBuffer* buffer,
- Symbol* incoming, Method* target, TRAPS) {
-
- BytecodeAssembler assem(buffer, cp);
-
- SignatureStream in(incoming, true);
- SignatureStream out(target->signature(), true);
- u2 parameter_count = 0;
-
- assem.aload(parameter_count++); // load 'this'
-
- while (!in.at_return_type()) {
- assert(!out.at_return_type(), "Parameter counts do not match");
- BasicType bt = in.type();
- assert(out.type() == bt, "Parameter types are not compatible");
- assem.load(bt, parameter_count);
- if (in.is_object() && in.as_symbol(THREAD) != out.as_symbol(THREAD)) {
- assem.checkcast(out.as_symbol(THREAD));
- } else if (bt == T_LONG || bt == T_DOUBLE) {
- ++parameter_count; // longs and doubles use two slots
- }
- ++parameter_count;
- in.next();
- out.next();
- }
- assert(out.at_return_type(), "Parameter counts do not match");
- assert(covariant_return_type(out.type(), in.type()), "Return types are not compatible");
-
- if (parameter_count == 1 && (in.type() == T_LONG || in.type() == T_DOUBLE)) {
- ++parameter_count; // need room for return value
- }
- if (target->method_holder()->is_interface()) {
- assem.invokespecial(target);
- } else {
- assem.invokevirtual(target);
- }
-
- if (in.is_object() && in.as_symbol(THREAD) != out.as_symbol(THREAD)) {
- assem.checkcast(in.as_symbol(THREAD));
- }
- assem._return(in.type());
- return parameter_count;
-}
-
static int assemble_method_error(
BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* errorName, Symbol* message, TRAPS) {
@@ -924,18 +883,18 @@
}
}
-// A "bridge" is a method created by javac to bridge the gap between
-// an implementation and a generically-compatible, but different, signature.
-// Bridges have actual bytecode implementation in classfiles.
-// An "overpass", on the other hand, performs the same function as a bridge
-// but does not occur in a classfile; the VM creates overpass itself,
-// when it needs a path to get from a call site to an default method, and
-// a bridge doesn't exist.
-static void create_overpasses(
+// Create default_methods list for the current class.
+// With the VM only processing erased signatures, the VM only
+// creates an overpass in a conflict case or a case with no candidates.
+// This allows virtual methods to override the overpass, but ensures
+// that a local method search will find the exception rather than an abstract
+// or default method that is not a valid candidate.
+static void create_defaults_and_exceptions(
GrowableArray<EmptyVtableSlot*>* slots,
InstanceKlass* klass, TRAPS) {
GrowableArray<Method*> overpasses;
+ GrowableArray<Method*> defaults;
BytecodeConstantPool bpool(klass->constants());
for (int i = 0; i < slots->length(); ++i) {
@@ -943,7 +902,6 @@
if (slot->is_bound()) {
MethodFamily* method = slot->get_binding();
- int max_stack = 0;
BytecodeBuffer buffer;
#ifndef PRODUCT
@@ -953,26 +911,27 @@
tty->print_cr("");
if (method->has_target()) {
method->print_selected(tty, 1);
- } else {
+ } else if (method->throws_exception()) {
method->print_exception(tty, 1);
}
}
#endif // ndef PRODUCT
+
if (method->has_target()) {
Method* selected = method->get_selected_target();
if (selected->method_holder()->is_interface()) {
- max_stack = assemble_redirect(
- &bpool, &buffer, slot->signature(), selected, CHECK);
+ defaults.push(selected);
}
} else if (method->throws_exception()) {
- max_stack = assemble_method_error(&bpool, &buffer, method->get_exception_name(), method->get_exception_message(), CHECK);
- }
- if (max_stack != 0) {
+ int max_stack = assemble_method_error(&bpool, &buffer,
+ method->get_exception_name(), method->get_exception_message(), CHECK);
AccessFlags flags = accessFlags_from(
JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE);
- Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(),
+ Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(),
flags, max_stack, slot->size_of_parameters(),
ConstMethod::OVERPASS, CHECK);
+ // We push to the methods list:
+ // overpass methods which are exception throwing methods
if (m != NULL) {
overpasses.push(m);
}
@@ -983,11 +942,31 @@
#ifndef PRODUCT
if (TraceDefaultMethods) {
tty->print_cr("Created %d overpass methods", overpasses.length());
+ tty->print_cr("Created %d default methods", defaults.length());
}
#endif // ndef PRODUCT
- switchover_constant_pool(&bpool, klass, &overpasses, CHECK);
- merge_in_new_methods(klass, &overpasses, CHECK);
+ if (overpasses.length() > 0) {
+ switchover_constant_pool(&bpool, klass, &overpasses, CHECK);
+ merge_in_new_methods(klass, &overpasses, CHECK);
+ }
+ if (defaults.length() > 0) {
+ create_default_methods(klass, &defaults, CHECK);
+ }
+}
+
+static void create_default_methods( InstanceKlass* klass,
+ GrowableArray<Method*>* new_methods, TRAPS) {
+
+ int new_size = new_methods->length();
+ Array<Method*>* total_default_methods = MetadataFactory::new_array<Method*>(
+ klass->class_loader_data(), new_size, NULL, CHECK);
+ for (int index = 0; index < new_size; index++ ) {
+ total_default_methods->at_put(index, new_methods->at(index));
+ }
+ Method::sort_methods(total_default_methods, false, false);
+
+ klass->set_default_methods(total_default_methods);
}
static void sort_methods(GrowableArray<Method*>* methods) {
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp Wed Oct 09 22:01:59 2013 -0400
@@ -107,18 +107,13 @@
add(loader_data, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
}
- // Table size
- enum {
- symbol_table_size = 20011
- };
-
Symbol* lookup(int index, const char* name, int len, unsigned int hash);
SymbolTable()
- : Hashtable<Symbol*, mtSymbol>(symbol_table_size, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
+ : Hashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
- : Hashtable<Symbol*, mtSymbol>(symbol_table_size, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
+ : Hashtable<Symbol*, mtSymbol>(SymbolTableSize, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
number_of_entries) {}
// Arena for permanent symbols (null class loader) that are never unloaded
@@ -136,6 +131,9 @@
// The symbol table
static SymbolTable* the_table() { return _the_table; }
+ // Size of one bucket in the string table. Used when checking for rollover.
+ static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
+
static void create_table() {
assert(_the_table == NULL, "One symbol table allowed.");
_the_table = new SymbolTable();
@@ -145,8 +143,11 @@
static void create_table(HashtableBucket<mtSymbol>* t, int length,
int number_of_entries) {
assert(_the_table == NULL, "One symbol table allowed.");
- assert(length == symbol_table_size * sizeof(HashtableBucket<mtSymbol>),
- "bad shared symbol size.");
+
+ // If CDS archive used a different symbol table size, use that size instead
+ // which is better than giving an error.
+ SymbolTableSize = length/bucket_size();
+
_the_table = new SymbolTable(t, number_of_entries);
// if CDS give symbol table a default arena size since most symbols
// are already allocated in the shared misc section.
--- a/hotspot/src/share/vm/classfile/verifier.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -2442,10 +2442,16 @@
bool subtype = ref_class_type.is_assignable_from(
current_type(), this, CHECK_VERIFY(this));
if (!subtype) {
- verify_error(ErrorContext::bad_code(bci),
- "Bad invokespecial instruction: "
- "current class isn't assignable to reference class.");
- return;
+ if (current_class()->is_anonymous()) {
+ subtype = ref_class_type.is_assignable_from(VerificationType::reference_type(
+ current_class()->host_klass()->name()), this, CHECK_VERIFY(this));
+ }
+ if (!subtype) {
+ verify_error(ErrorContext::bad_code(bci),
+ "Bad invokespecial instruction: "
+ "current class isn't assignable to reference class.");
+ return;
+ }
}
}
// Match method descriptor with operand stack
@@ -2461,7 +2467,28 @@
} else { // other methods
// Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) {
- current_frame->pop_stack(current_type(), CHECK_VERIFY(this));
+ if (!current_class()->is_anonymous()) {
+ current_frame->pop_stack(current_type(), CHECK_VERIFY(this));
+ } else {
+ // anonymous class invokespecial calls: either the
+ // operand stack/objectref is a subtype of the current class OR
+ // the objectref is a subtype of the host_klass of the current class
+ // to allow an anonymous class to reference methods in the host_klass
+ VerificationType top = current_frame->pop_stack(CHECK_VERIFY(this));
+ bool subtype = current_type().is_assignable_from(top, this, CHECK_VERIFY(this));
+ if (!subtype) {
+ VerificationType hosttype =
+ VerificationType::reference_type(current_class()->host_klass()->name());
+ subtype = hosttype.is_assignable_from(top, this, CHECK_VERIFY(this));
+ }
+ if (!subtype) {
+ verify_error( ErrorContext::bad_type(current_frame->offset(),
+ current_frame->stack_top_ctx(),
+ TypeOrigin::implicit(top)),
+ "Bad type on operand stack");
+ return;
+ }
+ }
} else if (opcode == Bytecodes::_invokevirtual) {
VerificationType stack_object_type =
current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this));
--- a/hotspot/src/share/vm/code/dependencies.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/code/dependencies.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -812,8 +812,8 @@
Klass* k = ctxk;
Method* lm = k->lookup_method(m->name(), m->signature());
if (lm == NULL && k->oop_is_instance()) {
- // It might be an abstract interface method, devoid of mirandas.
- lm = ((InstanceKlass*)k)->lookup_method_in_all_interfaces(m->name(),
+ // It might be an interface method
+ lm = ((InstanceKlass*)k)->lookup_method_in_ordered_interfaces(m->name(),
m->signature());
}
if (lm == m)
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 1997, 2013, 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
@@ -221,8 +222,17 @@
//
// According to JVM spec. $5.4.3c & $5.4.3d
+// Look up method in klasses, including static methods
+// Then look up local default methods
void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
Method* result_oop = klass->uncached_lookup_method(name, signature);
+ if (result_oop == NULL) {
+ Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
+ if (default_methods != NULL) {
+ result_oop = InstanceKlass::find_method(default_methods, name, signature);
+ }
+ }
+
if (EnableInvokeDynamic && result_oop != NULL) {
vmIntrinsics::ID iid = result_oop->intrinsic_id();
if (MethodHandles::is_signature_polymorphic(iid)) {
@@ -234,6 +244,7 @@
}
// returns first instance method
+// Looks up method in classes, then looks up local default methods
void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
Method* result_oop = klass->uncached_lookup_method(name, signature);
result = methodHandle(THREAD, result_oop);
@@ -241,13 +252,38 @@
klass = KlassHandle(THREAD, result->method_holder()->super());
result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature));
}
+
+ if (result.is_null()) {
+ Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
+ if (default_methods != NULL) {
+ result = methodHandle(InstanceKlass::find_method(default_methods, name, signature));
+ assert(result.is_null() || !result->is_static(), "static defaults not allowed");
+ }
+ }
}
+int LinkResolver::vtable_index_of_interface_method(KlassHandle klass,
+ methodHandle resolved_method, TRAPS) {
-int LinkResolver::vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
- ResourceMark rm(THREAD);
- klassVtable *vt = InstanceKlass::cast(klass())->vtable();
- return vt->index_of_miranda(name, signature);
+ int vtable_index = Method::invalid_vtable_index;
+ Symbol* name = resolved_method->name();
+ Symbol* signature = resolved_method->signature();
+
+ // First check in default method array
+ if (!resolved_method->is_abstract() &&
+ (InstanceKlass::cast(klass())->default_methods() != NULL)) {
+ int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature);
+ if (index >= 0 ) {
+ vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
+ }
+ }
+ if (vtable_index == Method::invalid_vtable_index) {
+ // get vtable_index for miranda methods
+ ResourceMark rm(THREAD);
+ klassVtable *vt = InstanceKlass::cast(klass())->vtable();
+ vtable_index = vt->index_of_miranda(name, signature);
+ }
+ return vtable_index;
}
void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
@@ -625,6 +661,12 @@
resolved_method->method_holder()->internal_name()
);
resolved_method->access_flags().print_on(tty);
+ if (resolved_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (resolved_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->cr();
}
}
@@ -853,6 +895,7 @@
resolved_method->signature()));
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
+
if (TraceItables && Verbose) {
ResourceMark rm(THREAD);
tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
@@ -864,8 +907,7 @@
resolved_method->method_holder()->internal_name()
);
resolved_method->access_flags().print_on(tty);
- if (resolved_method->method_holder()->is_interface() &&
- !resolved_method->is_abstract()) {
+ if (resolved_method->is_default_method()) {
tty->print("default");
}
if (resolved_method->is_overpass()) {
@@ -945,10 +987,12 @@
sel_method->method_holder()->internal_name()
);
sel_method->access_flags().print_on(tty);
- if (sel_method->method_holder()->is_interface() &&
- !sel_method->is_abstract()) {
+ if (sel_method->is_default_method()) {
tty->print("default");
}
+ if (sel_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->cr();
}
@@ -996,26 +1040,25 @@
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
- if (PrintVtables && Verbose) {
- ResourceMark rm(THREAD);
- tty->print("invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
- (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
- (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
- Method::name_and_sig_as_C_string(resolved_klass(),
- resolved_method->name(),
- resolved_method->signature()),
- resolved_method->method_holder()->internal_name()
- );
- resolved_method->access_flags().print_on(tty);
- if (resolved_method->method_holder()->is_interface() &&
- !resolved_method->is_abstract()) {
- tty->print("default");
- }
- if (resolved_method->is_overpass()) {
- tty->print("overpass");
- }
- tty->cr();
- }
+ if (PrintVtables && Verbose) {
+ ResourceMark rm(THREAD);
+ tty->print("invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
+ (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
+ (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
+ Method::name_and_sig_as_C_string(resolved_klass(),
+ resolved_method->name(),
+ resolved_method->signature()),
+ resolved_method->method_holder()->internal_name()
+ );
+ resolved_method->access_flags().print_on(tty);
+ if (resolved_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (resolved_method->is_overpass()) {
+ tty->print("overpass");
+ }
+ tty->cr();
+ }
}
// throws runtime exceptions
@@ -1045,10 +1088,8 @@
// do lookup based on receiver klass using the vtable index
if (resolved_method->method_holder()->is_interface()) { // miranda method
- vtable_index = vtable_index_of_miranda_method(resolved_klass,
- resolved_method->name(),
- resolved_method->signature(), CHECK);
-
+ vtable_index = vtable_index_of_interface_method(resolved_klass,
+ resolved_method, CHECK);
assert(vtable_index >= 0 , "we should have valid vtable index at this point");
InstanceKlass* inst = InstanceKlass::cast(recv_klass());
@@ -1104,11 +1145,10 @@
vtable_index
);
selected_method->access_flags().print_on(tty);
- if (selected_method->method_holder()->is_interface() &&
- !selected_method->is_abstract()) {
+ if (selected_method->is_default_method()) {
tty->print("default");
}
- if (resolved_method->is_overpass()) {
+ if (selected_method->is_overpass()) {
tty->print("overpass");
}
tty->cr();
@@ -1191,7 +1231,6 @@
sel_method->name(),
sel_method->signature()));
}
-
// check if abstract
if (check_null_and_abstract && sel_method->is_abstract()) {
ResourceMark rm(THREAD);
@@ -1220,11 +1259,10 @@
sel_method->method_holder()->internal_name()
);
sel_method->access_flags().print_on(tty);
- if (sel_method->method_holder()->is_interface() &&
- !sel_method->is_abstract()) {
+ if (sel_method->is_default_method()) {
tty->print("default");
}
- if (resolved_method->is_overpass()) {
+ if (sel_method->is_overpass()) {
tty->print("overpass");
}
tty->cr();
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp Wed Oct 09 22:01:59 2013 -0400
@@ -130,8 +130,7 @@
static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
- static int vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
-
+ static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method, TRAPS);
static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS);
static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);
--- a/hotspot/src/share/vm/memory/heapInspection.hpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/memory/heapInspection.hpp Wed Oct 09 22:01:59 2013 -0400
@@ -73,6 +73,10 @@
"Number of bytes used by the InstanceKlass::methods() array") \
f(method_ordering_bytes, IK_method_ordering, \
"Number of bytes used by the InstanceKlass::method_ordering() array") \
+ f(default_methods_array_bytes, IK_default_methods, \
+ "Number of bytes used by the InstanceKlass::default_methods() array") \
+ f(default_vtable_indices_bytes, IK_default_vtable_indices, \
+ "Number of bytes used by the InstanceKlass::default_vtable_indices() array") \
f(local_interfaces_bytes, IK_local_interfaces, \
"Number of bytes used by the InstanceKlass::local_interfaces() array") \
f(transitive_interfaces_bytes, IK_transitive_interfaces, \
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -238,6 +238,13 @@
}
}
+// create a new array of vtable_indices for default methods
+Array<int>* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) {
+ Array<int>* vtable_indices = MetadataFactory::new_array<int>(class_loader_data(), len, CHECK_NULL);
+ assert(default_vtable_indices() == NULL, "only create once");
+ set_default_vtable_indices(vtable_indices);
+ return vtable_indices;
+}
InstanceKlass::InstanceKlass(int vtable_len,
int itable_len,
@@ -263,6 +270,8 @@
set_array_klasses(NULL);
set_methods(NULL);
set_method_ordering(NULL);
+ set_default_methods(NULL);
+ set_default_vtable_indices(NULL);
set_local_interfaces(NULL);
set_transitive_interfaces(NULL);
init_implementor();
@@ -376,6 +385,21 @@
}
set_method_ordering(NULL);
+ // default methods can be empty
+ if (default_methods() != NULL &&
+ default_methods() != Universe::the_empty_method_array()) {
+ MetadataFactory::free_array<Method*>(loader_data, default_methods());
+ }
+ // Do NOT deallocate the default methods, they are owned by superinterfaces.
+ set_default_methods(NULL);
+
+ // default methods vtable indices can be empty
+ if (default_vtable_indices() != NULL) {
+ MetadataFactory::free_array<int>(loader_data, default_vtable_indices());
+ }
+ set_default_vtable_indices(NULL);
+
+
// This array is in Klass, but remove it with the InstanceKlass since
// this place would be the only caller and it can share memory with transitive
// interfaces.
@@ -1354,32 +1378,44 @@
return -1;
}
+// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
return InstanceKlass::find_method(methods(), name, signature);
}
+// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
+ int hit = find_method_index(methods, name, signature);
+ return hit >= 0 ? methods->at(hit): NULL;
+}
+
+// Used directly for default_methods to find the index into the
+// default_vtable_indices, and indirectly by find_method
+// find_method_index looks in the local methods array to return the index
+// of the matching name/signature
+int InstanceKlass::find_method_index(
+ Array<Method*>* methods, Symbol* name, Symbol* signature) {
int hit = binary_search(methods, name);
if (hit != -1) {
Method* m = methods->at(hit);
// Do linear search to find matching signature. First, quick check
// for common case
- if (m->signature() == signature) return m;
+ if (m->signature() == signature) return hit;
// search downwards through overloaded methods
int i;
for (i = hit - 1; i >= 0; --i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
- if (m->signature() == signature) return m;
+ if (m->signature() == signature) return i;
}
// search upwards
for (i = hit + 1; i < methods->length(); ++i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
- if (m->signature() == signature) return m;
+ if (m->signature() == signature) return i;
}
// not found
#ifdef ASSERT
@@ -1387,9 +1423,8 @@
assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
}
- return NULL;
+ return -1;
}
-
int InstanceKlass::find_method_by_name(Symbol* name, int* end) {
return find_method_by_name(methods(), name, end);
}
@@ -1408,6 +1443,7 @@
return -1;
}
+// lookup_method searches both the local methods array and all superclasses methods arrays
Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
Klass* klass = const_cast<InstanceKlass*>(this);
while (klass != NULL) {
@@ -1418,6 +1454,21 @@
return NULL;
}
+// lookup a method in the default methods list then in all transitive interfaces
+// Do NOT return private or static methods
+Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name,
+ Symbol* signature) const {
+ Method* m = NULL;
+ if (default_methods() != NULL) {
+ m = find_method(default_methods(), name, signature);
+ }
+ // Look up interfaces
+ if (m == NULL) {
+ m = lookup_method_in_all_interfaces(name, signature);
+ }
+ return m;
+}
+
// lookup a method in all the interfaces that this class implements
// Do NOT return private or static methods, new in JDK8 which are not externally visible
// They should only be found in the initial InterfaceMethodRef
@@ -2548,6 +2599,42 @@
return m;
}
+
+#if INCLUDE_JVMTI
+// update default_methods for redefineclasses for methods that are
+// 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) {
+ // 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 ++) {
+ 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()));
+ }
+ }
+ }
+ }
+ }
+}
+#endif // INCLUDE_JVMTI
+
// On-stack replacement stuff
void InstanceKlass::add_osr_nmethod(nmethod* n) {
// only one compilation can be active
@@ -2742,11 +2829,21 @@
st->print(BULLET"methods: "); methods()->print_value_on(st); st->cr();
if (Verbose || WizardMode) {
Array<Method*>* method_array = methods();
- for(int i = 0; i < method_array->length(); i++) {
+ for (int i = 0; i < method_array->length(); i++) {
st->print("%d : ", i); method_array->at(i)->print_value(); st->cr();
}
}
- st->print(BULLET"method ordering: "); method_ordering()->print_value_on(st); st->cr();
+ st->print(BULLET"method ordering: "); method_ordering()->print_value_on(st); st->cr();
+ st->print(BULLET"default_methods: "); default_methods()->print_value_on(st); st->cr();
+ if (Verbose && default_methods() != NULL) {
+ Array<Method*>* method_array = default_methods();
+ for (int i = 0; i < method_array->length(); i++) {
+ st->print("%d : ", i); method_array->at(i)->print_value(); st->cr();
+ }
+ }
+ if (default_vtable_indices() != NULL) {
+ st->print(BULLET"default vtable indices: "); default_vtable_indices()->print_value_on(st); st->cr();
+ }
st->print(BULLET"local interfaces: "); local_interfaces()->print_value_on(st); st->cr();
st->print(BULLET"trans. interfaces: "); transitive_interfaces()->print_value_on(st); st->cr();
st->print(BULLET"constants: "); constants()->print_value_on(st); st->cr();
@@ -3099,6 +3196,19 @@
}
}
+ // Verify default methods
+ if (default_methods() != NULL) {
+ Array<Method*>* methods = this->default_methods();
+ for (int j = 0; j < methods->length(); j++) {
+ guarantee(methods->at(j)->is_method(), "non-method in methods array");
+ }
+ for (int j = 0; j < methods->length() - 1; j++) {
+ Method* m1 = methods->at(j);
+ Method* m2 = methods->at(j + 1);
+ guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly");
+ }
+ }
+
// Verify JNI static field identifiers
if (jni_ids() != NULL) {
jni_ids()->verify(this);
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Oct 09 22:01:59 2013 -0400
@@ -269,12 +269,18 @@
// Method array.
Array<Method*>* _methods;
+ // Default Method Array, concrete methods inherited from interfaces
+ Array<Method*>* _default_methods;
// Interface (Klass*s) this class declares locally to implement.
Array<Klass*>* _local_interfaces;
// Interface (Klass*s) this class implements transitively.
Array<Klass*>* _transitive_interfaces;
// Int array containing the original order of method in the class file (for JVMTI).
Array<int>* _method_ordering;
+ // Int array containing the vtable_indices for default_methods
+ // offset matches _default_methods offset
+ Array<int>* _default_vtable_indices;
+
// Instance and static variable information, starts with 6-tuples of shorts
// [access, name index, sig index, initval index, low_offset, high_offset]
// for all fields, followed by the generic signature data at the end of
@@ -356,6 +362,15 @@
void set_method_ordering(Array<int>* m) { _method_ordering = m; }
void copy_method_ordering(intArray* m, TRAPS);
+ // default_methods
+ Array<Method*>* default_methods() const { return _default_methods; }
+ void set_default_methods(Array<Method*>* a) { _default_methods = a; }
+
+ // default method vtable_indices
+ Array<int>* default_vtable_indices() const { return _default_vtable_indices; }
+ void set_default_vtable_indices(Array<int>* v) { _default_vtable_indices = v; }
+ Array<int>* create_new_default_vtable_indices(int len, TRAPS);
+
// interfaces
Array<Klass*>* local_interfaces() const { return _local_interfaces; }
void set_local_interfaces(Array<Klass*>* a) {
@@ -501,12 +516,18 @@
Method* find_method(Symbol* name, Symbol* signature) const;
static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+ // find a local method index in default_methods (returns -1 if not found)
+ static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature);
+
// lookup operation (returns NULL if not found)
Method* uncached_lookup_method(Symbol* name, Symbol* signature) const;
// lookup a method in all the interfaces that this class implements
// (returns NULL if not found)
Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature) const;
+ // lookup a method in local defaults then in all interfaces
+ // (returns NULL if not found)
+ Method* lookup_method_in_ordered_interfaces(Symbol* name, Symbol* signature) const;
// Find method indices by name. If a method with the specified name is
// found the index to the first method is returned, and 'end' is filled in
@@ -910,6 +931,11 @@
klassItable* itable() const; // return new klassItable wrapper
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);
+#endif // INCLUDE_JVMTI
+
// Garbage collection
void oop_follow_contents(oop obj);
int oop_adjust_pointers(oop obj);
--- a/hotspot/src/share/vm/oops/klassVtable.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -83,7 +83,7 @@
GrowableArray<Method*> new_mirandas(20);
// compute the number of mirandas methods that must be added to the end
- get_mirandas(&new_mirandas, all_mirandas, super, methods, local_interfaces);
+ get_mirandas(&new_mirandas, all_mirandas, super, methods, NULL, local_interfaces);
*num_new_mirandas = new_mirandas.length();
vtable_length += *num_new_mirandas * vtableEntry::size();
@@ -186,7 +186,7 @@
assert(methods->at(i)->is_method(), "must be a Method*");
methodHandle mh(THREAD, methods->at(i));
- bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK);
+ bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, -1, checkconstraints, CHECK);
if (needs_new_entry) {
put_method_at(mh(), initialized);
@@ -195,7 +195,35 @@
}
}
- // add miranda methods to end of vtable.
+ // update vtable with default_methods
+ Array<Method*>* default_methods = ik()->default_methods();
+ if (default_methods != NULL) {
+ len = default_methods->length();
+ if (len > 0) {
+ Array<int>* def_vtable_indices = NULL;
+ if ((def_vtable_indices = ik()->default_vtable_indices()) == NULL) {
+ def_vtable_indices = ik()->create_new_default_vtable_indices(len, CHECK);
+ } else {
+ assert(def_vtable_indices->length() == len, "reinit vtable len?");
+ }
+ for (int i = 0; i < len; i++) {
+ HandleMark hm(THREAD);
+ assert(default_methods->at(i)->is_method(), "must be a Method*");
+ methodHandle mh(THREAD, default_methods->at(i));
+
+ bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, i, checkconstraints, CHECK);
+
+ // needs new entry
+ if (needs_new_entry) {
+ put_method_at(mh(), initialized);
+ def_vtable_indices->at_put(i, initialized); //set vtable index
+ initialized++;
+ }
+ }
+ }
+ }
+
+ // add miranda methods; it will also return the updated initialized
initialized = fill_in_mirandas(initialized);
// In class hierarchies where the accessibility is not increasing (i.e., going from private ->
@@ -230,14 +258,19 @@
#ifndef PRODUCT
if (PrintVtables && Verbose) {
ResourceMark rm(THREAD);
+ char* sig = target_method()->name_and_sig_as_C_string();
tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ",
supersuperklass->internal_name(),
- _klass->internal_name(), (target_method() != NULL) ?
- target_method()->name()->as_C_string() : "<NULL>", vtable_index);
+ _klass->internal_name(), sig, vtable_index);
super_method->access_flags().print_on(tty);
+ if (super_method->is_default_method()) {
+ tty->print("default");
+ }
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
- tty->cr();
+ if (target_method->is_default_method()) {
+ tty->print("default");
+ }
}
#endif /*PRODUCT*/
break; // return found superk
@@ -258,16 +291,31 @@
// OR return true if a new vtable entry is required.
// Only called for InstanceKlass's, i.e. not for arrays
// If that changed, could not use _klass as handle for klass
-bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len,
- bool checkconstraints, TRAPS) {
+bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle target_method,
+ int super_vtable_len, int default_index,
+ bool checkconstraints, TRAPS) {
ResourceMark rm;
bool allocate_new = true;
assert(klass->oop_is_instance(), "must be InstanceKlass");
- assert(klass == target_method()->method_holder(), "caller resp.");
- // Initialize the method's vtable index to "nonvirtual".
- // If we allocate a vtable entry, we will update it to a non-negative number.
- target_method()->set_vtable_index(Method::nonvirtual_vtable_index);
+ Array<int>* def_vtable_indices = NULL;
+ bool is_default = false;
+ // default methods are concrete methods in superinterfaces which are added to the vtable
+ // with their real method_holder
+ // Since vtable and itable indices share the same storage, don't touch
+ // the default method's real vtable/itable index
+ // default_vtable_indices stores the vtable value relative to this inheritor
+ if (default_index >= 0 ) {
+ is_default = true;
+ def_vtable_indices = klass->default_vtable_indices();
+ assert(def_vtable_indices != NULL, "def vtable alloc?");
+ assert(default_index <= def_vtable_indices->length(), "def vtable len?");
+ } else {
+ assert(klass == target_method()->method_holder(), "caller resp.");
+ // Initialize the method's vtable index to "nonvirtual".
+ // If we allocate a vtable entry, we will update it to a non-negative number.
+ target_method()->set_vtable_index(Method::nonvirtual_vtable_index);
+ }
// Static and <init> methods are never in
if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) {
@@ -284,6 +332,8 @@
// An interface never allocates new vtable slots, only inherits old ones.
// This method will either be assigned its own itable index later,
// or be assigned an inherited vtable index in the loop below.
+ // default methods store their vtable indices in the inheritors default_vtable_indices
+ assert (default_index == -1, "interfaces don't store resolved default methods");
target_method()->set_vtable_index(Method::pending_itable_index);
}
@@ -307,8 +357,15 @@
Symbol* name = target_method()->name();
Symbol* signature = target_method()->signature();
- Handle target_loader(THREAD, _klass()->class_loader());
- Symbol* target_classname = _klass->name();
+
+ KlassHandle target_klass(THREAD, target_method()->method_holder());
+ if (target_klass == NULL) {
+ target_klass = _klass;
+ }
+
+ Handle target_loader(THREAD, target_klass->class_loader());
+
+ Symbol* target_classname = target_klass->name();
for(int i = 0; i < super_vtable_len; i++) {
Method* super_method = method_at(i);
// Check if method name matches
@@ -317,10 +374,14 @@
// get super_klass for method_holder for the found method
InstanceKlass* super_klass = super_method->method_holder();
- if ((super_klass->is_override(super_method, target_loader, target_classname, THREAD)) ||
- ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
- && ((super_klass = find_transitive_override(super_klass, target_method, i, target_loader,
- target_classname, THREAD)) != (InstanceKlass*)NULL))) {
+ if (is_default
+ || ((super_klass->is_override(super_method, target_loader, target_classname, THREAD))
+ || ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
+ && ((super_klass = find_transitive_override(super_klass,
+ target_method, i, target_loader,
+ target_classname, THREAD))
+ != (InstanceKlass*)NULL))))
+ {
// overriding, so no new entry
allocate_new = false;
@@ -347,7 +408,7 @@
"%s used in the signature";
char* sig = target_method()->name_and_sig_as_C_string();
const char* loader1 = SystemDictionary::loader_name(target_loader());
- char* current = _klass->name()->as_C_string();
+ char* current = target_klass->name()->as_C_string();
const char* loader2 = SystemDictionary::loader_name(super_loader());
char* failed_type_name = failed_type_symbol->as_C_string();
size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
@@ -360,16 +421,39 @@
}
}
- put_method_at(target_method(), i);
- target_method()->set_vtable_index(i);
+ put_method_at(target_method(), i);
+ if (!is_default) {
+ target_method()->set_vtable_index(i);
+ } else {
+ if (def_vtable_indices != NULL) {
+ def_vtable_indices->at_put(default_index, i);
+ }
+ assert(super_method->is_default_method() || super_method->is_overpass()
+ || super_method->is_abstract(), "default override error");
+ }
+
+
#ifndef PRODUCT
if (PrintVtables && Verbose) {
+ ResourceMark rm(THREAD);
+ char* sig = target_method()->name_and_sig_as_C_string();
tty->print("overriding with %s::%s index %d, original flags: ",
- _klass->internal_name(), (target_method() != NULL) ?
- target_method()->name()->as_C_string() : "<NULL>", i);
+ target_klass->internal_name(), sig, i);
super_method->access_flags().print_on(tty);
+ if (super_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (super_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
+ if (target_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (target_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->cr();
}
#endif /*PRODUCT*/
@@ -378,12 +462,25 @@
// but not override another. Once we override one, not need new
#ifndef PRODUCT
if (PrintVtables && Verbose) {
+ ResourceMark rm(THREAD);
+ char* sig = target_method()->name_and_sig_as_C_string();
tty->print("NOT overriding with %s::%s index %d, original flags: ",
- _klass->internal_name(), (target_method() != NULL) ?
- target_method()->name()->as_C_string() : "<NULL>", i);
+ target_klass->internal_name(), sig,i);
super_method->access_flags().print_on(tty);
+ if (super_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (super_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
+ if (target_method->is_default_method()) {
+ tty->print("default");
+ }
+ if (target_method->is_overpass()) {
+ tty->print("overpass");
+ }
tty->cr();
}
#endif /*PRODUCT*/
@@ -438,6 +535,14 @@
return false;
}
+ // Concrete interface methods do not need new entries, they override
+ // abstract method entries using default inheritance rules
+ if (target_method()->method_holder() != NULL &&
+ target_method()->method_holder()->is_interface() &&
+ !target_method()->is_abstract() ) {
+ return false;
+ }
+
// we need a new entry if there is no superclass
if (super == NULL) {
return true;
@@ -446,7 +551,7 @@
// private methods in classes always have a new entry in the vtable
// specification interpretation since classic has
// private methods not overriding
- // JDK8 adds private methods in interfaces which require invokespecial
+ // JDK8 adds private methods in interfaces which require invokespecial
if (target_method()->is_private()) {
return true;
}
@@ -526,35 +631,40 @@
if (mhk->is_interface()) {
assert(m->is_public(), "should be public");
assert(ik()->implements_interface(method_holder) , "this class should implement the interface");
- assert(is_miranda(m, ik()->methods(), ik()->super()), "should be a miranda_method");
+ assert(is_miranda(m, ik()->methods(), ik()->default_methods(), ik()->super()), "should be a miranda_method");
return true;
}
return false;
}
-// check if a method is a miranda method, given a class's methods table and its super
-// "miranda" means not static, not defined by this class, and not defined
-// in super unless it is private and therefore inaccessible to this class.
+// check if a method is a miranda method, given a class's methods table,
+// its default_method table and its super
+// "miranda" means not static, not defined by this class.
+// private methods in interfaces do not belong in the miranda list.
// the caller must make sure that the method belongs to an interface implemented by the class
// Miranda methods only include public interface instance methods
-// Not private methods, not static methods, not default = concrete abstract
-bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods, Klass* super) {
- if (m->is_static()) {
+// Not private methods, not static methods, not default == concrete abstract
+bool klassVtable::is_miranda(Method* m, Array<Method*>* class_methods,
+ Array<Method*>* default_methods, Klass* super) {
+ if (m->is_static() || m->is_private()) {
return false;
}
Symbol* name = m->name();
Symbol* signature = m->signature();
if (InstanceKlass::find_method(class_methods, name, signature) == NULL) {
// did not find it in the method table of the current class
- if (super == NULL) {
- // super doesn't exist
- return true;
- }
+ if ((default_methods == NULL) ||
+ InstanceKlass::find_method(default_methods, name, signature) == NULL) {
+ if (super == NULL) {
+ // super doesn't exist
+ return true;
+ }
- Method* mo = InstanceKlass::cast(super)->lookup_method(name, signature);
- if (mo == NULL || mo->access_flags().is_private() ) {
- // super class hierarchy does not implement it or protection is different
- return true;
+ Method* mo = InstanceKlass::cast(super)->lookup_method(name, signature);
+ if (mo == NULL || mo->access_flags().is_private() ) {
+ // super class hierarchy does not implement it or protection is different
+ return true;
+ }
}
}
@@ -562,7 +672,7 @@
}
// Scans current_interface_methods for miranda methods that do not
-// already appear in new_mirandas and are also not defined-and-non-private
+// already appear in new_mirandas, or default methods, and are also not defined-and-non-private
// in super (superclass). These mirandas are added to all_mirandas if it is
// not null; in addition, those that are not duplicates of miranda methods
// inherited by super from its interfaces are added to new_mirandas.
@@ -572,7 +682,8 @@
void klassVtable::add_new_mirandas_to_lists(
GrowableArray<Method*>* new_mirandas, GrowableArray<Method*>* all_mirandas,
Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
- Klass* super) {
+ Array<Method*>* default_methods, Klass* super) {
+
// iterate thru the current interface's method to see if it a miranda
int num_methods = current_interface_methods->length();
for (int i = 0; i < num_methods; i++) {
@@ -590,7 +701,7 @@
}
if (!is_duplicate) { // we don't want duplicate miranda entries in the vtable
- if (is_miranda(im, class_methods, super)) { // is it a miranda at all?
+ if (is_miranda(im, class_methods, default_methods, super)) { // is it a miranda at all?
InstanceKlass *sk = InstanceKlass::cast(super);
// check if it is a duplicate of a super's miranda
if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) {
@@ -607,6 +718,7 @@
void klassVtable::get_mirandas(GrowableArray<Method*>* new_mirandas,
GrowableArray<Method*>* all_mirandas,
Klass* super, Array<Method*>* class_methods,
+ Array<Method*>* default_methods,
Array<Klass*>* local_interfaces) {
assert((new_mirandas->length() == 0) , "current mirandas must be 0");
@@ -615,14 +727,16 @@
for (int i = 0; i < num_local_ifs; i++) {
InstanceKlass *ik = InstanceKlass::cast(local_interfaces->at(i));
add_new_mirandas_to_lists(new_mirandas, all_mirandas,
- ik->methods(), class_methods, super);
+ ik->methods(), class_methods,
+ default_methods, super);
// iterate thru each local's super interfaces
Array<Klass*>* super_ifs = ik->transitive_interfaces();
int num_super_ifs = super_ifs->length();
for (int j = 0; j < num_super_ifs; j++) {
InstanceKlass *sik = InstanceKlass::cast(super_ifs->at(j));
add_new_mirandas_to_lists(new_mirandas, all_mirandas,
- sik->methods(), class_methods, super);
+ sik->methods(), class_methods,
+ default_methods, super);
}
}
}
@@ -633,8 +747,22 @@
int klassVtable::fill_in_mirandas(int initialized) {
GrowableArray<Method*> mirandas(20);
get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(),
- ik()->local_interfaces());
+ ik()->default_methods(), ik()->local_interfaces());
for (int i = 0; i < mirandas.length(); i++) {
+ if (PrintVtables && Verbose) {
+ Method* meth = mirandas.at(i);
+ ResourceMark rm(Thread::current());
+ if (meth != NULL) {
+ char* sig = meth->name_and_sig_as_C_string();
+ tty->print("fill in mirandas with %s index %d, flags: ",
+ sig, initialized);
+ meth->access_flags().print_on(tty);
+ if (meth->is_default_method()) {
+ tty->print("default");
+ }
+ tty->cr();
+ }
+ }
put_method_at(mirandas.at(i), initialized);
++initialized;
}
@@ -648,6 +776,26 @@
}
#if INCLUDE_JVMTI
+bool klassVtable::adjust_default_method(int vtable_index, Method* old_method, Method* new_method) {
+ // If old_method is default, find this vtable index in default_vtable_indices
+ // and replace that method in the _default_methods list
+ bool updated = false;
+
+ Array<Method*>* default_methods = ik()->default_methods();
+ if (default_methods != NULL) {
+ int len = default_methods->length();
+ for (int idx = 0; idx < len; idx++) {
+ if (vtable_index == ik()->default_vtable_indices()->at(idx)) {
+ if (default_methods->at(idx) == old_method) {
+ default_methods->at_put(idx, new_method);
+ updated = true;
+ }
+ break;
+ }
+ }
+ }
+ 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
@@ -663,18 +811,26 @@
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);
+ }
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",
+ 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)",
+ RC_TRACE(0x00100000, ("vtable method update: %s(%s), updated default = %s",
new_method->name()->as_C_string(),
- new_method->signature()->as_C_string()));
+ new_method->signature()->as_C_string(),
+ updated_default ? "true" : "false"));
}
// cannot 'break' here; see for-loop comment above.
}
@@ -701,6 +857,12 @@
if (m != NULL) {
tty->print(" (%5d) ", i);
m->access_flags().print_on(tty);
+ if (m->is_default_method()) {
+ tty->print("default");
+ }
+ if (m->is_overpass()) {
+ tty->print("overpass");
+ }
tty->print(" -- ");
m->print_name(tty);
tty->cr();
@@ -757,9 +919,9 @@
// Initialization
void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
if (_klass->is_interface()) {
- // This needs to go after vtable indexes are assigned but
- // before implementors need to know the number of itable indexes.
- assign_itable_indexes_for_interface(_klass());
+ // This needs to go after vtable indices are assigned but
+ // before implementors need to know the number of itable indices.
+ assign_itable_indices_for_interface(_klass());
}
// Cannot be setup doing bootstrapping, interfaces don't have
@@ -803,7 +965,7 @@
return true;
}
-int klassItable::assign_itable_indexes_for_interface(Klass* klass) {
+int klassItable::assign_itable_indices_for_interface(Klass* klass) {
// an interface does not have an itable, but its methods need to be numbered
if (TraceItables) tty->print_cr("%3d: Initializing itable for interface %s", ++initialize_count,
klass->name()->as_C_string());
@@ -846,7 +1008,7 @@
}
nof_methods -= 1;
}
- // no methods have itable indexes
+ // no methods have itable indices
return 0;
}
@@ -907,6 +1069,21 @@
int ime_num = m->itable_index();
assert(ime_num < ime_count, "oob");
itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target());
+ if (TraceItables && Verbose) {
+ ResourceMark rm(THREAD);
+ if (target() != NULL) {
+ char* sig = target()->name_and_sig_as_C_string();
+ tty->print("interface: %s, ime_num: %d, target: %s, method_holder: %s ",
+ interf_h()->internal_name(), ime_num, sig,
+ target()->method_holder()->internal_name());
+ tty->print("target_method flags: ");
+ target()->access_flags().print_on(tty);
+ if (target()->is_default_method()) {
+ tty->print("default");
+ }
+ tty->cr();
+ }
+ }
}
}
}
@@ -980,6 +1157,9 @@
if (m != NULL) {
tty->print(" (%5d) ", i);
m->access_flags().print_on(tty);
+ if (m->is_default_method()) {
+ tty->print("default");
+ }
tty->print(" -- ");
m->print_name(tty);
tty->cr();
@@ -1116,7 +1296,7 @@
Array<Method*>* methods = InstanceKlass::cast(intf)->methods();
if (itable_index < 0 || itable_index >= method_count_for_interface(intf))
- return NULL; // help caller defend against bad indexes
+ return NULL; // help caller defend against bad indices
int index = itable_index;
Method* m = methods->at(index);
--- a/hotspot/src/share/vm/oops/klassVtable.hpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/oops/klassVtable.hpp Wed Oct 09 22:01:59 2013 -0400
@@ -97,6 +97,7 @@
// 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.
+ 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);
bool check_no_old_or_obsolete_entries();
@@ -118,24 +119,28 @@
void put_method_at(Method* m, int index);
static bool needs_new_vtable_entry(methodHandle m, Klass* super, Handle classloader, Symbol* classname, AccessFlags access_flags, TRAPS);
- bool update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS);
+ bool update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len, int default_index, bool checkconstraints, TRAPS);
InstanceKlass* find_transitive_override(InstanceKlass* initialsuper, methodHandle target_method, int vtable_index,
Handle target_loader, Symbol* target_classname, Thread* THREAD);
// support for miranda methods
bool is_miranda_entry_at(int i);
int fill_in_mirandas(int initialized);
- static bool is_miranda(Method* m, Array<Method*>* class_methods, Klass* super);
+ static bool is_miranda(Method* m, Array<Method*>* class_methods,
+ Array<Method*>* default_methods, Klass* super);
static void add_new_mirandas_to_lists(
GrowableArray<Method*>* new_mirandas,
GrowableArray<Method*>* all_mirandas,
- Array<Method*>* current_interface_methods, Array<Method*>* class_methods,
+ Array<Method*>* current_interface_methods,
+ Array<Method*>* class_methods,
+ Array<Method*>* default_methods,
Klass* super);
static void get_mirandas(
GrowableArray<Method*>* new_mirandas,
GrowableArray<Method*>* all_mirandas, Klass* super,
- Array<Method*>* class_methods, Array<Klass*>* local_interfaces);
-
+ Array<Method*>* class_methods,
+ Array<Method*>* default_methods,
+ Array<Klass*>* local_interfaces);
void verify_against(outputStream* st, klassVtable* vt, int index);
inline InstanceKlass* ik() const;
};
@@ -290,7 +295,7 @@
#endif // INCLUDE_JVMTI
// Setup of itable
- static int assign_itable_indexes_for_interface(Klass* klass);
+ static int assign_itable_indices_for_interface(Klass* klass);
static int method_count_for_interface(Klass* klass);
static int compute_itable_size(Array<Klass*>* transitive_interfaces);
static void setup_itable_offset_table(instanceKlassHandle klass);
--- a/hotspot/src/share/vm/oops/method.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/oops/method.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -511,9 +511,9 @@
bool Method::is_final_method(AccessFlags class_access_flags) const {
// or "does_not_require_vtable_entry"
- // overpass can occur, is not final (reuses vtable entry)
+ // default method or overpass can occur, is not final (reuses vtable entry)
// private methods get vtable entries for backward class compatibility.
- if (is_overpass()) return false;
+ if (is_overpass() || is_default_method()) return false;
return is_final() || class_access_flags.is_final();
}
@@ -521,11 +521,24 @@
return is_final_method(method_holder()->access_flags());
}
+bool Method::is_default_method() const {
+ if (method_holder() != NULL &&
+ method_holder()->is_interface() &&
+ !is_abstract()) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
bool Method::can_be_statically_bound(AccessFlags class_access_flags) const {
if (is_final_method(class_access_flags)) return true;
#ifdef ASSERT
+ ResourceMark rm;
bool is_nonv = (vtable_index() == nonvirtual_vtable_index);
- if (class_access_flags.is_interface()) assert(is_nonv == is_static(), err_msg("is_nonv=%s", is_nonv));
+ if (class_access_flags.is_interface()) {
+ assert(is_nonv == is_static(), err_msg("is_nonv=%s", name_and_sig_as_C_string()));
+ }
#endif
assert(valid_vtable_index() || valid_itable_index(), "method must be linked before we ask this question");
return vtable_index() == nonvirtual_vtable_index;
@@ -1371,7 +1384,8 @@
}
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
-void Method::sort_methods(Array<Method*>* methods, bool idempotent) {
+// default_methods also uses this without the ordering for fast find_method
+void Method::sort_methods(Array<Method*>* methods, bool idempotent, bool set_idnums) {
int length = methods->length();
if (length > 1) {
{
@@ -1379,14 +1393,15 @@
QuickSort::sort<Method*>(methods->data(), length, method_comparator, idempotent);
}
// Reset method ordering
- for (int i = 0; i < length; i++) {
- Method* m = methods->at(i);
- m->set_method_idnum(i);
+ if (set_idnums) {
+ for (int i = 0; i < length; i++) {
+ Method* m = methods->at(i);
+ m->set_method_idnum(i);
+ }
}
}
}
-
//-----------------------------------------------------------------------------------
// Non-product code unless JVM/TI needs it
--- a/hotspot/src/share/vm/oops/method.hpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/oops/method.hpp Wed Oct 09 22:01:59 2013 -0400
@@ -567,6 +567,7 @@
// checks method and its method holder
bool is_final_method() const;
bool is_final_method(AccessFlags class_access_flags) const;
+ bool is_default_method() const;
// true if method needs no dynamic dispatch (final and/or no vtable entry)
bool can_be_statically_bound() const;
@@ -846,7 +847,7 @@
#endif
// Helper routine used for method sorting
- static void sort_methods(Array<Method*>* methods, bool idempotent = false);
+ static void sort_methods(Array<Method*>* methods, bool idempotent = false, bool set_idnums = true);
// Deallocation function for redefine classes or if an error occurs
void deallocate_contents(ClassLoaderData* loader_data);
--- a/hotspot/src/share/vm/prims/jni.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/prims/jni.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -1591,10 +1591,8 @@
}
} else {
m = klass->lookup_method(name, signature);
- // Look up interfaces
- if (m == NULL && klass->oop_is_instance()) {
- m = InstanceKlass::cast(klass())->lookup_method_in_all_interfaces(name,
- signature);
+ if (m == NULL && klass->oop_is_instance()) {
+ m = InstanceKlass::cast(klass())->lookup_method_in_ordered_interfaces(name, signature);
}
}
if (m == NULL || (m->is_static() != is_static)) {
--- a/hotspot/src/share/vm/prims/jvm.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -668,13 +668,12 @@
JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth))
JVMWrapper("JVM_GetCallerClass");
- // Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation.
- if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) {
+ // Pre-JDK 8 and early builds of JDK 8 don't have a CallerSensitive annotation; or
+ // sun.reflect.Reflection.getCallerClass with a depth parameter is provided
+ // temporarily for existing code to use until a replacement API is defined.
+ if (SystemDictionary::reflect_CallerSensitive_klass() == NULL || depth != JVM_CALLER_DEPTH) {
Klass* k = thread->security_get_caller_class(depth);
return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror());
- } else {
- // Basic handshaking with Java_sun_reflect_Reflection_getCallerClass
- assert(depth == -1, "wrong handshake depth");
}
// Getting the class of the caller frame.
--- a/hotspot/src/share/vm/prims/jvm.h Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/prims/jvm.h Wed Oct 09 22:01:59 2013 -0400
@@ -374,6 +374,9 @@
/*
* java.lang.Class and java.lang.ClassLoader
*/
+
+#define JVM_CALLER_DEPTH -1
+
/*
* Returns the class in which the code invoking the native method
* belongs.
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -2755,13 +2755,26 @@
// InstanceKlass around to hold obsolete methods so we don't have
// any other InstanceKlass embedded vtables to update. The vtable
// holds the Method*s for virtual (but not final) methods.
- if (ik->vtable_length() > 0 && ik->is_subtype_of(_the_class_oop)) {
+ // Default methods, or concrete methods in interfaces are stored
+ // in the vtable, so if an interface changes we need to check
+ // adjust_method_entries() for every InstanceKlass, which will also
+ // adjust the default method vtable indices.
+ // We also need to adjust any default method entries that are
+ // not yet in the vtable, because the vtable setup is in progress.
+ // This must be done after we adjust the default_methods and
+ // default_vtable_indices for methods already in the vtable.
+ if (ik->vtable_length() > 0 && (_the_class_oop->is_interface()
+ || 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);
}
// If the current class has an itable and we are either redefining an
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -187,12 +187,34 @@
receiver_limit = m->method_holder();
assert(receiver_limit->verify_itable_index(vmindex), "");
flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
+ if (TraceInvokeDynamic) {
+ ResourceMark rm;
+ tty->print_cr("memberName: invokeinterface method_holder::method: %s, receiver: %s, itableindex: %d, access_flags:",
+ Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()),
+ receiver_limit()->internal_name(), vmindex);
+ m->access_flags().print_on(tty);
+ if (!m->is_abstract()) {
+ tty->print("default");
+ }
+ tty->cr();
+ }
break;
case CallInfo::vtable_call:
vmindex = info.vtable_index();
flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
assert(receiver_limit->is_subtype_of(m->method_holder()), "virtual call must be type-safe");
+ if (TraceInvokeDynamic) {
+ ResourceMark rm;
+ tty->print_cr("memberName: invokevirtual method_holder::method: %s, receiver: %s, vtableindex: %d, access_flags:",
+ Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()),
+ receiver_limit()->internal_name(), vmindex);
+ m->access_flags().print_on(tty);
+ if (m->is_default_method()) {
+ tty->print("default");
+ }
+ tty->cr();
+ }
break;
case CallInfo::direct_call:
--- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -2045,6 +2045,9 @@
status = status && verify_interval(StringTableSize, minimumStringTableSize,
(max_uintx / StringTable::bucket_size()), "StringTable size");
+ status = status && verify_interval(SymbolTableSize, minimumSymbolTableSize,
+ (max_uintx / SymbolTable::bucket_size()), "SymbolTable size");
+
if (MinHeapFreeRatio > MaxHeapFreeRatio) {
jio_fprintf(defaultStream::error_stream(),
"MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
--- a/hotspot/src/share/vm/runtime/globals.hpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Oct 09 22:01:59 2013 -0400
@@ -3727,6 +3727,9 @@
product(uintx, StringTableSize, defaultStringTableSize, \
"Number of buckets in the interned String table") \
\
+ experimental(uintx, SymbolTableSize, defaultSymbolTableSize, \
+ "Number of buckets in the JVM internal Symbol table") \
+ \
develop(bool, TraceDefaultMethods, false, \
"Trace the default method processing steps") \
\
--- a/hotspot/src/share/vm/runtime/reflectionUtils.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/runtime/reflectionUtils.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, 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
@@ -27,8 +27,11 @@
#include "memory/universe.inline.hpp"
#include "runtime/reflectionUtils.hpp"
-KlassStream::KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only) {
- _klass = klass;
+KlassStream::KlassStream(instanceKlassHandle klass, bool local_only,
+ bool classes_only, bool walk_defaults) {
+ _klass = _base_klass = klass;
+ _base_class_search_defaults = false;
+ _defaults_checked = false;
if (classes_only) {
_interfaces = Universe::the_empty_klass_array();
} else {
@@ -37,6 +40,7 @@
_interface_index = _interfaces->length();
_local_only = local_only;
_classes_only = classes_only;
+ _walk_defaults = walk_defaults;
}
bool KlassStream::eos() {
@@ -45,7 +49,13 @@
if (!_klass->is_interface() && _klass->super() != NULL) {
// go up superclass chain (not for interfaces)
_klass = _klass->super();
+ // Next for method walks, walk default methods
+ } else if (_walk_defaults && (_defaults_checked == false) && (_base_klass->default_methods() != NULL)) {
+ _base_class_search_defaults = true;
+ _klass = _base_klass;
+ _defaults_checked = true;
} else {
+ // Next walk transitive interfaces
if (_interface_index > 0) {
_klass = _interfaces->at(--_interface_index);
} else {
--- a/hotspot/src/share/vm/runtime/reflectionUtils.hpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/runtime/reflectionUtils.hpp Wed Oct 09 22:01:59 2013 -0400
@@ -38,7 +38,7 @@
// and (super)interfaces. Streaming is done in reverse order (subclasses first,
// interfaces last).
//
-// for (KlassStream st(k, false, false); !st.eos(); st.next()) {
+// for (KlassStream st(k, false, false, false); !st.eos(); st.next()) {
// Klass* k = st.klass();
// ...
// }
@@ -46,17 +46,21 @@
class KlassStream VALUE_OBJ_CLASS_SPEC {
protected:
instanceKlassHandle _klass; // current klass/interface iterated over
- Array<Klass*>* _interfaces; // transitive interfaces for initial class
+ instanceKlassHandle _base_klass; // initial klass/interface to iterate over
+ Array<Klass*>* _interfaces; // transitive interfaces for initial class
int _interface_index; // current interface being processed
bool _local_only; // process initial class/interface only
bool _classes_only; // process classes only (no interfaces)
+ bool _walk_defaults; // process default methods
+ bool _base_class_search_defaults; // time to process default methods
+ bool _defaults_checked; // already checked for default methods
int _index;
- virtual int length() const = 0;
+ virtual int length() = 0;
public:
// constructor
- KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only);
+ KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only, bool walk_defaults);
// testing
bool eos();
@@ -67,6 +71,8 @@
// accessors
instanceKlassHandle klass() const { return _klass; }
int index() const { return _index; }
+ bool base_class_search_defaults() const { return _base_class_search_defaults; }
+ void base_class_search_defaults(bool b) { _base_class_search_defaults = b; }
};
@@ -81,17 +87,24 @@
class MethodStream : public KlassStream {
private:
- int length() const { return methods()->length(); }
- Array<Method*>* methods() const { return _klass->methods(); }
+ int length() { return methods()->length(); }
+ Array<Method*>* methods() {
+ if (base_class_search_defaults()) {
+ base_class_search_defaults(false);
+ return _klass->default_methods();
+ } else {
+ return _klass->methods();
+ }
+ }
public:
MethodStream(instanceKlassHandle klass, bool local_only, bool classes_only)
- : KlassStream(klass, local_only, classes_only) {
+ : KlassStream(klass, local_only, classes_only, true) {
_index = length();
next();
}
void next() { _index--; }
- Method* method() const { return methods()->at(index()); }
+ Method* method() { return methods()->at(index()); }
};
@@ -107,13 +120,13 @@
class FieldStream : public KlassStream {
private:
- int length() const { return _klass->java_fields_count(); }
+ int length() { return _klass->java_fields_count(); }
fieldDescriptor _fd_buf;
public:
FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only)
- : KlassStream(klass, local_only, classes_only) {
+ : KlassStream(klass, local_only, classes_only, false) {
_index = length();
next();
}
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Oct 09 22:01:59 2013 -0400
@@ -27,7 +27,6 @@
#include "classfile/javaClasses.hpp"
#include "classfile/loaderConstraints.hpp"
#include "classfile/placeholders.hpp"
-#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstance.hpp"
@@ -289,6 +288,7 @@
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \
nonstatic_field(InstanceKlass, _array_klasses, Klass*) \
nonstatic_field(InstanceKlass, _methods, Array<Method*>*) \
+ nonstatic_field(InstanceKlass, _default_methods, Array<Method*>*) \
nonstatic_field(InstanceKlass, _local_interfaces, Array<Klass*>*) \
nonstatic_field(InstanceKlass, _transitive_interfaces, Array<Klass*>*) \
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
@@ -323,6 +323,7 @@
nonstatic_field(nmethodBucket, _count, int) \
nonstatic_field(nmethodBucket, _next, nmethodBucket*) \
nonstatic_field(InstanceKlass, _method_ordering, Array<int>*) \
+ nonstatic_field(InstanceKlass, _default_vtable_indices, Array<int>*) \
nonstatic_field(Klass, _super_check_offset, juint) \
nonstatic_field(Klass, _secondary_super_cache, Klass*) \
nonstatic_field(Klass, _secondary_supers, Array<Klass*>*) \
@@ -2247,12 +2248,6 @@
declare_preprocessor_constant("PERFDATA_BIG_ENDIAN", PERFDATA_BIG_ENDIAN) \
declare_preprocessor_constant("PERFDATA_LITTLE_ENDIAN", PERFDATA_LITTLE_ENDIAN) \
\
- /***************/ \
- /* SymbolTable */ \
- /***************/ \
- \
- declare_constant(SymbolTable::symbol_table_size) \
- \
/***********************************/ \
/* LoaderConstraintTable constants */ \
/***********************************/ \
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Wed Oct 09 21:45:28 2013 -0400
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Wed Oct 09 22:01:59 2013 -0400
@@ -333,6 +333,9 @@
const int defaultStringTableSize = NOT_LP64(1009) LP64_ONLY(60013);
const int minimumStringTableSize=1009;
+const int defaultSymbolTableSize = 20011;
+const int minimumSymbolTableSize = 1009;
+
//----------------------------------------------------------------------------------------------------
// HotSwap - for JVMTI aka Class File Replacement and PopFrame