--- old/src/share/vm/oops/typeArrayOop.hpp 2015-11-16 17:05:16.542599672 -0500 +++ new/src/share/vm/oops/typeArrayOop.hpp 2015-11-16 17:05:16.020521721 -0500 @@ -39,7 +39,9 @@ jboolean* bool_base() const { return (jboolean*)base(T_BOOLEAN); } jbyte* byte_base() const { return (jbyte*) base(T_BYTE); } jint* int_base() const { return (jint*) base(T_INT); } + juint* uint_base() const { return (juint*) base(T_INT); } jlong* long_base() const { return (jlong*) base(T_LONG); } + julong* ulong_base() const { return (julong*) base(T_LONG); } jshort* short_base() const { return (jshort*) base(T_SHORT); } jfloat* float_base() const { return (jfloat*) base(T_FLOAT); } jdouble* double_base() const { return (jdouble*) base(T_DOUBLE); } @@ -67,6 +69,11 @@ return &int_base()[which]; } + juint* uint_at_addr(int which) const { + assert(is_within_bounds(which), "index out of bounds"); + return (juint*)&uint_base()[which]; + } + jshort* short_at_addr(int which) const { assert(is_within_bounds(which), "index out of bounds"); return &short_base()[which]; @@ -82,6 +89,11 @@ return &long_base()[which]; } + julong* ulong_at_addr(int which) const { + assert(is_within_bounds(which), "index out of bounds"); + return (julong*) &ulong_base()[which]; + } + jfloat* float_at_addr(int which) const { assert(is_within_bounds(which), "index out of bounds"); return &float_base()[which]; @@ -122,20 +134,20 @@ jbyte byte_at_acquire(int which) const { return OrderAccess::load_acquire(byte_at_addr(which)); } void release_byte_at_put(int which, jbyte contents) { OrderAccess::release_store(byte_at_addr(which), contents); } - // Java thinks metadata arrays are just arrays of either long or int, since + // Java thinks Symbol* arrays are just arrays of either long or int, since // there doesn't seem to be T_ADDRESS, so this is a bit of unfortunate // casting #ifdef _LP64 - Metadata* metadata_at(int which) const { - return (Metadata*)*long_at_addr(which); } - void metadata_at_put(int which, Metadata* contents) { - *long_at_addr(which) = (long)contents; + Symbol* symbol_at(int which) const { + return (Symbol*)*ulong_at_addr(which); } + void symbol_at_put(int which, Symbol* contents) { + *ulong_at_addr(which) = (julong)contents; } #else - Metadata* metadata_at(int which) const { - return (Metadata*)*int_at_addr(which); } - void metadata_at_put(int which, Metadata* contents) { - *int_at_addr(which) = (int)contents; + Symbol* symbol_at(int which) const { + return (Symbol*)*uint_at_addr(which); } + void symbol_at_put(int which, Symbol* contents) { + *uint_at_addr(which) = (juint)contents; } #endif // _LP64 --- old/src/share/vm/memory/oopFactory.hpp 2015-11-16 17:05:16.510333371 -0500 +++ new/src/share/vm/memory/oopFactory.hpp 2015-11-16 17:05:16.021071288 -0500 @@ -62,7 +62,7 @@ static typeArrayOop new_typeArray(BasicType type, int length, TRAPS); static typeArrayOop new_typeArray_nozero(BasicType type, int length, TRAPS); - static typeArrayOop new_metaDataArray(int length, TRAPS); + static typeArrayOop new_symbolArray(int length, TRAPS); // Regular object arrays static objArrayOop new_objArray(Klass* klass, int length, TRAPS); --- old/src/share/vm/memory/oopFactory.cpp 2015-11-16 17:05:16.510329340 -0500 +++ new/src/share/vm/memory/oopFactory.cpp 2015-11-16 17:05:15.954007298 -0500 @@ -57,16 +57,14 @@ return result; } -// Create a Java array that points to metadata. -// As far as Java code is concerned, a metaData array is either an array of -// int or long depending on pointer size. Only a few things use this, like -// stack trace elements in Throwable. They cast Method* into this type. -// Note:can't point to symbols because there's no way to unreference count -// them when this object goes away. -typeArrayOop oopFactory::new_metaDataArray(int length, TRAPS) { +// Create a Java array that points to symbols. +// As far as Java code is concerned, a Symbol array is either an array of +// int or long depending on pointer size. Only stack trace elements in Throwable use +// this. They cast Symbol* into this type. +typeArrayOop oopFactory::new_symbolArray(int length, TRAPS) { BasicType type = LP64_ONLY(T_LONG) NOT_LP64(T_INT); - Klass* type_asKlassOop = Universe::typeArrayKlassObj(type); - TypeArrayKlass* type_asArrayKlass = TypeArrayKlass::cast(type_asKlassOop); + Klass* tk = Universe::typeArrayKlassObj(type); + TypeArrayKlass* type_asArrayKlass = TypeArrayKlass::cast(tk); typeArrayOop result = type_asArrayKlass->allocate_common(length, true, THREAD); return result; } --- old/src/share/vm/classfile/javaClasses.cpp 2015-11-16 17:05:16.510492874 -0500 +++ new/src/share/vm/classfile/javaClasses.cpp 2015-11-16 17:05:16.165778454 -0500 @@ -1362,7 +1362,7 @@ typeArrayOop _methods; typeArrayOop _bcis; objArrayOop _mirrors; - typeArrayOop _cprefs; // needed to insulate method name against redefinition + typeArrayOop _names; // needed to insulate method name against redefinition int _index; No_Safepoint_Verifier _nsv; @@ -1372,7 +1372,7 @@ trace_methods_offset = java_lang_Throwable::trace_methods_offset, trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, - trace_cprefs_offset = java_lang_Throwable::trace_cprefs_offset, + trace_names_offset = java_lang_Throwable::trace_names_offset, trace_next_offset = java_lang_Throwable::trace_next_offset, trace_size = java_lang_Throwable::trace_size, trace_chunk_size = java_lang_Throwable::trace_chunk_size @@ -1394,14 +1394,14 @@ assert(mirrors != NULL, "mirror array should be initialized in backtrace"); return mirrors; } - static typeArrayOop get_cprefs(objArrayHandle chunk) { - typeArrayOop cprefs = typeArrayOop(chunk->obj_at(trace_cprefs_offset)); - assert(cprefs != NULL, "cprefs array should be initialized in backtrace"); - return cprefs; + static typeArrayOop get_names(objArrayHandle chunk) { + typeArrayOop names = typeArrayOop(chunk->obj_at(trace_names_offset)); + assert(names != NULL, "names array should be initialized in backtrace"); + return names; } // constructor for new backtrace - BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) { + BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _names(NULL) { expand(CHECK); _backtrace = _head; _index = 0; @@ -1411,7 +1411,7 @@ _methods = get_methods(backtrace); _bcis = get_bcis(backtrace); _mirrors = get_mirrors(backtrace); - _cprefs = get_cprefs(backtrace); + _names = get_names(backtrace); assert(_methods->length() == _bcis->length() && _methods->length() == _mirrors->length(), "method and source information arrays should match"); @@ -1437,8 +1437,8 @@ objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); objArrayHandle new_mirrors(THREAD, mirrors); - typeArrayOop cprefs = oopFactory::new_shortArray(trace_chunk_size, CHECK); - typeArrayHandle new_cprefs(THREAD, cprefs); + typeArrayOop names = oopFactory::new_symbolArray(trace_chunk_size, CHECK); + typeArrayHandle new_names(THREAD, names); if (!old_head.is_null()) { old_head->obj_at_put(trace_next_offset, new_head()); @@ -1446,13 +1446,13 @@ new_head->obj_at_put(trace_methods_offset, new_methods()); new_head->obj_at_put(trace_bcis_offset, new_bcis()); new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); - new_head->obj_at_put(trace_cprefs_offset, new_cprefs()); + new_head->obj_at_put(trace_names_offset, new_names()); _head = new_head(); _methods = new_methods(); _bcis = new_bcis(); _mirrors = new_mirrors(); - _cprefs = new_cprefs(); + _names = new_names(); _index = 0; } @@ -1474,7 +1474,11 @@ _methods->short_at_put(_index, method->orig_method_idnum()); _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); - _cprefs->short_at_put(_index, method->name_index()); + // We can store Symbol* in the backtrace without additional refcounting because the + // Symbol* for the name is kept alive because the class containing the method is kept + // alive via. the mirror. Since redefinition does not allow deleting methods, the new + // class will also have this name, somewhere, maybe not at the same constant pool index. + _names->symbol_at_put(_index, method->name()); // We need to save the mirrors in the backtrace to keep the class // from being unloaded while we still have this stack trace. @@ -1499,8 +1503,7 @@ } // Print stack trace element to resource allocated buffer -char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, - int method_id, int version, int bci, int cpref) { +char* print_stack_element_to_buffer(Handle mirror, int method_id, int version, int bci, Symbol* name) { // Get strings and string lengths InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); @@ -1509,9 +1512,7 @@ Method* method = holder->method_with_orig_idnum(method_id, version); - // The method can be NULL if the requested class version is gone - Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); - char* method_name = sym->as_C_string(); + char* method_name = name->as_C_string(); buf_len += (int)strlen(method_name); char* source_file_name = NULL; @@ -1554,10 +1555,10 @@ return buf; } -void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, - int method_id, int version, int bci, int cpref) { +void print_stack_element_internal(outputStream *st, Handle mirror, + int method_id, int version, int bci, Symbol* name) { ResourceMark rm; - char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, cpref); + char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, name); st->print_cr("%s", buf); } @@ -1565,12 +1566,8 @@ Handle mirror = method->method_holder()->java_mirror(); int method_id = method->orig_method_idnum(); int version = method->constants()->version(); - int cpref = method->name_index(); - print_stack_element(st, mirror, method_id, version, bci, cpref); -} - -const char* java_lang_Throwable::no_stack_trace_message() { - return "\t<>"; + Symbol *name = method->name(); + print_stack_element_internal(st, mirror, method_id, version, bci, name); } @@ -1581,7 +1578,7 @@ while (h_throwable.not_null()) { objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); if (result.is_null()) { - st->print_raw_cr(no_stack_trace_message()); + st->print_raw_cr("\t<>"); return; } @@ -1591,7 +1588,7 @@ typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); - typeArrayHandle cprefs (THREAD, BacktraceBuilder::get_cprefs(result)); + typeArrayHandle names (THREAD, BacktraceBuilder::get_names(result)); int length = methods()->length(); for (int index = 0; index < length; index++) { @@ -1601,8 +1598,8 @@ int method = methods->short_at(index); int version = version_at(bcis->int_at(index)); int bci = bci_at(bcis->int_at(index)); - int cpref = cprefs->short_at(index); - print_stack_element(st, mirror, method, version, bci, cpref); + Symbol* name = names->symbol_at(index); + print_stack_element_internal(st, mirror, method, version, bci, name); } result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); } @@ -1878,30 +1875,30 @@ if (chunk == NULL) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } - // Get method id, bci, version, mirror and cpref from chunk + // Get method id, bci, version, mirror and name from chunk typeArrayOop methods = BacktraceBuilder::get_methods(chunk); typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); - typeArrayOop cprefs = BacktraceBuilder::get_cprefs(chunk); + typeArrayOop names = BacktraceBuilder::get_names(chunk); assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); int method = methods->short_at(chunk_index); int version = version_at(bcis->int_at(chunk_index)); int bci = bci_at(bcis->int_at(chunk_index)); - int cpref = cprefs->short_at(chunk_index); + Symbol* name = names->symbol_at(chunk_index); Handle mirror(THREAD, mirrors->obj_at(chunk_index)); // Chunk can be partial full if (mirror.is_null()) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } - oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, cpref, CHECK_0); + oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, name, CHECK_0); return element; } oop java_lang_StackTraceElement::create(Handle mirror, int method_id, - int version, int bci, int cpref, TRAPS) { + int version, int bci, Symbol* name, TRAPS) { // Allocate java.lang.StackTraceElement instance Klass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); @@ -1918,15 +1915,13 @@ oop classname = StringTable::intern((char*) str, CHECK_0); java_lang_StackTraceElement::set_declaringClass(element(), classname); - Method* method = holder->method_with_orig_idnum(method_id, version); - - // The method can be NULL if the requested class version is gone - Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); // Fill in method name - oop methodname = StringTable::intern(sym, CHECK_0); + oop methodname = StringTable::intern(name, CHECK_0); java_lang_StackTraceElement::set_methodName(element(), methodname); + // The method can be NULL if the requested class version is gone + Method* method = holder->method_with_orig_idnum(method_id, version); if (!version_matches(method, version)) { // The method was redefined, accurate line number information isn't available java_lang_StackTraceElement::set_fileName(element(), NULL); @@ -1948,8 +1943,8 @@ oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { Handle mirror (THREAD, method->method_holder()->java_mirror()); int method_id = method->orig_method_idnum(); - int cpref = method->name_index(); - return create(mirror, method_id, method->constants()->version(), bci, cpref, THREAD); + Symbol* name = method->name(); + return create(mirror, method_id, method->constants()->version(), bci, name, THREAD); } void java_lang_reflect_AccessibleObject::compute_offsets() { --- old/src/share/vm/classfile/javaClasses.hpp 2015-11-16 17:05:16.542613731 -0500 +++ new/src/share/vm/classfile/javaClasses.hpp 2015-11-16 17:05:16.020532573 -0500 @@ -496,7 +496,7 @@ trace_methods_offset = 0, trace_bcis_offset = 1, trace_mirrors_offset = 2, - trace_cprefs_offset = 3, + trace_names_offset = 3, trace_next_offset = 4, trace_size = 5, trace_chunk_size = 32 @@ -508,12 +508,8 @@ static int stackTrace_offset; static int static_unassigned_stacktrace_offset; - // Printing - static char* print_stack_element_to_buffer(Handle mirror, int method, int version, int bci, int cpref); // StackTrace (programmatic access, new since 1.4) static void clear_stacktrace(oop throwable); - // No stack trace available - static const char* no_stack_trace_message(); // Stacktrace (post JDK 1.7.0 to allow immutability protocol to be followed) static void set_stacktrace(oop throwable, oop st_element_array); static oop unassigned_stacktrace(); @@ -530,10 +526,7 @@ static oop message(Handle throwable); static void set_message(oop throwable, oop value); static Symbol* detail_message(oop throwable); - static void print_stack_element(outputStream *st, Handle mirror, int method, - int version, int bci, int cpref); static void print_stack_element(outputStream *st, const methodHandle& method, int bci); - static void print_stack_usage(Handle stream); // Allocate space for backtrace (created but stack trace not filled in) static void allocate_backtrace(Handle throwable, TRAPS); @@ -1346,7 +1339,7 @@ static void set_lineNumber(oop element, int value); // Create an instance of StackTraceElement - static oop create(Handle mirror, int method, int version, int bci, int cpref, TRAPS); + static oop create(Handle mirror, int method, int version, int bci, Symbol* name, TRAPS); static oop create(const methodHandle& method, int bci, TRAPS); // Debugging