7047069: Array can dynamically change size when assigned to an object field
authorkvn
Fri, 27 May 2011 12:47:48 -0700
changeset 9965 21ec27af2037
parent 9964 6fe8abf59580
child 9966 b30a5eb9bcff
7047069: Array can dynamically change size when assigned to an object field Summary: Fix initialization of a newly-allocated array with arraycopy Reviewed-by: never
hotspot/src/share/vm/opto/library_call.cpp
hotspot/test/compiler/7047069/Test7047069.java
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu May 26 16:39:34 2011 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Fri May 27 12:47:48 2011 -0700
@@ -5225,15 +5225,16 @@
 
   // Look at the alignment of the starting offsets.
   int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type);
-  const intptr_t BIG_NEG = -128;
-  assert(BIG_NEG + 2*abase < 0, "neg enough");
-
-  intptr_t src_off  = abase + ((intptr_t) find_int_con(src_offset, -1)  << scale);
-  intptr_t dest_off = abase + ((intptr_t) find_int_con(dest_offset, -1) << scale);
-  if (src_off < 0 || dest_off < 0)
+
+  intptr_t src_off_con  = (intptr_t) find_int_con(src_offset, -1);
+  intptr_t dest_off_con = (intptr_t) find_int_con(dest_offset, -1);
+  if (src_off_con < 0 || dest_off_con < 0)
     // At present, we can only understand constants.
     return false;
 
+  intptr_t src_off  = abase + (src_off_con  << scale);
+  intptr_t dest_off = abase + (dest_off_con << scale);
+
   if (((src_off | dest_off) & (BytesPerLong-1)) != 0) {
     // Non-aligned; too bad.
     // One more chance:  Pick off an initial 32-bit word.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/7047069/Test7047069.java	Fri May 27 12:47:48 2011 -0700
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2011, 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 7047069
+ * @summary Array can dynamically change size when assigned to an object field
+ *
+ * @run main/othervm -Xbatch Test7047069
+ */
+
+import java.util.*;
+import java.awt.geom.*;
+
+public class Test7047069 {
+    static boolean verbose;
+
+    static final int GROW_SIZE = 24;    // Multiple of cubic & quad curve size
+
+    float squareflat;           // Square of the flatness parameter
+                    // for testing against squared lengths
+
+    int limit;              // Maximum number of recursion levels
+
+    float hold[] = new float[14];   // The cache of interpolated coords
+                    // Note that this must be long enough
+                    // to store a full cubic segment and
+                    // a relative cubic segment to avoid
+                    // aliasing when copying the coords
+                    // of a curve to the end of the array.
+                    // This is also serendipitously equal
+                    // to the size of a full quad segment
+                    // and 2 relative quad segments.
+
+    int holdEnd;            // The index of the last curve segment
+                    // being held for interpolation
+
+    int holdIndex;          // The index of the curve segment
+                    // that was last interpolated.  This
+                    // is the curve segment ready to be
+                    // returned in the next call to
+                    // currentSegment().
+
+    int levels[];           // The recursion level at which
+                    // each curve being held in storage
+                    // was generated.
+
+    int levelIndex;         // The index of the entry in the
+                    // levels array of the curve segment
+                    // at the holdIndex
+
+    public static void subdivide(float src[], int srcoff,
+                                 float left[], int leftoff,
+                                 float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx = src[srcoff + 2];
+        float ctrly = src[srcoff + 3];
+        float x2 = src[srcoff + 4];
+        float y2 = src[srcoff + 5];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+        x1 = (x1 + ctrlx) / 2f;
+        y1 = (y1 + ctrly) / 2f;
+        x2 = (x2 + ctrlx) / 2f;
+        y2 = (y2 + ctrly) / 2f;
+        ctrlx = (x1 + x2) / 2f;
+        ctrly = (y1 + y2) / 2f;
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx;
+            left[leftoff + 5] = ctrly;
+        }
+        if (right != null) {
+            right[rightoff + 0] = ctrlx;
+            right[rightoff + 1] = ctrly;
+            right[rightoff + 2] = x2;
+            right[rightoff + 3] = y2;
+        }
+    }
+
+    public static double getFlatnessSq(float coords[], int offset) {
+        return Line2D.ptSegDistSq(coords[offset + 0], coords[offset + 1],
+                                  coords[offset + 4], coords[offset + 5],
+                                  coords[offset + 2], coords[offset + 3]);
+    }
+
+    public Test7047069() {
+        this.squareflat = .0001f * .0001f;
+        holdIndex = hold.length - 6;
+        holdEnd = hold.length - 2;
+        hold[holdIndex + 0] = (float) (Math.random() * 100);
+        hold[holdIndex + 1] = (float) (Math.random() * 100);
+        hold[holdIndex + 2] = (float) (Math.random() * 100);
+        hold[holdIndex + 3] = (float) (Math.random() * 100);
+        hold[holdIndex + 4] = (float) (Math.random() * 100);
+        hold[holdIndex + 5] = (float) (Math.random() * 100);
+        levelIndex = 0;
+        this.limit = 10;
+        this.levels = new int[limit + 1];
+    }
+
+    /*
+     * Ensures that the hold array can hold up to (want) more values.
+     * It is currently holding (hold.length - holdIndex) values.
+     */
+    void ensureHoldCapacity(int want) {
+        if (holdIndex - want < 0) {
+            int have = hold.length - holdIndex;
+            int newsize = hold.length + GROW_SIZE;
+            float newhold[] = new float[newsize];
+            System.arraycopy(hold, holdIndex,
+                     newhold, holdIndex + GROW_SIZE,
+                     have);
+            if (verbose) System.err.println("old hold = "+hold+"["+hold.length+"]");
+            if (verbose) System.err.println("replacement hold = "+newhold+"["+newhold.length+"]");
+            hold = newhold;
+            if (verbose) System.err.println("new hold = "+hold+"["+hold.length+"]");
+            if (verbose) System.err.println("replacement hold still = "+newhold+"["+newhold.length+"]");
+            holdIndex += GROW_SIZE;
+            holdEnd += GROW_SIZE;
+        }
+    }
+
+    private boolean next() {
+        if (holdIndex >= holdEnd) {
+            return false;
+        }
+
+        int level = levels[levelIndex];
+        while (level < limit) {
+            if (getFlatnessSq(hold, holdIndex) < squareflat) {
+                break;
+            }
+
+            ensureHoldCapacity(4);
+            subdivide(hold, holdIndex,
+                      hold, holdIndex - 4,
+                      hold, holdIndex);
+            holdIndex -= 4;
+
+            // Now that we have subdivided, we have constructed
+            // two curves of one depth lower than the original
+            // curve.  One of those curves is in the place of
+            // the former curve and one of them is in the next
+            // set of held coordinate slots.  We now set both
+            // curves level values to the next higher level.
+            level++;
+            levels[levelIndex] = level;
+            levelIndex++;
+            levels[levelIndex] = level;
+        }
+
+        // This curve segment is flat enough, or it is too deep
+        // in recursion levels to try to flatten any more.  The
+        // two coordinates at holdIndex+4 and holdIndex+5 now
+        // contain the endpoint of the curve which can be the
+        // endpoint of an approximating line segment.
+        holdIndex += 4;
+        levelIndex--;
+        return true;
+    }
+
+    public static void main(String argv[]) {
+        verbose = (argv.length > 0);
+        for (int i = 0; i < 100000; i++) {
+            Test7047069 st = new Test7047069();
+            while (st.next()) {}
+        }
+    }
+}