# HG changeset patch # User kvn # Date 1280510475 25200 # Node ID 4846648c4b7bbda49e603d870c25da6516701799 # Parent bfbfaacd23e5e72246c0aa7f844c54c2259dc6c7 6973308: Missing zero length check before repne scas in check_klass_subtype_slow_path() Summary: set Z = 0 (not equal) before repne_scan() to indicate that class was not found when RCX == 0. Reviewed-by: never, phh diff -r bfbfaacd23e5 -r 4846648c4b7b hotspot/src/cpu/x86/vm/assembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Mon Jul 26 15:58:07 2010 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Jul 30 10:21:15 2010 -0700 @@ -7568,21 +7568,27 @@ // Scan RCX words at [RDI] for an occurrence of RAX. // Set NZ/Z based on last compare. + // Z flag value will not be set by 'repne' if RCX == 0 since 'repne' does + // not change flags (only scas instruction which is repeated sets flags). + // Set Z = 0 (not equal) before 'repne' to indicate that class was not found. #ifdef _LP64 // This part is tricky, as values in supers array could be 32 or 64 bit wide // and we store values in objArrays always encoded, thus we need to encode // the value of rax before repne. Note that rax is dead after the repne. if (UseCompressedOops) { - encode_heap_oop_not_null(rax); + encode_heap_oop_not_null(rax); // Changes flags. // The superclass is never null; it would be a basic system error if a null // pointer were to sneak in here. Note that we have already loaded the // Klass::super_check_offset from the super_klass in the fast path, // so if there is a null in that register, we are already in the afterlife. + testl(rax,rax); // Set Z = 0 repne_scanl(); } else #endif // _LP64 + { + testptr(rax,rax); // Set Z = 0 repne_scan(); - + } // Unspill the temp. registers: if (pushed_rdi) pop(rdi); if (pushed_rcx) pop(rcx); @@ -8257,30 +8263,35 @@ } } +#ifdef ASSERT +void MacroAssembler::verify_heapbase(const char* msg) { + assert (UseCompressedOops, "should be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + if (CheckCompressedOops) { + Label ok; + push(rscratch1); // cmpptr trashes rscratch1 + cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); + jcc(Assembler::equal, ok); + stop(msg); + bind(ok); + pop(rscratch1); + } +} +#endif + // Algorithm must match oop.inline.hpp encode_heap_oop. void MacroAssembler::encode_heap_oop(Register r) { - assert (UseCompressedOops, "should be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); +#ifdef ASSERT + verify_heapbase("MacroAssembler::encode_heap_oop: heap base corrupted?"); +#endif + verify_oop(r, "broken oop in encode_heap_oop"); if (Universe::narrow_oop_base() == NULL) { - verify_oop(r, "broken oop in encode_heap_oop"); if (Universe::narrow_oop_shift() != 0) { assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); shrq(r, LogMinObjAlignmentInBytes); } return; } -#ifdef ASSERT - if (CheckCompressedOops) { - Label ok; - push(rscratch1); // cmpptr trashes rscratch1 - cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); - jcc(Assembler::equal, ok); - stop("MacroAssembler::encode_heap_oop: heap base corrupted?"); - bind(ok); - pop(rscratch1); - } -#endif - verify_oop(r, "broken oop in encode_heap_oop"); testq(r, r); cmovq(Assembler::equal, r, r12_heapbase); subq(r, r12_heapbase); @@ -8288,9 +8299,8 @@ } void MacroAssembler::encode_heap_oop_not_null(Register r) { - assert (UseCompressedOops, "should be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); #ifdef ASSERT + verify_heapbase("MacroAssembler::encode_heap_oop_not_null: heap base corrupted?"); if (CheckCompressedOops) { Label ok; testq(r, r); @@ -8310,9 +8320,8 @@ } void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { - assert (UseCompressedOops, "should be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); #ifdef ASSERT + verify_heapbase("MacroAssembler::encode_heap_oop_not_null2: heap base corrupted?"); if (CheckCompressedOops) { Label ok; testq(src, src); @@ -8335,40 +8344,21 @@ } void MacroAssembler::decode_heap_oop(Register r) { - assert (UseCompressedOops, "should be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); +#ifdef ASSERT + verify_heapbase("MacroAssembler::decode_heap_oop: heap base corrupted?"); +#endif if (Universe::narrow_oop_base() == NULL) { if (Universe::narrow_oop_shift() != 0) { assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); shlq(r, LogMinObjAlignmentInBytes); } - verify_oop(r, "broken oop in decode_heap_oop"); - return; - } -#ifdef ASSERT - if (CheckCompressedOops) { - Label ok; - push(rscratch1); - cmpptr(r12_heapbase, - ExternalAddress((address)Universe::narrow_oop_base_addr())); - jcc(Assembler::equal, ok); - stop("MacroAssembler::decode_heap_oop: heap base corrupted?"); - bind(ok); - pop(rscratch1); - } -#endif - - Label done; - shlq(r, LogMinObjAlignmentInBytes); - jccb(Assembler::equal, done); - addq(r, r12_heapbase); -#if 0 - // alternate decoding probably a wash. - testq(r, r); - jccb(Assembler::equal, done); - leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); -#endif - bind(done); + } else { + Label done; + shlq(r, LogMinObjAlignmentInBytes); + jccb(Assembler::equal, done); + addq(r, r12_heapbase); + bind(done); + } verify_oop(r, "broken oop in decode_heap_oop"); } @@ -8410,9 +8400,11 @@ addq(dst, r12_heapbase); } } - } else if (dst != src) { + } else { assert (Universe::narrow_oop_base() == NULL, "sanity"); - movq(dst, src); + if (dst != src) { + movq(dst, src); + } } } diff -r bfbfaacd23e5 -r 4846648c4b7b hotspot/src/cpu/x86/vm/assembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Mon Jul 26 15:58:07 2010 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Jul 30 10:21:15 2010 -0700 @@ -1714,6 +1714,9 @@ // if heap base register is used - reinit it with the correct value void reinit_heapbase(); + + DEBUG_ONLY(void verify_heapbase(const char* msg);) + #endif // _LP64 // Int division/remainder for Java diff -r bfbfaacd23e5 -r 4846648c4b7b hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Mon Jul 26 15:58:07 2010 -0700 +++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Jul 30 10:21:15 2010 -0700 @@ -2442,6 +2442,10 @@ "Call fatal if this exception is thrown. Example: " \ "java -XX:AbortVMOnException=java.lang.NullPointerException Foo") \ \ + notproduct(ccstr, AbortVMOnExceptionMessage, NULL, \ + "Call fatal if the exception pointed by AbortVMOnException " \ + "has this message.") \ + \ develop(bool, DebugVtables, false, \ "add debugging code to vtable dispatch") \ \ diff -r bfbfaacd23e5 -r 4846648c4b7b hotspot/src/share/vm/utilities/exceptions.cpp --- a/hotspot/src/share/vm/utilities/exceptions.cpp Mon Jul 26 15:58:07 2010 -0700 +++ b/hotspot/src/share/vm/utilities/exceptions.cpp Fri Jul 30 10:21:15 2010 -0700 @@ -117,7 +117,7 @@ (address)h_exception(), file, line, thread); } // for AbortVMOnException flag - NOT_PRODUCT(Exceptions::debug_check_abort(h_exception)); + NOT_PRODUCT(Exceptions::debug_check_abort(h_exception, message)); // Check for special boot-strapping/vm-thread handling if (special_exception(thread, file, line, h_exception)) return; @@ -375,17 +375,26 @@ #ifndef PRODUCT // caller frees value_string if necessary -void Exceptions::debug_check_abort(const char *value_string) { +void Exceptions::debug_check_abort(const char *value_string, const char* message) { if (AbortVMOnException != NULL && value_string != NULL && strstr(value_string, AbortVMOnException)) { - fatal(err_msg("Saw %s, aborting", value_string)); + if (AbortVMOnExceptionMessage == NULL || message == NULL || + strcmp(message, AbortVMOnExceptionMessage) == 0) { + fatal(err_msg("Saw %s, aborting", value_string)); + } } } -void Exceptions::debug_check_abort(Handle exception) { +void Exceptions::debug_check_abort(Handle exception, const char* message) { if (AbortVMOnException != NULL) { ResourceMark rm; - debug_check_abort(instanceKlass::cast(exception()->klass())->external_name()); + if (message == NULL && exception->is_a(SystemDictionary::Throwable_klass())) { + oop msg = java_lang_Throwable::message(exception); + if (msg != NULL) { + message = java_lang_String::as_utf8_string(msg); + } + } + debug_check_abort(instanceKlass::cast(exception()->klass())->external_name(), message); } } #endif diff -r bfbfaacd23e5 -r 4846648c4b7b hotspot/src/share/vm/utilities/exceptions.hpp --- a/hotspot/src/share/vm/utilities/exceptions.hpp Mon Jul 26 15:58:07 2010 -0700 +++ b/hotspot/src/share/vm/utilities/exceptions.hpp Fri Jul 30 10:21:15 2010 -0700 @@ -143,8 +143,8 @@ static void throw_stack_overflow_exception(Thread* thread, const char* file, int line); // for AbortVMOnException flag - NOT_PRODUCT(static void debug_check_abort(Handle exception);) - NOT_PRODUCT(static void debug_check_abort(const char *value_string);) + NOT_PRODUCT(static void debug_check_abort(Handle exception, const char* message = NULL);) + NOT_PRODUCT(static void debug_check_abort(const char *value_string, const char* message = NULL);) }; diff -r bfbfaacd23e5 -r 4846648c4b7b hotspot/src/share/vm/utilities/vmError.cpp --- a/hotspot/src/share/vm/utilities/vmError.cpp Mon Jul 26 15:58:07 2010 -0700 +++ b/hotspot/src/share/vm/utilities/vmError.cpp Fri Jul 30 10:21:15 2010 -0700 @@ -479,8 +479,8 @@ if (fr.sp()) { st->print(", sp=" PTR_FORMAT, fr.sp()); - st->print(", free space=%" INTPTR_FORMAT "k", - ((intptr_t)fr.sp() - (intptr_t)stack_bottom) >> 10); + size_t free_stack_size = pointer_delta(fr.sp(), stack_bottom, 1024); + st->print(", free space=" SIZE_FORMAT "k", free_stack_size); } st->cr();