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
--- 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);
+ }
}
}
--- 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
--- 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") \
\
--- 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
--- 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);)
};
--- 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();