# HG changeset patch # User Christos Kotselidis # Date 1375462985 -7200 # Node ID 97e282186b5be1aa86cecbd3ded459456598cac2 # Parent b43bc053ce8f54e7573d8198c8348e20414bf173 Add heap sanity checker with premature hard crash for debugging write barriers diff -r b43bc053ce8f -r 97e282186b5b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Aug 02 18:29:49 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Aug 02 19:03:05 2013 +0200 @@ -506,6 +506,7 @@ public long vmErrorAddress; public long writeBarrierPreAddress; public long writeBarrierPostAddress; + public long validateObject; public long javaTimeMillisAddress; public long javaTimeNanosAddress; public long arithmeticSinAddress; diff -r b43bc053ce8f -r 97e282186b5b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Aug 02 18:29:49 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Aug 02 19:03:05 2013 +0200 @@ -311,6 +311,8 @@ linkForeignCall(r, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF, NOT_REEXECUTABLE, NO_LOCATIONS); linkForeignCall(r, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); linkForeignCall(r, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(r, VALIDATEOBJECT, c.validateObject, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + if (IntrinsifyObjectMethods.getValue()) { r.registerSubstitutions(ObjectSubstitutions.class); } diff -r b43bc053ce8f -r 97e282186b5b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Aug 02 18:29:49 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Aug 02 19:03:05 2013 +0200 @@ -160,6 +160,7 @@ Object fixedValue = FixedValueAnchorNode.getObject(value); verifyOop(fixedObject); verifyOop(fixedValue); + validateObject(fixedObject, fixedValue); Word oop; if (usePrecise) { oop = (Word) Word.fromArray(fixedObject, location); @@ -409,4 +410,23 @@ private static boolean traceBarrier() { return GraalOptions.GCDebugStartCycle.getValue() > 0 && ((int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress()).readLong(0) > GraalOptions.GCDebugStartCycle.getValue()); } + + /** + * Validation helper method which performs sanity checks on write operations. The addresses of + * both the object and the value being written are checked in order to determine if they reside + * in a valid heap region. If an object is stale, an invalid access is performed in order to + * prematurely crash the VM and debug the stack trace of the faulty method. + */ + private static void validateObject(Object parent, Object child) { + if (child != null && !validateOop(VALIDATEOBJECT, parent, child)) { + log(true, "Verification ERROR, Parent: %p Child: %p\n", Word.fromObject(parent).rawValue(), Word.fromObject(child).rawValue()); + DirectObjectStoreNode.storeWord(null, 0, 0, Word.zero()); + } + } + + public static final ForeignCallDescriptor VALIDATEOBJECT = new ForeignCallDescriptor("validate_object", boolean.class, Word.class, Word.class); + + @NodeIntrinsic(ForeignCallNode.class) + private static native boolean validateOop(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object parent, Object object); + } diff -r b43bc053ce8f -r 97e282186b5b src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Aug 02 18:29:49 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Aug 02 19:03:05 2013 +0200 @@ -859,6 +859,7 @@ set_address("writeBarrierPreAddress", GraalRuntime::write_barrier_pre); set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post); set_address("gcTotalCollectionsAddress", (jlong)(address)(Universe::heap()->total_collections_address())); + set_address("validateObject", GraalRuntime::validate_object); BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) { diff -r b43bc053ce8f -r 97e282186b5b src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Fri Aug 02 18:29:49 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Fri Aug 02 19:03:05 2013 +0200 @@ -372,6 +372,21 @@ thread->dirty_card_queue().enqueue(card_addr); JRT_END +JRT_LEAF(jboolean, GraalRuntime::validate_object(JavaThread* thread,oopDesc* parent, oopDesc* child)) + bool ret = true; + if(!Universe::heap()->is_in_closed_subset(parent)) { + tty->print_cr("Parent Object "INTPTR_FORMAT" not in heap", parent); + parent->print(); + ret=false; + } + if(!Universe::heap()->is_in_closed_subset(child)) { + tty->print_cr("Child Object "INTPTR_FORMAT" not in heap", child); + child->print(); + ret=false; + } + return (jint)ret; +JRT_END + JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oop where, oop format, jlong value)) ResourceMark rm; assert(where == NULL || java_lang_String::is_instance(where), "must be"); diff -r b43bc053ce8f -r 97e282186b5b src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Fri Aug 02 18:29:49 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Fri Aug 02 19:03:05 2013 +0200 @@ -55,6 +55,7 @@ static void log_object(JavaThread* thread, oop msg, jint flags); static void write_barrier_pre(JavaThread* thread, oopDesc* obj); static void write_barrier_post(JavaThread* thread, void* card); + static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child); }; #endif // SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP