changeset 57553:048ef0e2ba9f

8235998: [c2] Memory leaks during tracing after '8224193: stringStream should not use Resource Area'. Reviewed-by: dholmes, kvn
author goetz
date Mon, 16 Dec 2019 14:10:20 +0100
parents 083e20312207
children 3b2174ed0eb1
files src/hotspot/share/opto/compile.cpp src/hotspot/share/opto/compile.hpp src/hotspot/share/opto/loopPredicate.cpp src/hotspot/share/utilities/growableArray.hpp
diffstat 4 files changed, 33 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/opto/compile.cpp	Sat Dec 21 06:28:48 2019 +0800
+++ b/src/hotspot/share/opto/compile.cpp	Mon Dec 16 14:10:20 2019 +0100
@@ -4280,6 +4280,13 @@
   return phase->transform(new ConvI2LNode(value, ltype));
 }
 
+void Compile::print_inlining_stream_free() {
+  if (_print_inlining_stream != NULL) {
+    _print_inlining_stream->~stringStream();
+    _print_inlining_stream = NULL;
+  }
+}
+
 // The message about the current inlining is accumulated in
 // _print_inlining_stream and transfered into the _print_inlining_list
 // once we know whether inlining succeeds or not. For regular
@@ -4290,13 +4297,21 @@
 // when the inlining is attempted again.
 void Compile::print_inlining_init() {
   if (print_inlining() || print_intrinsics()) {
+    // print_inlining_init is actually called several times.
+    print_inlining_stream_free();
     _print_inlining_stream = new stringStream();
+    // Watch out: The memory initialized by the constructor call PrintInliningBuffer()
+    // will be copied into the only initial element. The default destructor of
+    // PrintInliningBuffer will be called when leaving the scope here. If it
+    // would destuct the  enclosed stringStream _print_inlining_list[0]->_ss
+    // would be destructed, too!
     _print_inlining_list = new (comp_arena())GrowableArray<PrintInliningBuffer>(comp_arena(), 1, 1, PrintInliningBuffer());
   }
 }
 
 void Compile::print_inlining_reinit() {
   if (print_inlining() || print_intrinsics()) {
+    print_inlining_stream_free();
     // Re allocate buffer when we change ResourceMark
     _print_inlining_stream = new stringStream();
   }
@@ -4310,7 +4325,7 @@
   assert(print_inlining() || print_intrinsics(), "PrintInlining off?");
   // Transfer the message from _print_inlining_stream to the current
   // _print_inlining_list buffer and clear _print_inlining_stream.
-  _print_inlining_list->at(_print_inlining_idx).ss()->write(_print_inlining_stream->as_string(), _print_inlining_stream->size());
+  _print_inlining_list->at(_print_inlining_idx).ss()->write(_print_inlining_stream->base(), _print_inlining_stream->size());
   print_inlining_reset();
 }
 
@@ -4391,9 +4406,16 @@
   if (do_print_inlining) {
     ResourceMark rm;
     stringStream ss;
+    assert(_print_inlining_list != NULL, "process_print_inlining should be called only once.");
     for (int i = 0; i < _print_inlining_list->length(); i++) {
       ss.print("%s", _print_inlining_list->adr_at(i)->ss()->as_string());
+      _print_inlining_list->at(i).freeStream();
     }
+    // Reset _print_inlining_list, it only contains destructed objects.
+    // It is on the arena, so it will be freed when the arena is reset.
+    _print_inlining_list = NULL;
+    // _print_inlining_stream won't be used anymore, either.
+    print_inlining_stream_free();
     size_t end = ss.size();
     _print_inlining_output = NEW_ARENA_ARRAY(comp_arena(), char, end+1);
     strncpy(_print_inlining_output, ss.base(), end+1);
--- a/src/hotspot/share/opto/compile.hpp	Sat Dec 21 06:28:48 2019 +0800
+++ b/src/hotspot/share/opto/compile.hpp	Mon Dec 16 14:10:20 2019 +0100
@@ -512,6 +512,8 @@
     PrintInliningBuffer()
       : _cg(NULL) { _ss = new stringStream(); }
 
+    void freeStream() { _ss->~stringStream(); _ss = NULL; }
+
     stringStream* ss() const { return _ss; }
     CallGenerator* cg() const { return _cg; }
     void set_cg(CallGenerator* cg) { _cg = cg; }
@@ -533,6 +535,7 @@
 
   void* _replay_inline_data; // Pointer to data loaded from file
 
+  void print_inlining_stream_free();
   void print_inlining_init();
   void print_inlining_reinit();
   void print_inlining_commit();
--- a/src/hotspot/share/opto/loopPredicate.cpp	Sat Dec 21 06:28:48 2019 +0800
+++ b/src/hotspot/share/opto/loopPredicate.cpp	Mon Dec 16 14:10:20 2019 +0100
@@ -801,7 +801,8 @@
 
   if (TraceLoopPredicate) {
     predString->print_cr("<u range");
-    tty->print("%s", predString->as_string());
+    tty->print("%s", predString->base());
+    predString->~stringStream();
   }
   return bol;
 }
--- a/src/hotspot/share/utilities/growableArray.hpp	Sat Dec 21 06:28:48 2019 +0800
+++ b/src/hotspot/share/utilities/growableArray.hpp	Mon Dec 16 14:10:20 2019 +0100
@@ -192,7 +192,11 @@
     for (; i < _max; i++) ::new ((void*)&_data[i]) E();
   }
 
-  GrowableArray(Arena* arena, int initial_size, int initial_len, const E& filler) : GenericGrowableArray(arena, initial_size, initial_len) {
+  // Watch out, if filler was generated by a constructor, the destuctor might
+  // be called on the original object invalidating all the copies made here.
+  // Carefully design the copy constructor.
+  GrowableArray(Arena* arena, int initial_size, int initial_len, const E& filler) :
+      GenericGrowableArray(arena, initial_size, initial_len) {
     _data = (E*)raw_allocate(sizeof(E));
     int i = 0;
     for (; i < _len; i++) ::new ((void*)&_data[i]) E(filler);