7046490: Preallocated OOME objects should obey Throwable stack trace protocol
authordholmes
Fri, 22 Jul 2011 00:29:01 -0700
changeset 10233 b40fd2bd2fac
parent 10232 569c17cefddf
child 10234 31f396799198
7046490: Preallocated OOME objects should obey Throwable stack trace protocol Summary: Update the OOME stacktrace to contain Throwable.UNASSIGNED_STACK when the backtrace is filled in Reviewed-by: mchung, phh
hotspot/src/share/vm/classfile/javaClasses.cpp
hotspot/src/share/vm/classfile/javaClasses.hpp
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Sat Jul 16 22:21:39 2011 -0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Fri Jul 22 00:29:01 2011 -0700
@@ -1019,6 +1019,16 @@
   compute_offset(_ngroups_offset,     k, vmSymbols::ngroups_name(),     vmSymbols::int_signature());
 }
 
+oop java_lang_Throwable::unassigned_stacktrace() {
+  instanceKlass* ik = instanceKlass::cast(SystemDictionary::Throwable_klass());
+  address addr = ik->static_field_addr(static_unassigned_stacktrace_offset);
+  if (UseCompressedOops) {
+    return oopDesc::load_decode_heap_oop((narrowOop *)addr);
+  } else {
+    return oopDesc::load_decode_heap_oop((oop*)addr);
+  }
+}
+
 oop java_lang_Throwable::backtrace(oop throwable) {
   return throwable->obj_field_acquire(backtrace_offset);
 }
@@ -1044,9 +1054,13 @@
 }
 
 
+void java_lang_Throwable::set_stacktrace(oop throwable, oop st_element_array) {
+  throwable->obj_field_put(stackTrace_offset, st_element_array);
+}
+
 void java_lang_Throwable::clear_stacktrace(oop throwable) {
   assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4");
-  throwable->obj_field_put(stackTrace_offset, NULL);
+  set_stacktrace(throwable, NULL);
 }
 
 
@@ -1340,6 +1354,7 @@
   if (JDK_Version::is_gte_jdk14x_version()) {
     // New since 1.4, clear lazily constructed Java level stacktrace if
     // refilling occurs
+    // This is unnecessary in 1.7+ but harmless
     clear_stacktrace(throwable());
   }
 
@@ -1541,6 +1556,15 @@
     // Bail-out for deep stacks
     if (chunk_count >= max_chunks) break;
   }
+
+  // For Java 7+ we support the Throwable immutability protocol defined for Java 7. This support
+  // was missing in 7u0 so in 7u0 there is a workaround in the Throwable class. That workaround
+  // can be removed in a JDK using this JVM version
+  if (JDK_Version::is_gte_jdk17x_version()) {
+      java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace());
+      assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized");
+  }
+
 }
 
 
@@ -2770,6 +2794,7 @@
 int java_lang_Throwable::detailMessage_offset;
 int java_lang_Throwable::cause_offset;
 int java_lang_Throwable::stackTrace_offset;
+int java_lang_Throwable::static_unassigned_stacktrace_offset;
 int java_lang_reflect_AccessibleObject::override_offset;
 int java_lang_reflect_Method::clazz_offset;
 int java_lang_reflect_Method::name_offset;
@@ -2947,6 +2972,7 @@
   java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
   java_lang_Throwable::cause_offset      = java_lang_Throwable::hc_cause_offset      * x + header;
   java_lang_Throwable::stackTrace_offset = java_lang_Throwable::hc_stackTrace_offset * x + header;
+  java_lang_Throwable::static_unassigned_stacktrace_offset = java_lang_Throwable::hc_static_unassigned_stacktrace_offset *  x;
 
   // java_lang_boxing_object
   java_lang_boxing_object::value_offset = java_lang_boxing_object::hc_value_offset + header;
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Sat Jul 16 22:21:39 2011 -0400
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Fri Jul 22 00:29:01 2011 -0700
@@ -393,6 +393,9 @@
     hc_cause_offset         =  2,  // New since 1.4
     hc_stackTrace_offset    =  3   // New since 1.4
   };
+  enum {
+      hc_static_unassigned_stacktrace_offset = 0  // New since 1.7
+  };
   // Trace constants
   enum {
     trace_methods_offset = 0,
@@ -406,6 +409,7 @@
   static int detailMessage_offset;
   static int cause_offset;
   static int stackTrace_offset;
+  static int static_unassigned_stacktrace_offset;
 
   // Printing
   static char* print_stack_element_to_buffer(methodOop method, int bci);
@@ -414,6 +418,9 @@
   static void clear_stacktrace(oop throwable);
   // No stack trace available
   static const char* no_stack_trace_message();
+  // Stacktrace (post JDK 1.7.0 to allow immutability protocol to be followed)
+  static void set_stacktrace(oop throwable, oop st_element_array);
+  static oop unassigned_stacktrace();
 
  public:
   // Backtrace
@@ -438,7 +445,6 @@
   static void allocate_backtrace(Handle throwable, TRAPS);
   // Fill in current stack trace for throwable with preallocated backtrace (no GC)
   static void fill_in_stack_trace_of_preallocated_backtrace(Handle throwable);
-
   // Fill in current stack trace, can cause GC
   static void fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS);
   static void fill_in_stack_trace(Handle throwable, methodHandle method = methodHandle());