After I checked in Ralph Loader's fix for StringBuffer.substring the other day, Ralph pointed out that my modification had changed the meaning of the patch slightly:

On Monday, Sep 22, 2003, at 20:45 Pacific/Auckland, Ralph Loader wrote:

My interpretation of the original code was that it was meant to prevent
the possibility that a small substring of a large StringBuffer would
prevent the large array being gc'd.

The patch you checked in breaks this. Consider:

String Foo()
{
  StringBuffer b = new StringBuffer();
  ... put a megabyte of stuff into b ...
  String ignored = b.toString(); // sets b.shared
  return b.substring (0, 1);
}

The 1 character String returned from Foo now has it's contents stored in
a megabyte char[], and that array has no other references.


Passing ((len << 2) >= value.length) rather than StringBuffer.shared to
the String constructor prevented this.

Its hard to say what is optimal here, as you can also argue that if the string is already shared then its reasonable to share even if the substring is small. However, having to copy a small string unnecessarily doesn't seem as bad as potentially wasting a lot of memory in the scenario above. So, I'm checking in the following patch, which reverts to the behaviour of Ralph's original patch.


2003-09-24  Bryce McKinlay  <[EMAIL PROTECTED]>

        * java/lang/StringBuffer.java (substring): Don't set `shared' on
        small Strings, even if buffer is already shared.

Index: StringBuffer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/StringBuffer.java,v
retrieving revision 1.16
diff -u -r1.16 StringBuffer.java
--- StringBuffer.java   22 Sep 2003 08:17:48 -0000      1.16
+++ StringBuffer.java   24 Sep 2003 06:02:00 -0000
@@ -564,11 +564,12 @@
       throw new StringIndexOutOfBoundsException();
     if (len == 0)
       return "";
-    // Share unless substring is smaller than 1/4 of the buffer.
-    if ((len << 2) >= value.length)
-      shared = true;
+    // Don't copy unless substring is smaller than 1/4 of the buffer.
+    boolean share_buffer = ((len << 2) >= value.length);
+    if (share_buffer)
+      this.shared = true;
     // Package constructor avoids an array copy.
-    return new String(value, beginIndex, len, shared);
+    return new String(value, beginIndex, len, share_buffer);
   }
 
   /**


Regards

Bryce.

_______________________________________________
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath

Reply via email to