Fri, 30 Jul 2010 10:21:15 -0700
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
1.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Mon Jul 26 15:58:07 2010 -0700 1.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Fri Jul 30 10:21:15 2010 -0700 1.3 @@ -7568,21 +7568,27 @@ 1.4 1.5 // Scan RCX words at [RDI] for an occurrence of RAX. 1.6 // Set NZ/Z based on last compare. 1.7 + // Z flag value will not be set by 'repne' if RCX == 0 since 'repne' does 1.8 + // not change flags (only scas instruction which is repeated sets flags). 1.9 + // Set Z = 0 (not equal) before 'repne' to indicate that class was not found. 1.10 #ifdef _LP64 1.11 // This part is tricky, as values in supers array could be 32 or 64 bit wide 1.12 // and we store values in objArrays always encoded, thus we need to encode 1.13 // the value of rax before repne. Note that rax is dead after the repne. 1.14 if (UseCompressedOops) { 1.15 - encode_heap_oop_not_null(rax); 1.16 + encode_heap_oop_not_null(rax); // Changes flags. 1.17 // The superclass is never null; it would be a basic system error if a null 1.18 // pointer were to sneak in here. Note that we have already loaded the 1.19 // Klass::super_check_offset from the super_klass in the fast path, 1.20 // so if there is a null in that register, we are already in the afterlife. 1.21 + testl(rax,rax); // Set Z = 0 1.22 repne_scanl(); 1.23 } else 1.24 #endif // _LP64 1.25 + { 1.26 + testptr(rax,rax); // Set Z = 0 1.27 repne_scan(); 1.28 - 1.29 + } 1.30 // Unspill the temp. registers: 1.31 if (pushed_rdi) pop(rdi); 1.32 if (pushed_rcx) pop(rcx); 1.33 @@ -8257,30 +8263,35 @@ 1.34 } 1.35 } 1.36 1.37 +#ifdef ASSERT 1.38 +void MacroAssembler::verify_heapbase(const char* msg) { 1.39 + assert (UseCompressedOops, "should be compressed"); 1.40 + assert (Universe::heap() != NULL, "java heap should be initialized"); 1.41 + if (CheckCompressedOops) { 1.42 + Label ok; 1.43 + push(rscratch1); // cmpptr trashes rscratch1 1.44 + cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); 1.45 + jcc(Assembler::equal, ok); 1.46 + stop(msg); 1.47 + bind(ok); 1.48 + pop(rscratch1); 1.49 + } 1.50 +} 1.51 +#endif 1.52 + 1.53 // Algorithm must match oop.inline.hpp encode_heap_oop. 1.54 void MacroAssembler::encode_heap_oop(Register r) { 1.55 - assert (UseCompressedOops, "should be compressed"); 1.56 - assert (Universe::heap() != NULL, "java heap should be initialized"); 1.57 +#ifdef ASSERT 1.58 + verify_heapbase("MacroAssembler::encode_heap_oop: heap base corrupted?"); 1.59 +#endif 1.60 + verify_oop(r, "broken oop in encode_heap_oop"); 1.61 if (Universe::narrow_oop_base() == NULL) { 1.62 - verify_oop(r, "broken oop in encode_heap_oop"); 1.63 if (Universe::narrow_oop_shift() != 0) { 1.64 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); 1.65 shrq(r, LogMinObjAlignmentInBytes); 1.66 } 1.67 return; 1.68 } 1.69 -#ifdef ASSERT 1.70 - if (CheckCompressedOops) { 1.71 - Label ok; 1.72 - push(rscratch1); // cmpptr trashes rscratch1 1.73 - cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); 1.74 - jcc(Assembler::equal, ok); 1.75 - stop("MacroAssembler::encode_heap_oop: heap base corrupted?"); 1.76 - bind(ok); 1.77 - pop(rscratch1); 1.78 - } 1.79 -#endif 1.80 - verify_oop(r, "broken oop in encode_heap_oop"); 1.81 testq(r, r); 1.82 cmovq(Assembler::equal, r, r12_heapbase); 1.83 subq(r, r12_heapbase); 1.84 @@ -8288,9 +8299,8 @@ 1.85 } 1.86 1.87 void MacroAssembler::encode_heap_oop_not_null(Register r) { 1.88 - assert (UseCompressedOops, "should be compressed"); 1.89 - assert (Universe::heap() != NULL, "java heap should be initialized"); 1.90 #ifdef ASSERT 1.91 + verify_heapbase("MacroAssembler::encode_heap_oop_not_null: heap base corrupted?"); 1.92 if (CheckCompressedOops) { 1.93 Label ok; 1.94 testq(r, r); 1.95 @@ -8310,9 +8320,8 @@ 1.96 } 1.97 1.98 void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { 1.99 - assert (UseCompressedOops, "should be compressed"); 1.100 - assert (Universe::heap() != NULL, "java heap should be initialized"); 1.101 #ifdef ASSERT 1.102 + verify_heapbase("MacroAssembler::encode_heap_oop_not_null2: heap base corrupted?"); 1.103 if (CheckCompressedOops) { 1.104 Label ok; 1.105 testq(src, src); 1.106 @@ -8335,40 +8344,21 @@ 1.107 } 1.108 1.109 void MacroAssembler::decode_heap_oop(Register r) { 1.110 - assert (UseCompressedOops, "should be compressed"); 1.111 - assert (Universe::heap() != NULL, "java heap should be initialized"); 1.112 +#ifdef ASSERT 1.113 + verify_heapbase("MacroAssembler::decode_heap_oop: heap base corrupted?"); 1.114 +#endif 1.115 if (Universe::narrow_oop_base() == NULL) { 1.116 if (Universe::narrow_oop_shift() != 0) { 1.117 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); 1.118 shlq(r, LogMinObjAlignmentInBytes); 1.119 } 1.120 - verify_oop(r, "broken oop in decode_heap_oop"); 1.121 - return; 1.122 - } 1.123 -#ifdef ASSERT 1.124 - if (CheckCompressedOops) { 1.125 - Label ok; 1.126 - push(rscratch1); 1.127 - cmpptr(r12_heapbase, 1.128 - ExternalAddress((address)Universe::narrow_oop_base_addr())); 1.129 - jcc(Assembler::equal, ok); 1.130 - stop("MacroAssembler::decode_heap_oop: heap base corrupted?"); 1.131 - bind(ok); 1.132 - pop(rscratch1); 1.133 - } 1.134 -#endif 1.135 - 1.136 - Label done; 1.137 - shlq(r, LogMinObjAlignmentInBytes); 1.138 - jccb(Assembler::equal, done); 1.139 - addq(r, r12_heapbase); 1.140 -#if 0 1.141 - // alternate decoding probably a wash. 1.142 - testq(r, r); 1.143 - jccb(Assembler::equal, done); 1.144 - leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); 1.145 -#endif 1.146 - bind(done); 1.147 + } else { 1.148 + Label done; 1.149 + shlq(r, LogMinObjAlignmentInBytes); 1.150 + jccb(Assembler::equal, done); 1.151 + addq(r, r12_heapbase); 1.152 + bind(done); 1.153 + } 1.154 verify_oop(r, "broken oop in decode_heap_oop"); 1.155 } 1.156 1.157 @@ -8410,9 +8400,11 @@ 1.158 addq(dst, r12_heapbase); 1.159 } 1.160 } 1.161 - } else if (dst != src) { 1.162 + } else { 1.163 assert (Universe::narrow_oop_base() == NULL, "sanity"); 1.164 - movq(dst, src); 1.165 + if (dst != src) { 1.166 + movq(dst, src); 1.167 + } 1.168 } 1.169 } 1.170
2.1 --- a/src/cpu/x86/vm/assembler_x86.hpp Mon Jul 26 15:58:07 2010 -0700 2.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp Fri Jul 30 10:21:15 2010 -0700 2.3 @@ -1714,6 +1714,9 @@ 2.4 2.5 // if heap base register is used - reinit it with the correct value 2.6 void reinit_heapbase(); 2.7 + 2.8 + DEBUG_ONLY(void verify_heapbase(const char* msg);) 2.9 + 2.10 #endif // _LP64 2.11 2.12 // Int division/remainder for Java
3.1 --- a/src/share/vm/runtime/globals.hpp Mon Jul 26 15:58:07 2010 -0700 3.2 +++ b/src/share/vm/runtime/globals.hpp Fri Jul 30 10:21:15 2010 -0700 3.3 @@ -2442,6 +2442,10 @@ 3.4 "Call fatal if this exception is thrown. Example: " \ 3.5 "java -XX:AbortVMOnException=java.lang.NullPointerException Foo") \ 3.6 \ 3.7 + notproduct(ccstr, AbortVMOnExceptionMessage, NULL, \ 3.8 + "Call fatal if the exception pointed by AbortVMOnException " \ 3.9 + "has this message.") \ 3.10 + \ 3.11 develop(bool, DebugVtables, false, \ 3.12 "add debugging code to vtable dispatch") \ 3.13 \
4.1 --- a/src/share/vm/utilities/exceptions.cpp Mon Jul 26 15:58:07 2010 -0700 4.2 +++ b/src/share/vm/utilities/exceptions.cpp Fri Jul 30 10:21:15 2010 -0700 4.3 @@ -117,7 +117,7 @@ 4.4 (address)h_exception(), file, line, thread); 4.5 } 4.6 // for AbortVMOnException flag 4.7 - NOT_PRODUCT(Exceptions::debug_check_abort(h_exception)); 4.8 + NOT_PRODUCT(Exceptions::debug_check_abort(h_exception, message)); 4.9 4.10 // Check for special boot-strapping/vm-thread handling 4.11 if (special_exception(thread, file, line, h_exception)) return; 4.12 @@ -375,17 +375,26 @@ 4.13 4.14 #ifndef PRODUCT 4.15 // caller frees value_string if necessary 4.16 -void Exceptions::debug_check_abort(const char *value_string) { 4.17 +void Exceptions::debug_check_abort(const char *value_string, const char* message) { 4.18 if (AbortVMOnException != NULL && value_string != NULL && 4.19 strstr(value_string, AbortVMOnException)) { 4.20 - fatal(err_msg("Saw %s, aborting", value_string)); 4.21 + if (AbortVMOnExceptionMessage == NULL || message == NULL || 4.22 + strcmp(message, AbortVMOnExceptionMessage) == 0) { 4.23 + fatal(err_msg("Saw %s, aborting", value_string)); 4.24 + } 4.25 } 4.26 } 4.27 4.28 -void Exceptions::debug_check_abort(Handle exception) { 4.29 +void Exceptions::debug_check_abort(Handle exception, const char* message) { 4.30 if (AbortVMOnException != NULL) { 4.31 ResourceMark rm; 4.32 - debug_check_abort(instanceKlass::cast(exception()->klass())->external_name()); 4.33 + if (message == NULL && exception->is_a(SystemDictionary::Throwable_klass())) { 4.34 + oop msg = java_lang_Throwable::message(exception); 4.35 + if (msg != NULL) { 4.36 + message = java_lang_String::as_utf8_string(msg); 4.37 + } 4.38 + } 4.39 + debug_check_abort(instanceKlass::cast(exception()->klass())->external_name(), message); 4.40 } 4.41 } 4.42 #endif
5.1 --- a/src/share/vm/utilities/exceptions.hpp Mon Jul 26 15:58:07 2010 -0700 5.2 +++ b/src/share/vm/utilities/exceptions.hpp Fri Jul 30 10:21:15 2010 -0700 5.3 @@ -143,8 +143,8 @@ 5.4 static void throw_stack_overflow_exception(Thread* thread, const char* file, int line); 5.5 5.6 // for AbortVMOnException flag 5.7 - NOT_PRODUCT(static void debug_check_abort(Handle exception);) 5.8 - NOT_PRODUCT(static void debug_check_abort(const char *value_string);) 5.9 + NOT_PRODUCT(static void debug_check_abort(Handle exception, const char* message = NULL);) 5.10 + NOT_PRODUCT(static void debug_check_abort(const char *value_string, const char* message = NULL);) 5.11 }; 5.12 5.13
6.1 --- a/src/share/vm/utilities/vmError.cpp Mon Jul 26 15:58:07 2010 -0700 6.2 +++ b/src/share/vm/utilities/vmError.cpp Fri Jul 30 10:21:15 2010 -0700 6.3 @@ -479,8 +479,8 @@ 6.4 6.5 if (fr.sp()) { 6.6 st->print(", sp=" PTR_FORMAT, fr.sp()); 6.7 - st->print(", free space=%" INTPTR_FORMAT "k", 6.8 - ((intptr_t)fr.sp() - (intptr_t)stack_bottom) >> 10); 6.9 + size_t free_stack_size = pointer_delta(fr.sp(), stack_bottom, 1024); 6.10 + st->print(", free space=" SIZE_FORMAT "k", free_stack_size); 6.11 } 6.12 6.13 st->cr();