8227766: CheckUnhandledOops is broken in MemAllocator
authorcoleenp
Thu, 18 Jul 2019 07:06:33 -0400 (2019-07-18)
changeset 55734 51f5b4c29626
parent 55733 9cfb9387a9e8
child 55735 08893cf52ee9
8227766: CheckUnhandledOops is broken in MemAllocator Summary: Save oop created in handle more eagerly, so CheckUnhandledOops doesn't bash it. Reviewed-by: lfoltan, eosterlund
src/hotspot/share/classfile/stringTable.cpp
src/hotspot/share/gc/shared/memAllocator.cpp
src/hotspot/share/runtime/javaCalls.cpp
src/hotspot/share/runtime/unhandledOops.cpp
src/hotspot/share/services/gcNotifier.cpp
test/hotspot/jtreg/runtime/CheckUnhandledOops/TestOutOfMemory.java
--- a/src/hotspot/share/classfile/stringTable.cpp	Thu Jul 18 10:25:49 2019 +0200
+++ b/src/hotspot/share/classfile/stringTable.cpp	Thu Jul 18 07:06:33 2019 -0400
@@ -342,7 +342,7 @@
   if (found_string != NULL) {
     return found_string;
   }
-  return do_intern(string_or_null_h, name, len, hash, CHECK_NULL);
+  return do_intern(string_or_null_h, name, len, hash, THREAD);
 }
 
 oop StringTable::do_intern(Handle string_or_null_h, const jchar* name,
--- a/src/hotspot/share/gc/shared/memAllocator.cpp	Thu Jul 18 10:25:49 2019 +0200
+++ b/src/hotspot/share/gc/shared/memAllocator.cpp	Thu Jul 18 07:06:33 2019 -0400
@@ -370,6 +370,10 @@
     HeapWord* mem = mem_allocate(allocation);
     if (mem != NULL) {
       obj = initialize(mem);
+    } else {
+      // The unhandled oop detector will poison local variable obj,
+      // so reset it to NULL if mem is NULL.
+      obj = NULL;
     }
   }
   return obj;
--- a/src/hotspot/share/runtime/javaCalls.cpp	Thu Jul 18 10:25:49 2019 +0200
+++ b/src/hotspot/share/runtime/javaCalls.cpp	Thu Jul 18 07:06:33 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -346,9 +346,6 @@
   assert(!SafepointSynchronize::is_at_safepoint(), "call to Java code during VM operation");
   assert(!thread->handle_area()->no_handle_mark_active(), "cannot call out to Java here");
 
-
-  CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();)
-
 #if INCLUDE_JVMCI
   // Gets the nmethod (if any) that should be called instead of normal target
   nmethod* alternative_target = args->alternative_target();
@@ -395,10 +392,6 @@
   BasicType result_type = runtime_type_from(result);
   bool oop_result_flag = (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY);
 
-  // NOTE: if we move the computation of the result_val_address inside
-  // the call to call_stub, the optimizer produces wrong code.
-  intptr_t* result_val_address = (intptr_t*)(result->get_value_addr());
-
   // Find receiver
   Handle receiver = (!method->is_static()) ? args->receiver() : Handle();
 
@@ -436,6 +429,11 @@
   { JavaCallWrapper link(method, receiver, result, CHECK);
     { HandleMark hm(thread);  // HandleMark used by HandleMarkCleaner
 
+      // NOTE: if we move the computation of the result_val_address inside
+      // the call to call_stub, the optimizer produces wrong code.
+      intptr_t* result_val_address = (intptr_t*)(result->get_value_addr());
+      intptr_t* parameter_address = args->parameters();
+
       StubRoutines::call_stub()(
         (address)&link,
         // (intptr_t*)&(result->_value), // see NOTE above (compiler problem)
@@ -443,7 +441,7 @@
         result_type,
         method(),
         entry_point,
-        args->parameters(),
+        parameter_address,
         args->size_of_parameters(),
         CHECK
       );
--- a/src/hotspot/share/runtime/unhandledOops.cpp	Thu Jul 18 10:25:49 2019 +0200
+++ b/src/hotspot/share/runtime/unhandledOops.cpp	Thu Jul 18 07:06:33 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,15 +55,15 @@
 
 // For debugging unhandled oop detector _in the debugger_
 // You don't want to turn it on in compiled code here.
-static bool unhandled_oop_print=0;
+static Thread* unhandled_oop_print = NULL;
 
 void UnhandledOops::register_unhandled_oop(oop* op, address pc) {
   if (!_thread->is_in_stack((address)op))
     return;
 
-  _level ++;
-  if (unhandled_oop_print) {
-    for (int i=0; i<_level; i++) tty->print(" ");
+  _level++;
+  if (unhandled_oop_print == _thread) {
+    for (int i=0; i < _level; i++) tty->print(" ");
     tty->print_cr("r " INTPTR_FORMAT, p2i(op));
   }
   UnhandledOopEntry entry(op, pc);
@@ -98,11 +98,11 @@
 void UnhandledOops::unregister_unhandled_oop(oop* op) {
   if (!_thread->is_in_stack((address)op)) return;
 
-  _level --;
-  if (unhandled_oop_print) {
-    for (int i=0; i<_level; i++) tty->print(" ");
+  if (unhandled_oop_print == _thread) {
+    for (int i=0; i < _level; i++) tty->print(" ");
     tty->print_cr("u " INTPTR_FORMAT, p2i(op));
   }
+  _level--;
 
   int i = _oop_list->find_from_end(op, match_oop_entry);
   assert(i!=-1, "oop not in unhandled_oop_list");
--- a/src/hotspot/share/services/gcNotifier.cpp	Thu Jul 18 10:25:49 2019 +0200
+++ b/src/hotspot/share/services/gcNotifier.cpp	Thu Jul 18 07:06:33 2019 -0400
@@ -159,7 +159,7 @@
                           gcInfoklass,
                           vmSymbols::com_sun_management_GcInfo_constructor_signature(),
                           &constructor_args,
-                          CHECK_NH);
+                          THREAD);
 }
 
 void GCNotifier::sendNotification(TRAPS) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/CheckUnhandledOops/TestOutOfMemory.java	Thu Jul 18 07:06:33 2019 -0400
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8227766
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+CheckUnhandledOops -Xmx100m TestOutOfMemory
+ */
+
+public class TestOutOfMemory {
+    public static void main(java.lang.String[] unused) {
+        final int BIG = 0x100000;
+        // Getting OOM breaks the unhandled oop detector
+        try {
+            int[][] X = new int[BIG][];
+            for (int i = 0; i < BIG; i++) {
+                X[i] = new int[BIG];
+                System.out.println("length = " + X.length);
+            }
+         } catch (OutOfMemoryError oom) {
+            System.out.println("OOM expected");
+         }
+    }
+}