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
--- 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()) {}
+ }
+ }
+}