From c71395c821ddda7e16e049448661d4f9f6123071 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 6 May 2009 14:14:54 -0700 Subject: [PATCH 01/23] 6806822: Font.getFontName() is slow in Java5 and 6 Reviewed-by: igor, jgodinez --- .../share/classes/sun/font/TrueTypeFont.java | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/sun/font/TrueTypeFont.java b/jdk/src/share/classes/sun/font/TrueTypeFont.java index 7a87e81a0e2..01893d655dd 100644 --- a/jdk/src/share/classes/sun/font/TrueTypeFont.java +++ b/jdk/src/share/classes/sun/font/TrueTypeFont.java @@ -160,6 +160,13 @@ public class TrueTypeFont extends FileFont { private boolean supportsJA; private boolean supportsCJK; + /* These are for faster access to the name of the font as + * typically exposed via API to applications. + */ + private Locale nameLocale; + private String localeFamilyName; + private String localeFullName; + /** * - does basic verification of the file * - reads the header table for this font (within a collection) @@ -1092,6 +1099,10 @@ public class TrueTypeFont extends FileFont { * greater than 32767, so read and store those as ints */ int stringPtr = sbuffer.get() & 0xffff; + + nameLocale = sun.awt.SunToolkit.getStartupLocale(); + short nameLocaleID = FontManager.getLCIDFromLocale(nameLocale); + for (int i=0; i Date: Thu, 21 May 2009 09:56:03 -0700 Subject: [PATCH 02/23] 6829659: Circle is rendered in C shape Reviewed-by: campbell, flar --- .../sun/java2d/pisces/PiscesCache.java | 2 +- jdk/test/sun/pisces/ScaleTest.java | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 jdk/test/sun/pisces/ScaleTest.java diff --git a/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java b/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java index ce62e0dab3d..05e20fdfca5 100644 --- a/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java +++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java @@ -96,7 +96,7 @@ public final class PiscesCache { bboxX1 = x1+1; } else { if (bboxX0 > x0) bboxX0 = x0; - if (bboxX1 < x1) bboxX1 = x1; + if (bboxX1 < x1 + 1) bboxX1 = x1 + 1; while (bboxY1++ < y) { reallocRowInfo(alphaRows+1); minTouched[alphaRows] = 0; diff --git a/jdk/test/sun/pisces/ScaleTest.java b/jdk/test/sun/pisces/ScaleTest.java new file mode 100644 index 00000000000..bef16e28b2d --- /dev/null +++ b/jdk/test/sun/pisces/ScaleTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.awt.*; +import java.awt.geom.Ellipse2D; +import java.awt.image.BufferedImage; +import java.io.File; +import javax.imageio.ImageIO; + + +public class ScaleTest { + public static void main(String[] args) throws Exception { + BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB); + Graphics2D g = image.createGraphics(); + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setPaint(Color.WHITE); + g.fill(new Rectangle(image.getWidth(), image.getHeight())); + g.scale(.9, .9); + g.setPaint(Color.BLACK); + g.setStroke(new BasicStroke(0.5f)); + g.draw(new Ellipse2D.Double(25, 25, 150, 150)); + + // To visually check it + //ImageIO.write(image, "PNG", new File(args[0])); + + boolean nonWhitePixelFound = false; + for (int x = 100; x < 200; ++x) { + if (image.getRGB(x, 90) != Color.WHITE.getRGB()) { + nonWhitePixelFound = true; + break; + } + } + if (!nonWhitePixelFound) { + throw new RuntimeException("A circle is rendered like a 'C' shape."); + } + } +} From 8e2b3cf3063c4307e190928ecfedfc1a0a3cef7c Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Sat, 23 May 2009 08:35:37 +0400 Subject: [PATCH 03/23] 4893408: JPEGReader throws IllegalArgException when setting the destination to BYTE_GRAY Reviewed-by: igor, prr --- .../com/sun/imageio/plugins/jpeg/JPEG.java | 22 +- .../imageio/plugins/jpeg/JPEGImageReader.java | 249 +++++++++++++----- .../imageio/plugins/jpeg/JPEGImageWriter.java | 8 +- .../imageio/plugins/jpeg/JPEGMetadata.java | 2 +- .../classes/java/awt/color/ICC_Profile.java | 48 ++-- .../native/sun/awt/image/jpeg/imageioJPEG.c | 44 ++-- .../imageio/plugins/jpeg/ReadAsGrayTest.java | 179 +++++++++++++ 7 files changed, 435 insertions(+), 117 deletions(-) create mode 100644 jdk/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java index 3ed5c5083c3..6957bec6aaf 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java @@ -215,17 +215,21 @@ public class JPEG { public static class JCS { public static final ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB); - public static final ColorSpace YCC; - static { - ColorSpace cs = null; - try { - cs = ColorSpace.getInstance(ColorSpace.CS_PYCC); - } catch (IllegalArgumentException e) { - // PYCC.pf may not always be installed - } finally { - YCC = cs; + private static ColorSpace YCC = null; + private static boolean yccInited = false; + + public static ColorSpace getYCC() { + if (!yccInited) { + try { + YCC = ColorSpace.getInstance(ColorSpace.CS_PYCC); + } catch (IllegalArgumentException e) { + // PYCC.pf may not always be installed + } finally { + yccInited = true; + } } + return YCC; } } diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java index faf8261544c..2459ff54418 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -53,6 +53,7 @@ import java.io.IOException; import java.util.List; import java.util.Iterator; import java.util.ArrayList; +import java.util.NoSuchElementException; import sun.java2d.Disposer; import sun.java2d.DisposerRecord; @@ -215,51 +216,6 @@ public class JPEGImageReader extends ImageReader { /** The DisposerRecord that handles the actual disposal of this reader. */ private DisposerRecord disposerRecord; - /** - * Maintain an array of the default image types corresponding to the - * various supported IJG colorspace codes. - */ - private static final ImageTypeSpecifier [] defaultTypes = - new ImageTypeSpecifier [JPEG.NUM_JCS_CODES]; - - static { - defaultTypes[JPEG.JCS_GRAYSCALE] = - ImageTypeSpecifier.createFromBufferedImageType - (BufferedImage.TYPE_BYTE_GRAY); - defaultTypes[JPEG.JCS_RGB] = - ImageTypeSpecifier.createInterleaved - (JPEG.JCS.sRGB, - JPEG.bOffsRGB, - DataBuffer.TYPE_BYTE, - false, - false); - defaultTypes[JPEG.JCS_RGBA] = - ImageTypeSpecifier.createPacked - (JPEG.JCS.sRGB, - 0xff000000, - 0x00ff0000, - 0x0000ff00, - 0x000000ff, - DataBuffer.TYPE_INT, - false); - if (JPEG.JCS.YCC != null) { - defaultTypes[JPEG.JCS_YCC] = - ImageTypeSpecifier.createInterleaved - (JPEG.JCS.YCC, - JPEG.bandOffsets[2], - DataBuffer.TYPE_BYTE, - false, - false); - defaultTypes[JPEG.JCS_YCCA] = - ImageTypeSpecifier.createInterleaved - (JPEG.JCS.YCC, - JPEG.bandOffsets[3], - DataBuffer.TYPE_BYTE, - true, - false); - } - } - /** Sets up static C structures. */ private static native void initReaderIDs(Class iisClass, Class qTableClass, @@ -706,11 +662,11 @@ public class JPEGImageReader extends ImageReader { * Return an ImageTypeSpecifier corresponding to the given * color space code, or null if the color space is unsupported. */ - private ImageTypeSpecifier getImageType(int code) { - ImageTypeSpecifier ret = null; + private ImageTypeProducer getImageType(int code) { + ImageTypeProducer ret = null; if ((code > 0) && (code < JPEG.NUM_JCS_CODES)) { - ret = defaultTypes[code]; + ret = ImageTypeProducer.getTypeProducer(code); } return ret; } @@ -724,7 +680,7 @@ public class JPEGImageReader extends ImageReader { } // Returns null if it can't be represented - return getImageType(colorSpaceCode); + return getImageType(colorSpaceCode).getType(); } finally { clearThreadLock(); } @@ -758,13 +714,13 @@ public class JPEGImageReader extends ImageReader { // Get the raw ITS, if there is one. Note that this // won't always be the same as the default. - ImageTypeSpecifier raw = getImageType(colorSpaceCode); + ImageTypeProducer raw = getImageType(colorSpaceCode); // Given the encoded colorspace, build a list of ITS's // representing outputs you could handle starting // with the default. - ArrayList list = new ArrayList(1); + ArrayList list = new ArrayList(1); switch (colorSpaceCode) { case JPEG.JCS_GRAYSCALE: @@ -774,9 +730,7 @@ public class JPEGImageReader extends ImageReader { case JPEG.JCS_RGB: list.add(raw); list.add(getImageType(JPEG.JCS_GRAYSCALE)); - if (JPEG.JCS.YCC != null) { - list.add(getImageType(JPEG.JCS_YCC)); - } + list.add(getImageType(JPEG.JCS_YCC)); break; case JPEG.JCS_RGBA: list.add(raw); @@ -801,19 +755,21 @@ public class JPEGImageReader extends ImageReader { list.add(getImageType(JPEG.JCS_RGB)); if (iccCS != null) { - list.add(ImageTypeSpecifier.createInterleaved + list.add(new ImageTypeProducer() { + protected ImageTypeSpecifier produce() { + return ImageTypeSpecifier.createInterleaved (iccCS, JPEG.bOffsRGB, // Assume it's for RGB DataBuffer.TYPE_BYTE, false, - false)); + false); + } + }); } list.add(getImageType(JPEG.JCS_GRAYSCALE)); - if (JPEG.JCS.YCC != null) { // Might be null if PYCC.pf not installed - list.add(getImageType(JPEG.JCS_YCC)); - } + list.add(getImageType(JPEG.JCS_YCC)); break; case JPEG.JCS_YCbCrA: // Default is to convert to RGBA // As there is no YCbCr ColorSpace, we can't support @@ -822,7 +778,7 @@ public class JPEGImageReader extends ImageReader { break; } - return list.iterator(); + return new ImageTypeIterator(list.iterator()); } /** @@ -872,6 +828,10 @@ public class JPEGImageReader extends ImageReader { if (csType == ColorSpace.TYPE_RGB) { // We want RGB // IJG can do this for us more efficiently setOutColorSpace(structPointer, JPEG.JCS_RGB); + // Update java state according to changes + // in the native part of decoder. + outColorSpaceCode = JPEG.JCS_RGB; + numComponents = 3; } else if (csType != ColorSpace.TYPE_GRAY) { throw new IIOException("Incompatible color conversion"); } @@ -881,6 +841,10 @@ public class JPEGImageReader extends ImageReader { if (colorSpaceCode == JPEG.JCS_YCbCr) { // If the jpeg space is YCbCr, IJG can do it setOutColorSpace(structPointer, JPEG.JCS_GRAYSCALE); + // Update java state according to changes + // in the native part of decoder. + outColorSpaceCode = JPEG.JCS_GRAYSCALE; + numComponents = 1; } } else if ((iccCS != null) && (cm.getNumComponents() == numComponents) && @@ -906,20 +870,26 @@ public class JPEGImageReader extends ImageReader { } break; case JPEG.JCS_YCC: - if (JPEG.JCS.YCC == null) { // We can't do YCC at all - throw new IIOException("Incompatible color conversion"); - } - if ((cs != JPEG.JCS.YCC) && - (cm.getNumComponents() == numComponents)) { - convert = new ColorConvertOp(JPEG.JCS.YCC, cs, null); + { + ColorSpace YCC = JPEG.JCS.getYCC(); + if (YCC == null) { // We can't do YCC at all + throw new IIOException("Incompatible color conversion"); + } + if ((cs != YCC) && + (cm.getNumComponents() == numComponents)) { + convert = new ColorConvertOp(YCC, cs, null); + } } break; case JPEG.JCS_YCCA: - // No conversions available; image must be YCCA - if ((JPEG.JCS.YCC == null) || // We can't do YCC at all - (cs != JPEG.JCS.YCC) || - (cm.getNumComponents() != numComponents)) { - throw new IIOException("Incompatible color conversion"); + { + ColorSpace YCC = JPEG.JCS.getYCC(); + // No conversions available; image must be YCCA + if ((YCC == null) || // We can't do YCC at all + (cs != YCC) || + (cm.getNumComponents() != numComponents)) { + throw new IIOException("Incompatible color conversion"); + } } break; default: @@ -1554,3 +1524,140 @@ public class JPEGImageReader extends ImageReader { } } } + +/** + * An internal helper class that wraps producer's iterator + * and extracts specifier instances on demand. + */ +class ImageTypeIterator implements Iterator { + private Iterator producers; + private ImageTypeSpecifier theNext = null; + + public ImageTypeIterator(Iterator producers) { + this.producers = producers; + } + + public boolean hasNext() { + if (theNext != null) { + return true; + } + if (!producers.hasNext()) { + return false; + } + do { + theNext = producers.next().getType(); + } while (theNext == null && producers.hasNext()); + + return (theNext != null); + } + + public ImageTypeSpecifier next() { + if (theNext != null || hasNext()) { + ImageTypeSpecifier t = theNext; + theNext = null; + return t; + } else { + throw new NoSuchElementException(); + } + } + + public void remove() { + producers.remove(); + } +} + +/** + * An internal helper class that provides means for deferred creation + * of ImageTypeSpecifier instance required to describe available + * destination types. + * + * This implementation only supports standard + * jpeg color spaces (defined by corresponding JCS color space code). + * + * To support other color spaces one can override produce() method to + * return custom instance of ImageTypeSpecifier. + */ +class ImageTypeProducer { + + private ImageTypeSpecifier type = null; + boolean failed = false; + private int csCode; + + public ImageTypeProducer(int csCode) { + this.csCode = csCode; + } + + public ImageTypeProducer() { + csCode = -1; // undefined + } + + public synchronized ImageTypeSpecifier getType() { + if (!failed && type == null) { + try { + type = produce(); + } catch (Throwable e) { + failed = true; + } + } + return type; + } + + private static final ImageTypeProducer [] defaultTypes = + new ImageTypeProducer [JPEG.NUM_JCS_CODES]; + + public synchronized static ImageTypeProducer getTypeProducer(int csCode) { + if (csCode < 0 || csCode >= JPEG.NUM_JCS_CODES) { + return null; + } + if (defaultTypes[csCode] == null) { + defaultTypes[csCode] = new ImageTypeProducer(csCode); + } + return defaultTypes[csCode]; + } + + protected ImageTypeSpecifier produce() { + switch (csCode) { + case JPEG.JCS_GRAYSCALE: + return ImageTypeSpecifier.createFromBufferedImageType + (BufferedImage.TYPE_BYTE_GRAY); + case JPEG.JCS_RGB: + return ImageTypeSpecifier.createInterleaved(JPEG.JCS.sRGB, + JPEG.bOffsRGB, + DataBuffer.TYPE_BYTE, + false, + false); + case JPEG.JCS_RGBA: + return ImageTypeSpecifier.createPacked(JPEG.JCS.sRGB, + 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x000000ff, + DataBuffer.TYPE_INT, + false); + case JPEG.JCS_YCC: + if (JPEG.JCS.getYCC() != null) { + return ImageTypeSpecifier.createInterleaved( + JPEG.JCS.getYCC(), + JPEG.bandOffsets[2], + DataBuffer.TYPE_BYTE, + false, + false); + } else { + return null; + } + case JPEG.JCS_YCCA: + if (JPEG.JCS.getYCC() != null) { + return ImageTypeSpecifier.createInterleaved( + JPEG.JCS.getYCC(), + JPEG.bandOffsets[3], + DataBuffer.TYPE_BYTE, + true, + false); + } else { + return null; + } + default: + return null; + } + } +} diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java index 9c585047faa..1c4b5bc1b62 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java @@ -812,7 +812,7 @@ public class JPEGImageWriter extends ImageWriter { } break; case ColorSpace.TYPE_3CLR: - if (cs == JPEG.JCS.YCC) { + if (cs == JPEG.JCS.getYCC()) { if (!alpha) { if (jfif != null) { convertTosRGB = true; @@ -1494,7 +1494,7 @@ public class JPEGImageWriter extends ImageWriter { } break; case ColorSpace.TYPE_3CLR: - if (cs == JPEG.JCS.YCC) { + if (cs == JPEG.JCS.getYCC()) { if (alpha) { retval = JPEG.JCS_YCCA; } else { @@ -1533,7 +1533,7 @@ public class JPEGImageWriter extends ImageWriter { } break; case ColorSpace.TYPE_3CLR: - if (cs == JPEG.JCS.YCC) { + if (cs == JPEG.JCS.getYCC()) { if (alpha) { retval = JPEG.JCS_YCCA; } else { @@ -1579,7 +1579,7 @@ public class JPEGImageWriter extends ImageWriter { } break; case ColorSpace.TYPE_3CLR: - if (cs == JPEG.JCS.YCC) { + if (cs == JPEG.JCS.getYCC()) { if (alpha) { retval = JPEG.JCS_YCCA; } else { diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java index 044f7d632f6..c7a628c9f97 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java @@ -490,7 +490,7 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable { } break; case ColorSpace.TYPE_3CLR: - if (cs == JPEG.JCS.YCC) { + if (cs == JPEG.JCS.getYCC()) { wantJFIF = false; componentIDs[0] = (byte) 'Y'; componentIDs[1] = (byte) 'C'; diff --git a/jdk/src/share/classes/java/awt/color/ICC_Profile.java b/jdk/src/share/classes/java/awt/color/ICC_Profile.java index 705d2560e1f..ef685f43585 100644 --- a/jdk/src/share/classes/java/awt/color/ICC_Profile.java +++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java @@ -863,11 +863,16 @@ public class ICC_Profile implements Serializable { case ColorSpace.CS_PYCC: synchronized(ICC_Profile.class) { if (PYCCprofile == null) { - ProfileDeferralInfo pInfo = - new ProfileDeferralInfo("PYCC.pf", - ColorSpace.TYPE_3CLR, 3, - CLASS_DISPLAY); - PYCCprofile = getDeferredInstance(pInfo); + if (getProfileFile("PYCC.pf") != null) { + ProfileDeferralInfo pInfo = + new ProfileDeferralInfo("PYCC.pf", + ColorSpace.TYPE_3CLR, 3, + CLASS_DISPLAY); + PYCCprofile = getDeferredInstance(pInfo); + } else { + throw new IllegalArgumentException( + "Can't load standard profile: PYCC.pf"); + } } thisProfile = PYCCprofile; } @@ -1783,17 +1788,33 @@ public class ICC_Profile implements Serializable { return (FileInputStream)java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { - return privilegedOpenProfile(fileName); + File f = privilegedGetProfileFile(fileName); + if (f != null) { + try { + return new FileInputStream(f); + } catch (FileNotFoundException e) { + } + } + return null; + } + }); + } + + private static File getProfileFile(final String fileName) { + return (File)java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + return privilegedGetProfileFile(fileName); } }); } /* - * this version is called from doPrivileged in privilegedOpenProfile. - * the whole method is privileged! + * this version is called from doPrivileged in openProfile + * or getProfileFile, so the whole method is privileged! */ - private static FileInputStream privilegedOpenProfile(String fileName) { - FileInputStream fis = null; + + private static File privilegedGetProfileFile(String fileName) { String path, dir, fullPath; File f = new File(fileName); /* try absolute file name */ @@ -1830,12 +1851,9 @@ public class ICC_Profile implements Serializable { } if (f.isFile()) { - try { - fis = new FileInputStream(f); - } catch (FileNotFoundException e) { - } + return f; } - return fis; + return null; } diff --git a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c index 0a99c3fdb93..7d39c61e02f 100644 --- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c +++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c @@ -1783,7 +1783,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage struct jpeg_source_mgr *src; - JSAMPROW scanLinePtr; + JSAMPROW scanLinePtr = NULL; jint bands[MAX_BANDS]; int i, j; jint *body; @@ -1819,7 +1819,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage cinfo = (j_decompress_ptr) data->jpegObj; - if ((numBands < 1) || (numBands > cinfo->num_components) || + if ((numBands < 1) || (sourceXStart < 0) || (sourceXStart >= (jint)cinfo->image_width) || (sourceYStart < 0) || (sourceYStart >= (jint)cinfo->image_height) || (sourceWidth < 1) || (sourceWidth > (jint)cinfo->image_width) || @@ -1877,16 +1877,6 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage return data->abortFlag; // We already threw an out of memory exception } - // Allocate a 1-scanline buffer - scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->num_components); - if (scanLinePtr == NULL) { - RELEASE_ARRAYS(env, data, src->next_input_byte); - JNU_ThrowByName( env, - "java/lang/OutOfMemoryError", - "Reading JPEG Stream"); - return data->abortFlag; - } - /* Establish the setjmp return context for sun_jpeg_error_exit to use. */ jerr = (sun_jpeg_error_ptr) cinfo->err; @@ -1900,7 +1890,10 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage buffer); JNU_ThrowByName(env, "javax/imageio/IIOException", buffer); } - free(scanLinePtr); + if (scanLinePtr != NULL) { + free(scanLinePtr); + scanLinePtr = NULL; + } return data->abortFlag; } @@ -1938,6 +1931,23 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage jpeg_start_decompress(cinfo); + if (numBands != cinfo->output_components) { + JNU_ThrowByName(env, "javax/imageio/IIOException", + "Invalid argument to native readImage"); + return data->abortFlag; + } + + + // Allocate a 1-scanline buffer + scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->output_components); + if (scanLinePtr == NULL) { + RELEASE_ARRAYS(env, data, src->next_input_byte); + JNU_ThrowByName( env, + "java/lang/OutOfMemoryError", + "Reading JPEG Stream"); + return data->abortFlag; + } + // loop over progressive passes done = FALSE; while (!done) { @@ -1965,9 +1975,9 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage scanlineLimit = sourceYStart+sourceHeight; pixelLimit = scanLinePtr - +(sourceXStart+sourceWidth)*cinfo->num_components; + +(sourceXStart+sourceWidth)*cinfo->output_components; - pixelStride = stepX*cinfo->num_components; + pixelStride = stepX*cinfo->output_components; targetLine = 0; while ((data->abortFlag == JNI_FALSE) @@ -1982,12 +1992,12 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage // Optimization: The component bands are ordered sequentially, // so we can simply use memcpy() to copy the intermediate // scanline buffer into the raster. - in = scanLinePtr + (sourceXStart * cinfo->num_components); + in = scanLinePtr + (sourceXStart * cinfo->output_components); if (pixelLimit > in) { memcpy(out, in, pixelLimit - in); } } else { - for (in = scanLinePtr+sourceXStart*cinfo->num_components; + for (in = scanLinePtr+sourceXStart*cinfo->output_components; in < pixelLimit; in += pixelStride) { for (i = 0; i < numBands; i++) { diff --git a/jdk/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java b/jdk/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java new file mode 100644 index 00000000000..b572567771f --- /dev/null +++ b/jdk/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java @@ -0,0 +1,179 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 4893408 + * + * @summary Test verifies that Image I/O jpeg reader correctly handles + * destination types if number of color components in destination + * differs from number of color components in the jpeg image. + * Particularly, it verifies reading YCbCr image as a grayscaled + * and reading grayscaled jpeg as a RGB. + * + * @run main ReadAsGrayTest + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Iterator; +import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.stream.ImageInputStream; +import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR; +import static java.awt.image.BufferedImage.TYPE_BYTE_GRAY; +import static java.awt.color.ColorSpace.TYPE_GRAY; +import static java.awt.color.ColorSpace.CS_sRGB; + +public class ReadAsGrayTest { + static Color[] colors = new Color[] { + Color.white, Color.red, Color.green, + Color.blue, Color.black }; + + static final int dx = 50; + static final int h = 100; + + static ColorSpace sRGB = ColorSpace.getInstance(CS_sRGB); + + + public static void main(String[] args) throws IOException { + System.out.println("Type TYPE_BYTE_GRAY"); + doTest(TYPE_BYTE_GRAY); + + System.out.println("Type TYPE_3BYTE_BGR"); + doTest(TYPE_3BYTE_BGR); + + System.out.println("Test PASSED."); + } + + private static void doTest(int type) throws IOException { + BufferedImage src = createTestImage(type); + + File f = new File("test.jpg"); + + if (!ImageIO.write(src, "jpg", f)) { + throw new RuntimeException("Failed to write test image."); + } + + ImageInputStream iis = ImageIO.createImageInputStream(f); + ImageReader reader = ImageIO.getImageReaders(iis).next(); + reader.setInput(iis); + + Iterator types = reader.getImageTypes(0); + ImageTypeSpecifier srgb = null; + ImageTypeSpecifier gray = null; + // look for gray and srgb types + while ((srgb == null || gray == null) && types.hasNext()) { + ImageTypeSpecifier t = types.next(); + if (t.getColorModel().getColorSpace().getType() == TYPE_GRAY) { + gray = t; + } + if (t.getColorModel().getColorSpace() == sRGB) { + srgb = t; + } + } + if (gray == null) { + throw new RuntimeException("No gray type available."); + } + if (srgb == null) { + throw new RuntimeException("No srgb type available."); + } + + System.out.println("Read as GRAY..."); + testType(reader, gray, src); + + System.out.println("Read as sRGB..."); + testType(reader, srgb, src); + } + + private static void testType(ImageReader reader, + ImageTypeSpecifier t, + BufferedImage src) + throws IOException + { + ImageReadParam p = reader.getDefaultReadParam(); + p.setDestinationType(t); + BufferedImage dst = reader.read(0, p); + + verify(src, dst, t); + } + + private static void verify(BufferedImage src, + BufferedImage dst, + ImageTypeSpecifier type) + { + BufferedImage test = + type.createBufferedImage(src.getWidth(), src.getHeight()); + Graphics2D g = test.createGraphics(); + g.drawImage(src, 0, 0, null); + g.dispose(); + + for (int i = 0; i < colors.length; i++) { + int x = i * dx + dx / 2; + int y = h / 2; + + Color c_test = new Color(test.getRGB(x, y)); + Color c_dst = new Color(dst.getRGB(x, y)); + + if (!compareWithTolerance(c_test, c_dst, 0.01f)) { + String msg = String.format("Invalid color: %x instead of %x", + c_dst.getRGB(), c_test.getRGB()); + throw new RuntimeException("Test failed: " + msg); + } + } + System.out.println("Verified."); + } + + private static boolean compareWithTolerance(Color a, Color b, float delta) { + float[] a_rgb = new float[3]; + a_rgb = a.getRGBColorComponents(a_rgb); + float[] b_rgb = new float[3]; + b_rgb = b.getRGBColorComponents(b_rgb); + + for (int i = 0; i < 3; i++) { + if (Math.abs(a_rgb[i] - b_rgb[i]) > delta) { + return false; + } + } + return true; + } + + private static BufferedImage createTestImage(int type) { + BufferedImage img = new BufferedImage(dx * colors.length, h, type); + + Graphics2D g = img.createGraphics(); + for (int i = 0; i < colors.length; i++) { + g.setColor(colors[i]); + g.fillRect(i * dx, 0, dx, h); + } + g.dispose(); + + return img; + } +} From 9d9317de4c7c77fabef7bd8a9eecc3614d5ad795 Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Thu, 11 Jun 2009 12:40:00 -0700 Subject: [PATCH 04/23] 6820167: GCALotAtAllSafepoints + FullGCALot(ScavengeALot) options crash JVM Short-circuit gc-a-lot attempts by non-JavaThreads; SkipGCALot c'tor to elide re-entrant gc-a-lot attempts. Reviewed-by: apetrusenko, jcoomes, jmasa, kamg --- hotspot/src/share/vm/memory/gcLocker.hpp | 25 +++++++++++++++++++ .../src/share/vm/runtime/interfaceSupport.cpp | 5 +++- hotspot/src/share/vm/runtime/thread.cpp | 2 +- hotspot/src/share/vm/runtime/thread.hpp | 8 ++++++ hotspot/src/share/vm/runtime/vmThread.cpp | 1 + 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/memory/gcLocker.hpp b/hotspot/src/share/vm/memory/gcLocker.hpp index 109f4619772..8a131736976 100644 --- a/hotspot/src/share/vm/memory/gcLocker.hpp +++ b/hotspot/src/share/vm/memory/gcLocker.hpp @@ -242,6 +242,31 @@ class Pause_No_Safepoint_Verifier : public Pause_No_GC_Verifier { #endif }; +// A SkipGCALot object is used to elide the usual effect of gc-a-lot +// over a section of execution by a thread. Currently, it's used only to +// prevent re-entrant calls to GC. +class SkipGCALot : public StackObj { + private: + bool _saved; + Thread* _t; + + public: +#ifdef ASSERT + SkipGCALot(Thread* t) : _t(t) { + _saved = _t->skip_gcalot(); + _t->set_skip_gcalot(true); + } + + ~SkipGCALot() { + assert(_t->skip_gcalot(), "Save-restore protocol invariant"); + _t->set_skip_gcalot(_saved); + } +#else + SkipGCALot(Thread* t) { } + ~SkipGCALot() { } +#endif +}; + // JRT_LEAF currently can be called from either _thread_in_Java or // _thread_in_native mode. In _thread_in_native, it is ok // for another thread to trigger GC. The rest of the JRT_LEAF diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.cpp b/hotspot/src/share/vm/runtime/interfaceSupport.cpp index 9a6267c4efc..b60f3ffd7bf 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.cpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.cpp @@ -66,11 +66,14 @@ void InterfaceSupport::trace(const char* result_type, const char* header) { void InterfaceSupport::gc_alot() { Thread *thread = Thread::current(); - if (thread->is_VM_thread()) return; // Avoid concurrent calls + if (!thread->is_Java_thread()) return; // Avoid concurrent calls // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC. JavaThread *current_thread = (JavaThread *)thread; if (current_thread->active_handles() == NULL) return; + // Short-circuit any possible re-entrant gc-a-lot attempt + if (thread->skip_gcalot()) return; + if (is_init_completed()) { if (++_fullgc_alot_invocation < FullGCALotStart) { diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 1834d1491fe..5c08990e53b 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -127,6 +127,7 @@ Thread::Thread() { debug_only(_owned_locks = NULL;) debug_only(_allow_allocation_count = 0;) NOT_PRODUCT(_allow_safepoint_count = 0;) + NOT_PRODUCT(_skip_gcalot = false;) CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;) _jvmti_env_iteration_count = 0; _vm_operation_started_count = 0; @@ -784,7 +785,6 @@ void Thread::check_for_valid_safepoint_state(bool potential_vm_operation) { // We could enter a safepoint here and thus have a gc InterfaceSupport::check_gc_alot(); } - #endif } #endif diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 9043da17f42..f5529e0155a 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -191,6 +191,9 @@ class Thread: public ThreadShadow { NOT_PRODUCT(int _allow_safepoint_count;) // If 0, thread allow a safepoint to happen debug_only (int _allow_allocation_count;) // If 0, the thread is allowed to allocate oops. + // Used by SkipGCALot class. + NOT_PRODUCT(bool _skip_gcalot;) // Should we elide gc-a-lot? + // Record when GC is locked out via the GC_locker mechanism CHECK_UNHANDLED_OOPS_ONLY(int _gc_locked_out_count;) @@ -308,6 +311,11 @@ class Thread: public ThreadShadow { bool is_gc_locked_out() { return _gc_locked_out_count > 0; } #endif // CHECK_UNHANDLED_OOPS +#ifndef PRODUCT + bool skip_gcalot() { return _skip_gcalot; } + void set_skip_gcalot(bool v) { _skip_gcalot = v; } +#endif + public: // Installs a pending exception to be inserted later static void send_async_exception(oop thread_oop, oop java_throwable); diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index 56b54c381bd..c2d7c11db48 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -531,6 +531,7 @@ void VMThread::execute(VM_Operation* op) { Thread* t = Thread::current(); if (!t->is_VM_thread()) { + SkipGCALot sgcalot(t); // avoid re-entrant attempts to gc-a-lot // JavaThread or WatcherThread t->check_for_valid_safepoint_state(true); From 70fe3ca4f59916314adfc127a89ee2d8e36a12de Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Thu, 11 Jun 2009 17:19:33 -0700 Subject: [PATCH 05/23] 6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55 For heaps larger than 32Gb, the number of heap regions overflows the data type used to hold the region index in the SparsePRT structure. Changed the region indexes, card indexes, and RSet hash table buckets to ints and added some size overflow guarantees. Reviewed-by: ysr, tonyp --- .../gc_implementation/g1/g1CollectedHeap.cpp | 9 ++ .../gc_implementation/g1/g1CollectedHeap.hpp | 3 + .../gc_implementation/g1/heapRegionRemSet.cpp | 35 ++--- .../vm/gc_implementation/g1/sparsePRT.cpp | 90 ++++++----- .../vm/gc_implementation/g1/sparsePRT.hpp | 142 +++++++++--------- .../vm/gc_implementation/includeDB_gc_g1 | 2 +- 6 files changed, 150 insertions(+), 131 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 9589ce34407..1ceddfd81e6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1535,6 +1535,15 @@ jint G1CollectedHeap::initialize() { guarantee(_hrs != NULL, "Couldn't allocate HeapRegionSeq"); guarantee(_cur_alloc_region == NULL, "from constructor"); + // 6843694 - ensure that the maximum region index can fit + // in the remembered set structures. + const size_t max_region_idx = ((size_t)1 << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1; + guarantee((max_regions() - 1) <= max_region_idx, "too many regions"); + + const size_t cards_per_region = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift; + size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1; + guarantee(cards_per_region < max_cards_per_region, "too many cards per region"); + _bot_shared = new G1BlockOffsetSharedArray(_reserved, heap_word_size(init_byte_size)); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 4df0f2f9386..1508e4e7346 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -59,6 +59,9 @@ class ConcurrentZFThread; typedef GenericTaskQueue RefToScanQueue; typedef GenericTaskQueueSet RefToScanQueueSet; +typedef int RegionIdx_t; // needs to hold [ 0..max_regions() ) +typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion ) + enum G1GCThreadGroups { G1CRGroup = 0, G1ZFGroup = 1, diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp index c4b4c7d9d69..5fb5762811c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @@ -109,7 +109,7 @@ protected: return new PerRegionTable(hr); } - void add_card_work(short from_card, bool par) { + void add_card_work(CardIdx_t from_card, bool par) { if (!_bm.at(from_card)) { if (par) { if (_bm.par_at_put(from_card, 1)) { @@ -141,11 +141,11 @@ protected: // and adding a bit to the new table is never incorrect. if (loc_hr->is_in_reserved(from)) { size_t hw_offset = pointer_delta((HeapWord*)from, loc_hr->bottom()); - size_t from_card = - hw_offset >> - (CardTableModRefBS::card_shift - LogHeapWordSize); + CardIdx_t from_card = (CardIdx_t) + hw_offset >> (CardTableModRefBS::card_shift - LogHeapWordSize); - add_card_work((short) from_card, par); + assert(0 <= from_card && from_card < CardsPerRegion, "Must be in range."); + add_card_work(from_card, par); } } @@ -190,11 +190,11 @@ public: #endif } - void add_card(short from_card_index) { + void add_card(CardIdx_t from_card_index) { add_card_work(from_card_index, /*parallel*/ true); } - void seq_add_card(short from_card_index) { + void seq_add_card(CardIdx_t from_card_index) { add_card_work(from_card_index, /*parallel*/ false); } @@ -604,7 +604,7 @@ void OtherRegionsTable::add_reference(oop* from, int tid) { // Note that this may be a continued H region. HeapRegion* from_hr = _g1h->heap_region_containing_raw(from); - size_t from_hrs_ind = (size_t)from_hr->hrs_index(); + RegionIdx_t from_hrs_ind = (RegionIdx_t) from_hr->hrs_index(); // If the region is already coarsened, return. if (_coarse_map.at(from_hrs_ind)) { @@ -627,11 +627,11 @@ void OtherRegionsTable::add_reference(oop* from, int tid) { uintptr_t from_hr_bot_card_index = uintptr_t(from_hr->bottom()) >> CardTableModRefBS::card_shift; - int card_index = from_card - from_hr_bot_card_index; + CardIdx_t card_index = from_card - from_hr_bot_card_index; assert(0 <= card_index && card_index < PosParPRT::CardsPerRegion, "Must be in range."); if (G1HRRSUseSparseTable && - _sparse_table.add_card((short) from_hrs_ind, card_index)) { + _sparse_table.add_card(from_hrs_ind, card_index)) { if (G1RecordHRRSOops) { HeapRegionRemSet::record(hr(), from); #if HRRS_VERBOSE @@ -656,9 +656,9 @@ void OtherRegionsTable::add_reference(oop* from, int tid) { } // Otherwise, transfer from sparse to fine-grain. - short cards[SparsePRTEntry::CardsPerEntry]; + CardIdx_t cards[SparsePRTEntry::CardsPerEntry]; if (G1HRRSUseSparseTable) { - bool res = _sparse_table.get_cards((short) from_hrs_ind, &cards[0]); + bool res = _sparse_table.get_cards(from_hrs_ind, &cards[0]); assert(res, "There should have been an entry"); } @@ -679,13 +679,13 @@ void OtherRegionsTable::add_reference(oop* from, int tid) { // Add in the cards from the sparse table. if (G1HRRSUseSparseTable) { for (int i = 0; i < SparsePRTEntry::CardsPerEntry; i++) { - short c = cards[i]; + CardIdx_t c = cards[i]; if (c != SparsePRTEntry::NullEntry) { prt->add_card(c); } } // Now we can delete the sparse entry. - bool res = _sparse_table.delete_entry((short) from_hrs_ind); + bool res = _sparse_table.delete_entry(from_hrs_ind); assert(res, "It should have been there."); } } @@ -1030,7 +1030,7 @@ bool OtherRegionsTable::contains_reference(oop* from) const { bool OtherRegionsTable::contains_reference_locked(oop* from) const { HeapRegion* hr = _g1h->heap_region_containing_raw(from); if (hr == NULL) return false; - size_t hr_ind = hr->hrs_index(); + RegionIdx_t hr_ind = (RegionIdx_t) hr->hrs_index(); // Is this region in the coarse map? if (_coarse_map.at(hr_ind)) return true; @@ -1045,8 +1045,9 @@ bool OtherRegionsTable::contains_reference_locked(oop* from) const { uintptr_t hr_bot_card_index = uintptr_t(hr->bottom()) >> CardTableModRefBS::card_shift; assert(from_card >= hr_bot_card_index, "Inv"); - int card_index = from_card - hr_bot_card_index; - return _sparse_table.contains_card((short)hr_ind, card_index); + CardIdx_t card_index = from_card - hr_bot_card_index; + assert(0 <= card_index && card_index < PosParPRT::CardsPerRegion, "Must be in range."); + return _sparse_table.contains_card(hr_ind, card_index); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp index b8ace43a14a..7bee59dbff7 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp @@ -33,7 +33,7 @@ void SparsePRT::init_iterator(SparsePRTIter* sprt_iter) { sprt_iter->init(this); } -void SparsePRTEntry::init(short region_ind) { +void SparsePRTEntry::init(RegionIdx_t region_ind) { _region_ind = region_ind; _next_index = NullEntry; #if UNROLL_CARD_LOOPS @@ -43,11 +43,12 @@ void SparsePRTEntry::init(short region_ind) { _cards[2] = NullEntry; _cards[3] = NullEntry; #else - for (int i = 0; i < CardsPerEntry; i++) _cards[i] = NullEntry; + for (int i = 0; i < CardsPerEntry; i++) + _cards[i] = NullEntry; #endif } -bool SparsePRTEntry::contains_card(short card_index) const { +bool SparsePRTEntry::contains_card(CardIdx_t card_index) const { #if UNROLL_CARD_LOOPS assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); if (_cards[0] == card_index) return true; @@ -80,10 +81,10 @@ int SparsePRTEntry::num_valid_cards() const { return sum; } -SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(short card_index) { +SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(CardIdx_t card_index) { #if UNROLL_CARD_LOOPS assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); - short c = _cards[0]; + CardIdx_t c = _cards[0]; if (c == card_index) return found; if (c == NullEntry) { _cards[0] = card_index; return added; } c = _cards[1]; @@ -97,16 +98,19 @@ SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(short card_index) { if (c == NullEntry) { _cards[3] = card_index; return added; } #else for (int i = 0; i < CardsPerEntry; i++) { - short c = _cards[i]; + CardIdx_t c = _cards[i]; if (c == card_index) return found; - if (c == NullEntry) { _cards[i] = card_index; return added; } + if (c == NullEntry) { + _cards[i] = card_index; + return added; + } } #endif // Otherwise, we're full. return overflow; } -void SparsePRTEntry::copy_cards(short* cards) const { +void SparsePRTEntry::copy_cards(CardIdx_t* cards) const { #if UNROLL_CARD_LOOPS assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); cards[0] = _cards[0]; @@ -130,7 +134,7 @@ RSHashTable::RSHashTable(size_t capacity) : _capacity(capacity), _capacity_mask(capacity-1), _occupied_entries(0), _occupied_cards(0), _entries(NEW_C_HEAP_ARRAY(SparsePRTEntry, capacity)), - _buckets(NEW_C_HEAP_ARRAY(short, capacity)), + _buckets(NEW_C_HEAP_ARRAY(int, capacity)), _next_deleted(NULL), _deleted(false), _free_list(NullEntry), _free_region(0) { @@ -143,7 +147,7 @@ RSHashTable::~RSHashTable() { _entries = NULL; } if (_buckets != NULL) { - FREE_C_HEAP_ARRAY(short, _buckets); + FREE_C_HEAP_ARRAY(int, _buckets); _buckets = NULL; } } @@ -153,14 +157,18 @@ void RSHashTable::clear() { _occupied_cards = 0; guarantee(_entries != NULL, "INV"); guarantee(_buckets != NULL, "INV"); + + guarantee(_capacity <= ((size_t)1 << (sizeof(int)*BitsPerByte-1)) - 1, + "_capacity too large"); + // This will put -1 == NullEntry in the key field of all entries. memset(_entries, -1, _capacity * sizeof(SparsePRTEntry)); - memset(_buckets, -1, _capacity * sizeof(short)); + memset(_buckets, -1, _capacity * sizeof(int)); _free_list = NullEntry; _free_region = 0; } -bool RSHashTable::add_card(short region_ind, short card_index) { +bool RSHashTable::add_card(RegionIdx_t region_ind, CardIdx_t card_index) { SparsePRTEntry* e = entry_for_region_ind_create(region_ind); assert(e != NULL && e->r_ind() == region_ind, "Postcondition of call above."); @@ -175,9 +183,9 @@ bool RSHashTable::add_card(short region_ind, short card_index) { return res != SparsePRTEntry::overflow; } -bool RSHashTable::get_cards(short region_ind, short* cards) { - short ind = (short) (region_ind & capacity_mask()); - short cur_ind = _buckets[ind]; +bool RSHashTable::get_cards(RegionIdx_t region_ind, CardIdx_t* cards) { + int ind = (int) (region_ind & capacity_mask()); + int cur_ind = _buckets[ind]; SparsePRTEntry* cur; while (cur_ind != NullEntry && (cur = entry(cur_ind))->r_ind() != region_ind) { @@ -192,10 +200,10 @@ bool RSHashTable::get_cards(short region_ind, short* cards) { return true; } -bool RSHashTable::delete_entry(short region_ind) { - short ind = (short) (region_ind & capacity_mask()); - short* prev_loc = &_buckets[ind]; - short cur_ind = *prev_loc; +bool RSHashTable::delete_entry(RegionIdx_t region_ind) { + int ind = (int) (region_ind & capacity_mask()); + int* prev_loc = &_buckets[ind]; + int cur_ind = *prev_loc; SparsePRTEntry* cur; while (cur_ind != NullEntry && (cur = entry(cur_ind))->r_ind() != region_ind) { @@ -212,10 +220,11 @@ bool RSHashTable::delete_entry(short region_ind) { return true; } -SparsePRTEntry* RSHashTable::entry_for_region_ind(short region_ind) const { +SparsePRTEntry* +RSHashTable::entry_for_region_ind(RegionIdx_t region_ind) const { assert(occupied_entries() < capacity(), "Precondition"); - short ind = (short) (region_ind & capacity_mask()); - short cur_ind = _buckets[ind]; + int ind = (int) (region_ind & capacity_mask()); + int cur_ind = _buckets[ind]; SparsePRTEntry* cur; // XXX // int k = 0; @@ -242,15 +251,16 @@ SparsePRTEntry* RSHashTable::entry_for_region_ind(short region_ind) const { } } -SparsePRTEntry* RSHashTable::entry_for_region_ind_create(short region_ind) { +SparsePRTEntry* +RSHashTable::entry_for_region_ind_create(RegionIdx_t region_ind) { SparsePRTEntry* res = entry_for_region_ind(region_ind); if (res == NULL) { - short new_ind = alloc_entry(); + int new_ind = alloc_entry(); assert(0 <= new_ind && (size_t)new_ind < capacity(), "There should be room."); res = entry(new_ind); res->init(region_ind); // Insert at front. - short ind = (short) (region_ind & capacity_mask()); + int ind = (int) (region_ind & capacity_mask()); res->set_next_index(_buckets[ind]); _buckets[ind] = new_ind; _occupied_entries++; @@ -258,8 +268,8 @@ SparsePRTEntry* RSHashTable::entry_for_region_ind_create(short region_ind) { return res; } -short RSHashTable::alloc_entry() { - short res; +int RSHashTable::alloc_entry() { + int res; if (_free_list != NullEntry) { res = _free_list; _free_list = entry(res)->next_index(); @@ -273,13 +283,11 @@ short RSHashTable::alloc_entry() { } } - -void RSHashTable::free_entry(short fi) { +void RSHashTable::free_entry(int fi) { entry(fi)->set_next_index(_free_list); _free_list = fi; } - void RSHashTable::add_entry(SparsePRTEntry* e) { assert(e->num_valid_cards() > 0, "Precondition."); SparsePRTEntry* e2 = entry_for_region_ind_create(e->r_ind()); @@ -322,8 +330,8 @@ RSHashTable* RSHashTable::get_from_deleted_list() { return NULL; } -short /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() { - short res; +CardIdx_t /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() { + CardIdx_t res; while (_bl_ind != RSHashTable::NullEntry) { res = _rsht->entry(_bl_ind)->card(0); if (res != SparsePRTEntry::NullEntry) { @@ -336,7 +344,7 @@ short /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() { return SparsePRTEntry::NullEntry; } -size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(short ci) { +size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(CardIdx_t ci) { return _heap_bot_card_ind + (_rsht->entry(_bl_ind)->r_ind() * CardsPerRegion) @@ -345,7 +353,7 @@ size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(short ci) { bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) { _card_ind++; - short ci; + CardIdx_t ci; if (_card_ind < SparsePRTEntry::CardsPerEntry && ((ci = _rsht->entry(_bl_ind)->card(_card_ind)) != SparsePRTEntry::NullEntry)) { @@ -379,16 +387,16 @@ bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) { return false; } -bool RSHashTable::contains_card(short region_index, short card_index) const { +bool RSHashTable::contains_card(RegionIdx_t region_index, CardIdx_t card_index) const { SparsePRTEntry* e = entry_for_region_ind(region_index); return (e != NULL && e->contains_card(card_index)); } size_t RSHashTable::mem_size() const { - return sizeof(this) + capacity() * (sizeof(SparsePRTEntry) + sizeof(short)); + return sizeof(this) + + capacity() * (sizeof(SparsePRTEntry) + sizeof(int)); } - // ---------------------------------------------------------------------- SparsePRT* SparsePRT::_head_expanded_list = NULL; @@ -408,6 +416,7 @@ void SparsePRT::add_to_expanded_list(SparsePRT* sprt) { } } + SparsePRT* SparsePRT::get_from_expanded_list() { SparsePRT* hd = _head_expanded_list; while (hd != NULL) { @@ -452,6 +461,7 @@ SparsePRT::SparsePRT(HeapRegion* hr) : _next = _cur; } + SparsePRT::~SparsePRT() { assert(_next != NULL && _cur != NULL, "Inv"); if (_cur != _next) { delete _cur; } @@ -465,7 +475,7 @@ size_t SparsePRT::mem_size() const { return sizeof(this) + _next->mem_size(); } -bool SparsePRT::add_card(short region_id, short card_index) { +bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) { #if SPARSE_PRT_VERBOSE gclog_or_tty->print_cr(" Adding card %d from region %d to region %d sparse.", card_index, region_id, _hr->hrs_index()); @@ -476,11 +486,11 @@ bool SparsePRT::add_card(short region_id, short card_index) { return _next->add_card(region_id, card_index); } -bool SparsePRT::get_cards(short region_id, short* cards) { +bool SparsePRT::get_cards(RegionIdx_t region_id, CardIdx_t* cards) { return _next->get_cards(region_id, cards); } -bool SparsePRT::delete_entry(short region_id) { +bool SparsePRT::delete_entry(RegionIdx_t region_id) { return _next->delete_entry(region_id); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp index 6ff7b62ee1d..d5ab0d5181e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp @@ -35,32 +35,32 @@ class SparsePRTEntry: public CHeapObj { public: + enum SomePublicConstants { - CardsPerEntry = (short)4, - NullEntry = (short)-1, - DeletedEntry = (short)-2 + CardsPerEntry = 4, + NullEntry = -1 }; private: - short _region_ind; - short _next_index; - short _cards[CardsPerEntry]; + RegionIdx_t _region_ind; + int _next_index; + CardIdx_t _cards[CardsPerEntry]; public: // Set the region_ind to the given value, and delete all cards. - inline void init(short region_ind); + inline void init(RegionIdx_t region_ind); - short r_ind() const { return _region_ind; } + RegionIdx_t r_ind() const { return _region_ind; } bool valid_entry() const { return r_ind() >= 0; } - void set_r_ind(short rind) { _region_ind = rind; } + void set_r_ind(RegionIdx_t rind) { _region_ind = rind; } - short next_index() const { return _next_index; } - short* next_index_addr() { return &_next_index; } - void set_next_index(short ni) { _next_index = ni; } + int next_index() const { return _next_index; } + int* next_index_addr() { return &_next_index; } + void set_next_index(int ni) { _next_index = ni; } // Returns "true" iff the entry contains the given card index. - inline bool contains_card(short card_index) const; + inline bool contains_card(CardIdx_t card_index) const; // Returns the number of non-NULL card entries. inline int num_valid_cards() const; @@ -73,14 +73,14 @@ public: found, added }; - inline AddCardResult add_card(short card_index); + inline AddCardResult add_card(CardIdx_t card_index); // Copy the current entry's cards into "cards". - inline void copy_cards(short* cards) const; + inline void copy_cards(CardIdx_t* cards) const; // Copy the current entry's cards into the "_card" array of "e." inline void copy_cards(SparsePRTEntry* e) const; - inline short card(int i) const { return _cards[i]; } + inline CardIdx_t card(int i) const { return _cards[i]; } }; @@ -98,9 +98,9 @@ class RSHashTable : public CHeapObj { size_t _occupied_cards; SparsePRTEntry* _entries; - short* _buckets; - short _free_region; - short _free_list; + int* _buckets; + int _free_region; + int _free_list; static RSHashTable* _head_deleted_list; RSHashTable* _next_deleted; @@ -113,20 +113,20 @@ class RSHashTable : public CHeapObj { // operations, and that the the table be less than completely full. If // an entry for "region_ind" is already in the table, finds it and // returns its address; otherwise returns "NULL." - SparsePRTEntry* entry_for_region_ind(short region_ind) const; + SparsePRTEntry* entry_for_region_ind(RegionIdx_t region_ind) const; // Requires that the caller hold a lock preventing parallel modifying // operations, and that the the table be less than completely full. If // an entry for "region_ind" is already in the table, finds it and // returns its address; otherwise allocates, initializes, inserts and // returns a new entry for "region_ind". - SparsePRTEntry* entry_for_region_ind_create(short region_ind); + SparsePRTEntry* entry_for_region_ind_create(RegionIdx_t region_ind); // Returns the index of the next free entry in "_entries". - short alloc_entry(); + int alloc_entry(); // Declares the entry "fi" to be free. (It must have already been // deleted from any bucket lists. - void free_entry(short fi); + void free_entry(int fi); public: RSHashTable(size_t capacity); @@ -138,12 +138,12 @@ public: // Otherwise, returns "false" to indicate that the addition would // overflow the entry for the region. The caller must transfer these // entries to a larger-capacity representation. - bool add_card(short region_id, short card_index); + bool add_card(RegionIdx_t region_id, CardIdx_t card_index); - bool get_cards(short region_id, short* cards); - bool delete_entry(short region_id); + bool get_cards(RegionIdx_t region_id, CardIdx_t* cards); + bool delete_entry(RegionIdx_t region_id); - bool contains_card(short region_id, short card_index) const; + bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const; void add_entry(SparsePRTEntry* e); @@ -162,52 +162,50 @@ public: static void add_to_deleted_list(RSHashTable* rsht); static RSHashTable* get_from_deleted_list(); - - }; - // ValueObj because will be embedded in HRRS iterator. +// ValueObj because will be embedded in HRRS iterator. class RSHashTableIter VALUE_OBJ_CLASS_SPEC { - short _tbl_ind; - short _bl_ind; - short _card_ind; - RSHashTable* _rsht; - size_t _heap_bot_card_ind; - - enum SomePrivateConstants { - CardsPerRegion = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift - }; - - // If the bucket list pointed to by _bl_ind contains a card, sets - // _bl_ind to the index of that entry, and returns the card. - // Otherwise, returns SparseEntry::NullEnty. - short find_first_card_in_list(); - // Computes the proper card index for the card whose offset in the - // current region (as indicated by _bl_ind) is "ci". - // This is subject to errors when there is iteration concurrent with - // modification, but these errors should be benign. - size_t compute_card_ind(short ci); - - public: - RSHashTableIter(size_t heap_bot_card_ind) : - _tbl_ind(RSHashTable::NullEntry), - _bl_ind(RSHashTable::NullEntry), - _card_ind((SparsePRTEntry::CardsPerEntry-1)), - _rsht(NULL), - _heap_bot_card_ind(heap_bot_card_ind) - {} - - void init(RSHashTable* rsht) { - _rsht = rsht; - _tbl_ind = -1; // So that first increment gets to 0. - _bl_ind = RSHashTable::NullEntry; - _card_ind = (SparsePRTEntry::CardsPerEntry-1); - } - - bool has_next(size_t& card_index); + int _tbl_ind; // [-1, 0.._rsht->_capacity) + int _bl_ind; // [-1, 0.._rsht->_capacity) + short _card_ind; // [0..CardsPerEntry) + RSHashTable* _rsht; + size_t _heap_bot_card_ind; + enum SomePrivateConstants { + CardsPerRegion = HeapRegion::GrainBytes >> CardTableModRefBS::card_shift }; + // If the bucket list pointed to by _bl_ind contains a card, sets + // _bl_ind to the index of that entry, and returns the card. + // Otherwise, returns SparseEntry::NullEntry. + CardIdx_t find_first_card_in_list(); + + // Computes the proper card index for the card whose offset in the + // current region (as indicated by _bl_ind) is "ci". + // This is subject to errors when there is iteration concurrent with + // modification, but these errors should be benign. + size_t compute_card_ind(CardIdx_t ci); + +public: + RSHashTableIter(size_t heap_bot_card_ind) : + _tbl_ind(RSHashTable::NullEntry), + _bl_ind(RSHashTable::NullEntry), + _card_ind((SparsePRTEntry::CardsPerEntry-1)), + _rsht(NULL), + _heap_bot_card_ind(heap_bot_card_ind) + {} + + void init(RSHashTable* rsht) { + _rsht = rsht; + _tbl_ind = -1; // So that first increment gets to 0. + _bl_ind = RSHashTable::NullEntry; + _card_ind = (SparsePRTEntry::CardsPerEntry-1); + } + + bool has_next(size_t& card_index); +}; + // Concurrent accesss to a SparsePRT must be serialized by some external // mutex. @@ -238,7 +236,6 @@ class SparsePRT VALUE_OBJ_CLASS_SPEC { SparsePRT* next_expanded() { return _next_expanded; } void set_next_expanded(SparsePRT* nxt) { _next_expanded = nxt; } - static SparsePRT* _head_expanded_list; public: @@ -255,16 +252,16 @@ public: // Otherwise, returns "false" to indicate that the addition would // overflow the entry for the region. The caller must transfer these // entries to a larger-capacity representation. - bool add_card(short region_id, short card_index); + bool add_card(RegionIdx_t region_id, CardIdx_t card_index); // If the table hold an entry for "region_ind", Copies its // cards into "cards", which must be an array of length at least // "CardsPerEntry", and returns "true"; otherwise, returns "false". - bool get_cards(short region_ind, short* cards); + bool get_cards(RegionIdx_t region_ind, CardIdx_t* cards); // If there is an entry for "region_ind", removes it and return "true"; // otherwise returns "false." - bool delete_entry(short region_ind); + bool delete_entry(RegionIdx_t region_ind); // Clear the table, and reinitialize to initial capacity. void clear(); @@ -276,13 +273,12 @@ public: static void cleanup_all(); RSHashTable* cur() const { return _cur; } - void init_iterator(SparsePRTIter* sprt_iter); static void add_to_expanded_list(SparsePRT* sprt); static SparsePRT* get_from_expanded_list(); - bool contains_card(short region_id, short card_index) const { + bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const { return _next->contains_card(region_id, card_index); } diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 index 14c5057e90f..f7236edafe6 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 @@ -51,7 +51,6 @@ concurrentG1Refine.hpp globalDefinitions.hpp concurrentG1Refine.hpp allocation.hpp concurrentG1Refine.hpp thread.hpp - concurrentG1RefineThread.cpp concurrentG1Refine.hpp concurrentG1RefineThread.cpp concurrentG1RefineThread.hpp concurrentG1RefineThread.cpp g1CollectedHeap.inline.hpp @@ -334,6 +333,7 @@ sparsePRT.cpp space.inline.hpp sparsePRT.hpp allocation.hpp sparsePRT.hpp cardTableModRefBS.hpp sparsePRT.hpp globalDefinitions.hpp +sparsePRT.hpp g1CollectedHeap.inline.hpp sparsePRT.hpp heapRegion.hpp sparsePRT.hpp mutex.hpp From 10002fa2ff4aa8fc52c7a35b72f02d0195eb6a4c Mon Sep 17 00:00:00 2001 From: John Coomes Date: Sun, 7 Jun 2009 22:08:24 -0700 Subject: [PATCH 06/23] 6814552: par compact - some compilers fail to optimize bitmap code Reviewed-by: tonyp, iveresov, jmasa, ysr --- .../vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp index ca2ea6f9d9d..482b1a452e4 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp @@ -177,6 +177,7 @@ private: // are double-word aligned in 32-bit VMs, but not in 64-bit VMs, so the 32-bit // granularity is 2, 64-bit is 1. static inline size_t obj_granularity() { return size_t(MinObjAlignment); } + static inline int obj_granularity_shift() { return LogMinObjAlignment; } HeapWord* _region_start; size_t _region_size; @@ -299,13 +300,13 @@ inline bool ParMarkBitMap::is_unmarked(oop obj) const inline size_t ParMarkBitMap::bits_to_words(idx_t bits) { - return bits * obj_granularity(); + return bits << obj_granularity_shift(); } inline ParMarkBitMap::idx_t ParMarkBitMap::words_to_bits(size_t words) { - return words / obj_granularity(); + return words >> obj_granularity_shift(); } inline size_t ParMarkBitMap::obj_size(idx_t beg_bit, idx_t end_bit) const From 83632f1cab05dbdd72d5c7487b1bf6187690952b Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Thu, 11 Jun 2009 13:47:42 +0400 Subject: [PATCH 07/23] 6296893: BMP Writer handles TopDown property incorrectly for some of the compression types Reviewed-by: igor, prr --- .../imageio/plugins/bmp/BMPImageWriter.java | 17 ++- .../imageio/plugins/bmp/TopDownTest.java | 142 ++++++++++++++++++ 2 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 jdk/test/javax/imageio/plugins/bmp/TopDownTest.java diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java index d70f8f03181..1b0d0864340 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java @@ -506,6 +506,19 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants { writeFileHeader(fileSize, offset); + /* According to MSDN description, the top-down image layout + * is allowed only if compression type is BI_RGB or BI_BITFIELDS. + * Images with any other compression type must be wrote in the + * bottom-up layout. + */ + if (compressionType == BMPConstants.BI_RGB || + compressionType == BMPConstants.BI_BITFIELDS) + { + isTopDown = bmpParam.isTopDown(); + } else { + isTopDown = false; + } + writeInfoHeader(headerSize, bitsPerPixel); // compression @@ -588,8 +601,6 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants { return; } - isTopDown = bmpParam.isTopDown(); - int maxBandOffset = bandOffsets[0]; for (int i = 1; i < bandOffsets.length; i++) if (bandOffsets[i] > maxBandOffset) @@ -1299,7 +1310,7 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants { stream.writeInt(w); // height - stream.writeInt(h); + stream.writeInt(isTopDown ? -h : h); // number of planes stream.writeShort(1); diff --git a/jdk/test/javax/imageio/plugins/bmp/TopDownTest.java b/jdk/test/javax/imageio/plugins/bmp/TopDownTest.java new file mode 100644 index 00000000000..0163dae5922 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/bmp/TopDownTest.java @@ -0,0 +1,142 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6296893 + * @summary Test verifies that the isTopDown flag does not cause + * a writing of bmp image in wrong scanline layout. + * @run main TopDownTest + */ + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; + +import java.awt.image.IndexColorModel; +import java.io.File; +import java.io.IOException; +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.plugins.bmp.BMPImageWriteParam; +import javax.imageio.stream.ImageOutputStream; +import static java.awt.image.BufferedImage.TYPE_INT_RGB; +import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED; + +public class TopDownTest { + + public static void main(String[] args) throws IOException { + BufferedImage src = createTestImage(24); + + writeWithCompression(src, "BI_BITFIELDS"); + + writeWithCompression(src, "BI_RGB"); + + src = createTestImage(8); + writeWithCompression(src, "BI_RLE8"); + + src = createTestImage(4); + writeWithCompression(src, "BI_RLE4"); + + } + + private static void writeWithCompression(BufferedImage src, + String compression) throws IOException + { + System.out.println("Compression: " + compression); + ImageWriter writer = ImageIO.getImageWritersByFormatName("BMP").next(); + if (writer == null) { + throw new RuntimeException("Test failed: no bmp writer available"); + } + File fout = File.createTempFile(compression + "_", ".bmp", + new File(".")); + + ImageOutputStream ios = ImageIO.createImageOutputStream(fout); + writer.setOutput(ios); + + BMPImageWriteParam param = (BMPImageWriteParam) + writer.getDefaultWriteParam(); + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionType(compression); + param.setTopDown(true); + writer.write(null, new IIOImage(src, null, null), param); + writer.dispose(); + ios.flush(); + ios.close(); + + BufferedImage dst = ImageIO.read(fout); + + verify(dst); + } + + private static void verify(BufferedImage dst) { + int top_rgb = dst.getRGB(50, 25); + System.out.printf("top_rgb: %x\n", top_rgb); + int bot_rgb = dst.getRGB(50, 75); + System.out.printf("bot_rgb: %x\n", bot_rgb); + + // expect to see blue color on the top of image + if (top_rgb != 0xff0000ff) { + throw new RuntimeException("Invaid top color: " + + Integer.toHexString(bot_rgb)); + } + if (bot_rgb != 0xffff0000) { + throw new RuntimeException("Invalid bottom color: " + + Integer.toHexString(bot_rgb)); + } + } + + private static BufferedImage createTestImage(int bpp) { + + BufferedImage img = null; + switch (bpp) { + case 8: + img = new BufferedImage(100, 100, TYPE_BYTE_INDEXED); + break; + case 4: { + byte[] r = new byte[16]; + byte[] g = new byte[16]; + byte[] b = new byte[16]; + + r[1] = (byte)0xff; + b[0] = (byte)0xff; + + IndexColorModel icm = new IndexColorModel(4, 16, r, g, b); + img = new BufferedImage(100, 100, TYPE_BYTE_INDEXED, icm); + } + break; + case 24: + default: + img = new BufferedImage(100, 100, TYPE_INT_RGB); + } + Graphics g = img.createGraphics(); + g.setColor(Color.blue); + g.fillRect(0, 0, 100, 50); + g.setColor(Color.red); + g.fillRect(0, 50, 100, 50); + g.dispose(); + return img; + } +} From d78db1b0c76940a0c12dab6a8afb802866cd0be0 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Thu, 11 Jun 2009 14:22:33 +0400 Subject: [PATCH 08/23] 5101862: WBMP Image reader tries to load Quicktime MOV files Reviewed-by: igor, prr --- .../imageio/plugins/common/ReaderUtil.java | 15 ++ .../imageio/plugins/wbmp/WBMPImageReader.java | 16 +-- .../plugins/wbmp/WBMPImageReaderSpi.java | 44 +++++- .../imageio/plugins/wbmp/CanDecodeTest.java | 131 ++++++++++++++++++ 4 files changed, 187 insertions(+), 19 deletions(-) create mode 100644 jdk/test/javax/imageio/plugins/wbmp/CanDecodeTest.java diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java b/jdk/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java index 1f0068c2048..36865df60d7 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java @@ -27,6 +27,8 @@ package com.sun.imageio.plugins.common; import java.awt.Point; import java.awt.Rectangle; +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; /** * This class contains utility methods that may be useful to ImageReader @@ -198,4 +200,17 @@ public class ReaderUtil { vals, 1); return vals; } + + public static int readMultiByteInteger(ImageInputStream iis) + throws IOException + { + int value = iis.readByte(); + int result = value & 0x7f; + while((value & 0x80) == 0x80) { + result <<= 7; + value = iis.readByte(); + result |= (value & 0x7f); + } + return result; + } } diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java index e8da025b3cb..707a5419256 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java @@ -45,6 +45,7 @@ import java.util.ArrayList; import java.util.Iterator; import com.sun.imageio.plugins.common.I18N; +import com.sun.imageio.plugins.common.ReaderUtil; /** This class is the Java Image IO plugin reader for WBMP images. * It may subsample the image, clip the image, @@ -141,11 +142,11 @@ public class WBMPImageReader extends ImageReader { metadata.wbmpType = wbmpType; // Read image width - width = readMultiByteInteger(); + width = ReaderUtil.readMultiByteInteger(iis); metadata.width = width; // Read image height - height = readMultiByteInteger(); + height = ReaderUtil.readMultiByteInteger(iis); metadata.height = height; gotHeader = true; @@ -311,17 +312,6 @@ public class WBMPImageReader extends ImageReader { gotHeader = false; } - private int readMultiByteInteger() throws IOException { - int value = iis.readByte(); - int result = value & 0x7f; - while((value & 0x80) == 0x80) { - result <<= 7; - value = iis.readByte(); - result |= (value & 0x7f); - } - return result; - } - /* * This method verifies that given byte is valid wbmp type marker. * At the moment only 0x0 marker is described by wbmp spec. diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java index 2d882ab6b2c..cb4f3bce205 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java @@ -33,9 +33,13 @@ import javax.imageio.spi.ServiceRegistry; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; +import com.sun.imageio.plugins.common.ReaderUtil; public class WBMPImageReaderSpi extends ImageReaderSpi { + private static final int MAX_WBMP_WIDTH = 1024; + private static final int MAX_WBMP_HEIGHT = 768; + private static String [] writerSpiNames = {"com.sun.imageio.plugins.wbmp.WBMPImageWriterSpi"}; private static String[] formatNames = {"wbmp", "WBMP"}; @@ -79,16 +83,44 @@ public class WBMPImageReaderSpi extends ImageReaderSpi { } ImageInputStream stream = (ImageInputStream)source; - byte[] b = new byte[3]; stream.mark(); - stream.readFully(b); + int type = stream.readByte(); // TypeField + int fixHeaderField = stream.readByte(); + // check WBMP "header" + if (type != 0 || fixHeaderField != 0) { + // while WBMP reader does not support ext WBMP headers + stream.reset(); + return false; + } + + int width = ReaderUtil.readMultiByteInteger(stream); + int height = ReaderUtil.readMultiByteInteger(stream); + // check image dimension + if (width <= 0 || height <= 0) { + stream.reset(); + return false; + } + + long dataLength = stream.length(); + if (dataLength == -1) { + // We can't verify that amount of data in the stream + // corresponds to image dimension because we do not know + // the length of the data stream. + // Assuming that wbmp image are used for mobile devices, + // let's introduce an upper limit for image dimension. + // In case if exact amount of raster data is unknown, + // let's reject images with dimension above the limit. + stream.reset(); + return (width < MAX_WBMP_WIDTH) && (height < MAX_WBMP_HEIGHT); + } + + dataLength -= stream.getStreamPosition(); stream.reset(); - return ((b[0] == (byte)0) && // TypeField == 0 - b[1] == 0 && // FixHeaderField == 0xxx00000; not support ext header - ((b[2] & 0x8f) != 0 || (b[2] & 0x7f) != 0)); // First width byte - //XXX: b[2] & 0x8f) != 0 for the bug in Sony Ericsson encoder. + long scanSize = (width / 8) + ((width % 8) == 0 ? 0 : 1); + + return (dataLength == scanSize * height); } public ImageReader createReaderInstance(Object extension) diff --git a/jdk/test/javax/imageio/plugins/wbmp/CanDecodeTest.java b/jdk/test/javax/imageio/plugins/wbmp/CanDecodeTest.java new file mode 100644 index 00000000000..adaecdce419 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/wbmp/CanDecodeTest.java @@ -0,0 +1,131 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 5101862 + * @summary Test verifies that SPI of WBMP image reader + * does not claims to be able to decode QT movies, + * tga images, or ico files. + * @run main CanDecodeTest + */ + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Vector; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; + +public class CanDecodeTest { + + public static void main(String[] args) throws IOException { + ImageReader r = + ImageIO.getImageReadersByFormatName("WBMP").next(); + ImageReaderSpi spi = r.getOriginatingProvider(); + + Vector tests = getTestCases(); + for (TestCase t : tests) { + t.doTest(spi); + } + System.out.println("Test passed."); + } + + private static Vector getTestCases() { + Vector v = new Vector(4); + v.add(new TestCase("wbmp", new byte[]{(byte) 0x00, (byte) 0x00, + (byte) 0x60, (byte) 0x14}, 244, true)); + v.add(new TestCase("mov", new byte[]{(byte) 0x00, (byte) 0x00, + (byte) 0x07, (byte) 0xb5, (byte) 0x6d}, 82397, false)); + v.add(new TestCase("tga", new byte[]{(byte) 0x00, (byte) 0x00, + (byte) 0x0a, (byte) 0x00}, 39693, false)); + v.add(new TestCase("ico", new byte[]{(byte) 0x00, (byte) 0x00, + (byte) 0x01, (byte) 0x00}, 1078, false)); + return v; + } + + private static class TestCase { + + private String title; + private byte[] header; + private int dataLength; + private boolean canDecode; + + public TestCase(String title, byte[] header, + int dataLength, boolean canDecode) { + this.title = title; + this.dataLength = dataLength; + this.header = header.clone(); + this.canDecode = canDecode; + + } + + public void doTest(ImageReaderSpi spi) throws IOException { + System.out.println("Test for " + title + + (canDecode ? " (can decode)" : " (can't decode)")); + System.out.print("As a stream..."); + ImageInputStream iis = + ImageIO.createImageInputStream(getDataStream()); + + if (spi.canDecodeInput(iis) != canDecode) { + throw new RuntimeException("Test failed: wrong decideion " + + "for stream data"); + } + System.out.println("OK"); + + System.out.print("As a file..."); + iis = ImageIO.createImageInputStream(getDataFile()); + if (spi.canDecodeInput(iis) != canDecode) { + throw new RuntimeException("Test failed: wrong decideion " + + "for file data"); + } + System.out.println("OK"); + } + + private byte[] getData() { + byte[] data = new byte[dataLength]; + Arrays.fill(data, (byte) 0); + System.arraycopy(header, 0, data, 0, header.length); + + return data; + } + public InputStream getDataStream() { + return new ByteArrayInputStream(getData()); + } + + public File getDataFile() throws IOException { + File f = File.createTempFile("wbmp_", "." + title, new File(".")); + FileOutputStream fos = new FileOutputStream(f); + fos.write(getData()); + fos.flush(); + fos.close(); + + return f; + } + } +} From 24f3527be23f586cc0fcca8ee9b71d71074d52f9 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Thu, 11 Jun 2009 13:31:01 -0700 Subject: [PATCH 09/23] 6849716: BitMap - performance regression introduced with G1 Make verification code visible only in debug builds Reviewed-by: iveresov, ysr, johnc, apetrusenko, tonyp --- hotspot/src/share/vm/includeDB_compiler1 | 2 +- hotspot/src/share/vm/utilities/bitMap.cpp | 13 ------------- hotspot/src/share/vm/utilities/bitMap.hpp | 9 +++++---- hotspot/src/share/vm/utilities/bitMap.inline.hpp | 11 +++++++++++ hotspot/src/share/vm/utilities/macros.hpp | 2 ++ 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/hotspot/src/share/vm/includeDB_compiler1 b/hotspot/src/share/vm/includeDB_compiler1 index af25216cf55..6f33d724516 100644 --- a/hotspot/src/share/vm/includeDB_compiler1 +++ b/hotspot/src/share/vm/includeDB_compiler1 @@ -387,7 +387,7 @@ c1_ValueMap.hpp c1_ValueSet.hpp c1_ValueSet.cpp c1_ValueSet.hpp c1_ValueSet.hpp allocation.hpp -c1_ValueSet.hpp bitMap.hpp +c1_ValueSet.hpp bitMap.inline.hpp c1_ValueSet.hpp c1_Instruction.hpp c1_ValueStack.cpp c1_IR.hpp diff --git a/hotspot/src/share/vm/utilities/bitMap.cpp b/hotspot/src/share/vm/utilities/bitMap.cpp index 13f4721ca56..f2f54fa814c 100644 --- a/hotspot/src/share/vm/utilities/bitMap.cpp +++ b/hotspot/src/share/vm/utilities/bitMap.cpp @@ -41,19 +41,6 @@ BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) : resize(size_in_bits, in_resource_area); } - -void BitMap::verify_index(idx_t index) const { - assert(index < _size, "BitMap index out of bounds"); -} - -void BitMap::verify_range(idx_t beg_index, idx_t end_index) const { -#ifdef ASSERT - assert(beg_index <= end_index, "BitMap range error"); - // Note that [0,0) and [size,size) are both valid ranges. - if (end_index != _size) verify_index(end_index); -#endif -} - void BitMap::resize(idx_t size_in_bits, bool in_resource_area) { assert(size_in_bits >= 0, "just checking"); idx_t old_size_in_words = size_in_words(); diff --git a/hotspot/src/share/vm/utilities/bitMap.hpp b/hotspot/src/share/vm/utilities/bitMap.hpp index 899d65a07df..89818dfa6f2 100644 --- a/hotspot/src/share/vm/utilities/bitMap.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.hpp @@ -93,10 +93,12 @@ class BitMap VALUE_OBJ_CLASS_SPEC { // The index of the first full word in a range. idx_t word_index_round_up(idx_t bit) const; - // Verification, statistics. - void verify_index(idx_t index) const; - void verify_range(idx_t beg_index, idx_t end_index) const; + // Verification. + inline void verify_index(idx_t index) const NOT_DEBUG_RETURN; + inline void verify_range(idx_t beg_index, idx_t end_index) const + NOT_DEBUG_RETURN; + // Statistics. static idx_t* _pop_count_table; static void init_pop_count_table(); static idx_t num_set_bits(bm_word_t w); @@ -287,7 +289,6 @@ class BitMap VALUE_OBJ_CLASS_SPEC { #endif }; - // Convenience class wrapping BitMap which provides multiple bits per slot. class BitMap2D VALUE_OBJ_CLASS_SPEC { public: diff --git a/hotspot/src/share/vm/utilities/bitMap.inline.hpp b/hotspot/src/share/vm/utilities/bitMap.inline.hpp index 3f59e01a57d..7abce42c35d 100644 --- a/hotspot/src/share/vm/utilities/bitMap.inline.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.inline.hpp @@ -22,6 +22,17 @@ * */ +#ifdef ASSERT +inline void BitMap::verify_index(idx_t index) const { + assert(index < _size, "BitMap index out of bounds"); +} + +inline void BitMap::verify_range(idx_t beg_index, idx_t end_index) const { + assert(beg_index <= end_index, "BitMap range error"); + // Note that [0,0) and [size,size) are both valid ranges. + if (end_index != _size) verify_index(end_index); +} +#endif // #ifdef ASSERT inline void BitMap::set_bit(idx_t bit) { verify_index(bit); diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index 20b2871c583..1d7cb9cce19 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -106,11 +106,13 @@ #ifdef ASSERT #define DEBUG_ONLY(code) code #define NOT_DEBUG(code) +#define NOT_DEBUG_RETURN /*next token must be ;*/ // Historical. #define debug_only(code) code #else // ASSERT #define DEBUG_ONLY(code) #define NOT_DEBUG(code) code +#define NOT_DEBUG_RETURN {} #define debug_only(code) #endif // ASSERT From f741e2fceb29a8b3b6eb05c7109237bb16a9efc3 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Fri, 12 Jun 2009 16:20:16 -0400 Subject: [PATCH 10/23] 6850846: G1: extend G1 marking verification Extend G1 marking verification to use either the "prev" or "next" marking information, as appropriate. Reviewed-by: johnc, ysr --- .../gc_implementation/g1/concurrentMark.cpp | 15 +++-- .../gc_implementation/g1/g1CollectedHeap.cpp | 58 +++++++++++++------ .../gc_implementation/g1/g1CollectedHeap.hpp | 42 ++++++++++++-- .../vm/gc_implementation/g1/heapRegion.cpp | 24 +++++--- .../vm/gc_implementation/g1/heapRegion.hpp | 11 +++- 5 files changed, 117 insertions(+), 33 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 59ff099d87a..34880cc7eb6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -1157,6 +1157,13 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { } else { // We're done with marking. JavaThread::satb_mark_queue_set().set_active_all_threads(false); + + if (VerifyDuringGC) { + g1h->prepare_for_verify(); + g1h->verify(/* allow_dirty */ true, + /* silent */ false, + /* use_prev_marking */ false); + } } #if VERIFY_OBJS_PROCESSED @@ -1747,12 +1754,12 @@ void ConcurrentMark::cleanup() { // races with it goes around and waits for completeCleanup to finish. g1h->increment_total_collections(); -#ifndef PRODUCT if (VerifyDuringGC) { - G1CollectedHeap::heap()->prepare_for_verify(); - G1CollectedHeap::heap()->verify(true,false); + g1h->prepare_for_verify(); + g1h->verify(/* allow_dirty */ true, + /* silent */ false, + /* use_prev_marking */ true); } -#endif } void ConcurrentMark::completeCleanup() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 1ceddfd81e6..1c7a5442bfb 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -2136,17 +2136,22 @@ public: }; class VerifyObjsInRegionClosure: public ObjectClosure { +private: G1CollectedHeap* _g1h; size_t _live_bytes; HeapRegion *_hr; + bool _use_prev_marking; public: - VerifyObjsInRegionClosure(HeapRegion *hr) : _live_bytes(0), _hr(hr) { + // use_prev_marking == true -> use "prev" marking information, + // use_prev_marking == false -> use "next" marking information + VerifyObjsInRegionClosure(HeapRegion *hr, bool use_prev_marking) + : _live_bytes(0), _hr(hr), _use_prev_marking(use_prev_marking) { _g1h = G1CollectedHeap::heap(); } void do_object(oop o) { VerifyLivenessOopClosure isLive(_g1h); assert(o != NULL, "Huh?"); - if (!_g1h->is_obj_dead(o)) { + if (!_g1h->is_obj_dead_cond(o, _use_prev_marking)) { o->oop_iterate(&isLive); if (!_hr->obj_allocated_since_prev_marking(o)) _live_bytes += (o->size() * HeapWordSize); @@ -2185,17 +2190,22 @@ public: }; class VerifyRegionClosure: public HeapRegionClosure { -public: +private: bool _allow_dirty; bool _par; - VerifyRegionClosure(bool allow_dirty, bool par = false) - : _allow_dirty(allow_dirty), _par(par) {} + bool _use_prev_marking; +public: + // use_prev_marking == true -> use "prev" marking information, + // use_prev_marking == false -> use "next" marking information + VerifyRegionClosure(bool allow_dirty, bool par, bool use_prev_marking) + : _allow_dirty(allow_dirty), _par(par), + _use_prev_marking(use_prev_marking) {} bool doHeapRegion(HeapRegion* r) { guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue, "Should be unclaimed at verify points."); if (!r->continuesHumongous()) { - VerifyObjsInRegionClosure not_dead_yet_cl(r); - r->verify(_allow_dirty); + VerifyObjsInRegionClosure not_dead_yet_cl(r, _use_prev_marking); + r->verify(_allow_dirty, _use_prev_marking); r->object_iterate(¬_dead_yet_cl); guarantee(r->max_live_bytes() >= not_dead_yet_cl.live_bytes(), "More live objects than counted in last complete marking."); @@ -2208,10 +2218,13 @@ class VerifyRootsClosure: public OopsInGenClosure { private: G1CollectedHeap* _g1h; bool _failures; - + bool _use_prev_marking; public: - VerifyRootsClosure() : - _g1h(G1CollectedHeap::heap()), _failures(false) { } + // use_prev_marking == true -> use "prev" marking information, + // use_prev_marking == false -> use "next" marking information + VerifyRootsClosure(bool use_prev_marking) : + _g1h(G1CollectedHeap::heap()), _failures(false), + _use_prev_marking(use_prev_marking) { } bool failures() { return _failures; } @@ -2222,7 +2235,7 @@ public: void do_oop(oop* p) { oop obj = *p; if (obj != NULL) { - if (_g1h->is_obj_dead(obj)) { + if (_g1h->is_obj_dead_cond(obj, _use_prev_marking)) { gclog_or_tty->print_cr("Root location "PTR_FORMAT" " "points to dead obj "PTR_FORMAT, p, (void*) obj); obj->print_on(gclog_or_tty); @@ -2238,24 +2251,35 @@ class G1ParVerifyTask: public AbstractGangTask { private: G1CollectedHeap* _g1h; bool _allow_dirty; + bool _use_prev_marking; public: - G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty) : + // use_prev_marking == true -> use "prev" marking information, + // use_prev_marking == false -> use "next" marking information + G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty, + bool use_prev_marking) : AbstractGangTask("Parallel verify task"), - _g1h(g1h), _allow_dirty(allow_dirty) { } + _g1h(g1h), _allow_dirty(allow_dirty), + _use_prev_marking(use_prev_marking) { } void work(int worker_i) { HandleMark hm; - VerifyRegionClosure blk(_allow_dirty, true); + VerifyRegionClosure blk(_allow_dirty, true, _use_prev_marking); _g1h->heap_region_par_iterate_chunked(&blk, worker_i, HeapRegion::ParVerifyClaimValue); } }; void G1CollectedHeap::verify(bool allow_dirty, bool silent) { + verify(allow_dirty, silent, /* use_prev_marking */ true); +} + +void G1CollectedHeap::verify(bool allow_dirty, + bool silent, + bool use_prev_marking) { if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { if (!silent) { gclog_or_tty->print("roots "); } - VerifyRootsClosure rootsCl; + VerifyRootsClosure rootsCl(use_prev_marking); process_strong_roots(false, SharedHeap::SO_AllClasses, &rootsCl, @@ -2266,7 +2290,7 @@ void G1CollectedHeap::verify(bool allow_dirty, bool silent) { assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity check"); - G1ParVerifyTask task(this, allow_dirty); + G1ParVerifyTask task(this, allow_dirty, use_prev_marking); int n_workers = workers()->total_workers(); set_par_threads(n_workers); workers()->run_task(&task); @@ -2280,7 +2304,7 @@ void G1CollectedHeap::verify(bool allow_dirty, bool silent) { assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity check"); } else { - VerifyRegionClosure blk(allow_dirty); + VerifyRegionClosure blk(allow_dirty, false, use_prev_marking); _hrs->iterate(&blk); } if (!silent) gclog_or_tty->print("remset "); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 1508e4e7346..bc68d7f7804 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1049,6 +1049,17 @@ public: virtual void prepare_for_verify(); // Perform verification. + + // use_prev_marking == true -> use "prev" marking information, + // use_prev_marking == false -> use "next" marking information + // NOTE: Only the "prev" marking information is guaranteed to be + // consistent most of the time, so most calls to this should use + // use_prev_marking == true. Currently, there is only one case where + // this is called with use_prev_marking == false, which is to verify + // the "next" marking information at the end of remark. + void verify(bool allow_dirty, bool silent, bool use_prev_marking); + + // Override; it uses the "prev" marking information virtual void verify(bool allow_dirty, bool silent); virtual void print() const; virtual void print_on(outputStream* st) const; @@ -1125,6 +1136,18 @@ public: bool isMarkedPrev(oop obj) const; bool isMarkedNext(oop obj) const; + // use_prev_marking == true -> use "prev" marking information, + // use_prev_marking == false -> use "next" marking information + bool is_obj_dead_cond(const oop obj, + const HeapRegion* hr, + const bool use_prev_marking) const { + if (use_prev_marking) { + return is_obj_dead(obj, hr); + } else { + return is_obj_ill(obj, hr); + } + } + // Determine if an object is dead, given the object and also // the region to which the object belongs. An object is dead // iff a) it was not allocated since the last mark and b) it @@ -1162,8 +1185,19 @@ public: // Added if it is in permanent gen it isn't dead. // Added if it is NULL it isn't dead. - bool is_obj_dead(oop obj) { - HeapRegion* hr = heap_region_containing(obj); + // use_prev_marking == true -> use "prev" marking information, + // use_prev_marking == false -> use "next" marking information + bool is_obj_dead_cond(const oop obj, + const bool use_prev_marking) { + if (use_prev_marking) { + return is_obj_dead(obj); + } else { + return is_obj_ill(obj); + } + } + + bool is_obj_dead(const oop obj) { + const HeapRegion* hr = heap_region_containing(obj); if (hr == NULL) { if (Universe::heap()->is_in_permanent(obj)) return false; @@ -1173,8 +1207,8 @@ public: else return is_obj_dead(obj, hr); } - bool is_obj_ill(oop obj) { - HeapRegion* hr = heap_region_containing(obj); + bool is_obj_ill(const oop obj) { + const HeapRegion* hr = heap_region_containing(obj); if (hr == NULL) { if (Universe::heap()->is_in_permanent(obj)) return false; diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index d1cf6725696..b844b2e70be 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -40,15 +40,19 @@ FilterOutOfRegionClosure::FilterOutOfRegionClosure(HeapRegion* r, {} class VerifyLiveClosure: public OopClosure { +private: G1CollectedHeap* _g1h; CardTableModRefBS* _bs; oop _containing_obj; bool _failures; int _n_failures; + bool _use_prev_marking; public: - VerifyLiveClosure(G1CollectedHeap* g1h) : + // use_prev_marking == true -> use "prev" marking information, + // use_prev_marking == false -> use "next" marking information + VerifyLiveClosure(G1CollectedHeap* g1h, bool use_prev_marking) : _g1h(g1h), _bs(NULL), _containing_obj(NULL), - _failures(false), _n_failures(0) + _failures(false), _n_failures(0), _use_prev_marking(use_prev_marking) { BarrierSet* bs = _g1h->barrier_set(); if (bs->is_a(BarrierSet::CardTableModRef)) @@ -68,11 +72,13 @@ public: void do_oop(oop* p) { assert(_containing_obj != NULL, "Precondition"); - assert(!_g1h->is_obj_dead(_containing_obj), "Precondition"); + assert(!_g1h->is_obj_dead_cond(_containing_obj, _use_prev_marking), + "Precondition"); oop obj = *p; if (obj != NULL) { bool failed = false; - if (!_g1h->is_in_closed_subset(obj) || _g1h->is_obj_dead(obj)) { + if (!_g1h->is_in_closed_subset(obj) || + _g1h->is_obj_dead_cond(obj, _use_prev_marking)) { if (!_failures) { gclog_or_tty->print_cr(""); gclog_or_tty->print_cr("----------"); @@ -647,19 +653,23 @@ void HeapRegion::print_on(outputStream* st) const { G1OffsetTableContigSpace::print_on(st); } +void HeapRegion::verify(bool allow_dirty) const { + verify(allow_dirty, /* use_prev_marking */ true); +} + #define OBJ_SAMPLE_INTERVAL 0 #define BLOCK_SAMPLE_INTERVAL 100 // This really ought to be commoned up into OffsetTableContigSpace somehow. // We would need a mechanism to make that code skip dead objects. -void HeapRegion::verify(bool allow_dirty) const { +void HeapRegion::verify(bool allow_dirty, bool use_prev_marking) const { G1CollectedHeap* g1 = G1CollectedHeap::heap(); HeapWord* p = bottom(); HeapWord* prev_p = NULL; int objs = 0; int blocks = 0; - VerifyLiveClosure vl_cl(g1); + VerifyLiveClosure vl_cl(g1, use_prev_marking); while (p < top()) { size_t size = oop(p)->size(); if (blocks == BLOCK_SAMPLE_INTERVAL) { @@ -671,7 +681,7 @@ void HeapRegion::verify(bool allow_dirty) const { } if (objs == OBJ_SAMPLE_INTERVAL) { oop obj = oop(p); - if (!g1->is_obj_dead(obj, this)) { + if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) { obj->verify(); vl_cl.set_containing_obj(obj); obj->oop_iterate(&vl_cl); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index b2738a42581..663ed5c44bf 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -782,7 +782,16 @@ class HeapRegion: public G1OffsetTableContigSpace { void print() const; void print_on(outputStream* st) const; - // Override + // use_prev_marking == true -> use "prev" marking information, + // use_prev_marking == false -> use "next" marking information + // NOTE: Only the "prev" marking information is guaranteed to be + // consistent most of the time, so most calls to this should use + // use_prev_marking == true. Currently, there is only one case where + // this is called with use_prev_marking == false, which is to verify + // the "next" marking information at the end of remark. + void verify(bool allow_dirty, bool use_prev_marking) const; + + // Override; it uses the "prev" marking information virtual void verify(bool allow_dirty) const; #ifdef DEBUG From 5ecb6c24be627181537f1bc65dcc34af24eddc5e Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Mon, 15 Jun 2009 14:49:22 +0400 Subject: [PATCH 11/23] 6829549: JVM crash on certain images Reviewed-by: igor, prr --- .../sun/imageio/plugins/jpeg/JPEGImageReader.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java index 2459ff54418..e9a4b8ac5a9 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -41,6 +41,7 @@ import java.awt.Rectangle; import java.awt.color.ColorSpace; import java.awt.color.ICC_Profile; import java.awt.color.ICC_ColorSpace; +import java.awt.color.CMMException; import java.awt.image.BufferedImage; import java.awt.image.Raster; import java.awt.image.WritableRaster; @@ -629,6 +630,17 @@ public class JPEGImageReader extends ImageReader { !java.util.Arrays.equals(oldData, newData)) { iccCS = new ICC_ColorSpace(newProfile); + // verify new color space + try { + float[] colors = iccCS.fromRGB(new float[] {1f, 0f, 0f}); + } catch (CMMException e) { + /* + * Embedded profile seems to be corrupted. + * Ignore this profile. + */ + iccCS = null; + warningOccurred(WARNING_IGNORE_INVALID_ICC); + } } } From 0574960761f479291b9e597706be7599e1d5fb3d Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Mon, 15 Jun 2009 17:19:33 +0400 Subject: [PATCH 12/23] 6684104: Applets fails to launch using ImageIO if .java.policy with File permissions present on the system Reviewed-by: igor, prr --- .../share/classes/javax/imageio/ImageIO.java | 14 +- .../CachePermissionsTest.java | 120 ++++++++++++++++++ .../imageio/CachePremissionsTest/rw.policy | 5 + .../imageio/CachePremissionsTest/rwd.policy | 5 + .../imageio/CachePremissionsTest/w.policy | 5 + 5 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 jdk/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java create mode 100644 jdk/test/javax/imageio/CachePremissionsTest/rw.policy create mode 100644 jdk/test/javax/imageio/CachePremissionsTest/rwd.policy create mode 100644 jdk/test/javax/imageio/CachePremissionsTest/w.policy diff --git a/jdk/src/share/classes/javax/imageio/ImageIO.java b/jdk/src/share/classes/javax/imageio/ImageIO.java index 77f2a6b65e8..51b5eaeb804 100644 --- a/jdk/src/share/classes/javax/imageio/ImageIO.java +++ b/jdk/src/share/classes/javax/imageio/ImageIO.java @@ -28,6 +28,7 @@ package javax.imageio; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.File; +import java.io.FilePermission; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; @@ -195,13 +196,22 @@ public final class ImageIO { } else { cachepath = getTempDir(); - if (cachepath == null) { + if (cachepath == null || cachepath.isEmpty()) { getCacheInfo().setHasPermission(Boolean.FALSE); return false; } } - security.checkWrite(cachepath); + // we have to check whether we can read, write, + // and delete cache files. + // So, compose cache file path and check it. + String filepath = cachepath; + if (!filepath.endsWith(File.separator)) { + filepath += File.separator; + } + filepath += "*"; + + security.checkPermission(new FilePermission(filepath, "read, write, delete")); } } catch (SecurityException e) { getCacheInfo().setHasPermission(Boolean.FALSE); diff --git a/jdk/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java b/jdk/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java new file mode 100644 index 00000000000..4aa3a306493 --- /dev/null +++ b/jdk/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java @@ -0,0 +1,120 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6684104 + * @summary Test verifies that ImageIO checks all permissions required for + * the file cache usage: + * + * no policy file: No security restrictions. + * Expected result: ImageIO creates file-cached stream. + * + * w.policy: the case when we have read and write permissions + * for java.io.temp directory but have only write permission + * for a temp file. + * Expected result: ImageIO create a memory-cached stream + * image output stream. + * + * rw.policy: the case when we have read and write permissions + * for java.io.temp directory but have only read and write + * permission for a temp cache file. + * Expected result: ImageIO creates a memory-cached stream + * because temporary cache file can not be deleted. + * + * rwd.policy: the case when we have read and write permissions + * for java.io.temp directory and have all required permissions + * (read, write, and delete) for a temporary cache file. + * Expected result: ImageIO creates file-cached stream. + * + * -Djava.security.debug=access can be used to verify file permissions. + * + * @run main CachePermissionsTest true + * @run main/othervm/policy=w.policy CachePermissionsTest false + * @run main/othervm/policy=rw.policy CachePermissionsTest false + * @run main/othervm/policy=rwd.policy CachePermissionsTest true + */ + +import java.io.File; +import java.io.IOException; +import java.io.ByteArrayOutputStream; +import javax.imageio.stream.ImageOutputStream; + +import javax.imageio.ImageIO; + + +public class CachePermissionsTest { + public static void main(String[] args) { + boolean isFileCacheExpected = + Boolean.valueOf(args[0]).booleanValue(); + System.out.println("Is file cache expected: " + isFileCacheExpected); + + ImageIO.setUseCache(true); + + System.out.println("java.io.tmpdir is " + System.getProperty("java.io.tmpdir")); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + try { + ImageOutputStream ios = ImageIO.createImageOutputStream(baos); + + boolean isFileCache = ios.isCachedFile(); + System.out.println("Is file cache used: " + isFileCache); + + if (isFileCache !=isFileCacheExpected) { + System.out.println("WARNING: file chace usage is not as expected!"); + } + + System.out.println("Verify data writing..."); + for (int i = 0; i < 8192; i++) { + ios.writeInt(i); + } + + System.out.println("Verify data reading..."); + ios.seek(0L); + + for (int i = 0; i < 8192; i++) { + int j = ios.readInt(); + if (i != j) { + throw new RuntimeException("Wrong data in the stream " + j + " instead of " + i); + } + } + + System.out.println("Verify stream closing..."); + ios.close(); + } catch (IOException e) { + /* + * Something went wrong? + */ + throw new RuntimeException("Test FAILED.", e); + } catch (SecurityException e) { + /* + * We do not expect security execptions here: + * we there are any security restrition, ImageIO + * should swith to memory-cached streams, instead + * of using file cache. + */ + throw new RuntimeException("Test FAILED.", e); + } + } +} diff --git a/jdk/test/javax/imageio/CachePremissionsTest/rw.policy b/jdk/test/javax/imageio/CachePremissionsTest/rw.policy new file mode 100644 index 00000000000..003c85b5784 --- /dev/null +++ b/jdk/test/javax/imageio/CachePremissionsTest/rw.policy @@ -0,0 +1,5 @@ +grant { + permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "java.io.tmpdir", "read"; + permission java.io.FilePermission "${java.io.tmpdir}${/}*", "read, write"; +}; diff --git a/jdk/test/javax/imageio/CachePremissionsTest/rwd.policy b/jdk/test/javax/imageio/CachePremissionsTest/rwd.policy new file mode 100644 index 00000000000..f4d1f90a36e --- /dev/null +++ b/jdk/test/javax/imageio/CachePremissionsTest/rwd.policy @@ -0,0 +1,5 @@ +grant { + permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "java.io.tmpdir", "read"; + permission java.io.FilePermission "${java.io.tmpdir}${/}*", "read, write, delete"; +}; diff --git a/jdk/test/javax/imageio/CachePremissionsTest/w.policy b/jdk/test/javax/imageio/CachePremissionsTest/w.policy new file mode 100644 index 00000000000..ff354e9616b --- /dev/null +++ b/jdk/test/javax/imageio/CachePremissionsTest/w.policy @@ -0,0 +1,5 @@ +grant { + permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "java.io.tmpdir", "read"; + permission java.io.FilePermission "${java.io.tmpdir}${/}*", "write"; +}; From cb5399d38041d316f661518fabca9e8b936d60a0 Mon Sep 17 00:00:00 2001 From: Jennifer Godinez Date: Mon, 22 Jun 2009 09:47:50 -0700 Subject: [PATCH 13/23] 6850398: Allow GraphicsEnvironment to be loaded by system classloader (edit) Reviewed-by: campbell, prr --- jdk/src/share/classes/java/awt/GraphicsEnvironment.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/java/awt/GraphicsEnvironment.java b/jdk/src/share/classes/java/awt/GraphicsEnvironment.java index cf1852e2fc0..d77b2f22b8b 100644 --- a/jdk/src/share/classes/java/awt/GraphicsEnvironment.java +++ b/jdk/src/share/classes/java/awt/GraphicsEnvironment.java @@ -79,8 +79,9 @@ public abstract class GraphicsEnvironment { try { // long t0 = System.currentTimeMillis(); - localEnv = - (GraphicsEnvironment) Class.forName(nm).newInstance(); + ClassLoader cl = ClassLoader.getSystemClassLoader(); + Class geCls = Class.forName(nm, true, cl); + localEnv = (GraphicsEnvironment)geCls.newInstance(); // long t1 = System.currentTimeMillis(); // System.out.println("GE creation took " + (t1-t0)+ "ms."); if (isHeadless()) { From 886c516b5b3cc2f2d7939956fc87b3fa16305583 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 22 Jun 2009 14:10:09 -0700 Subject: [PATCH 14/23] 6853617: race condition in java.awt.Font.getAttributes() (private method) Reviewed-by: igor, jgodinez --- jdk/src/share/classes/java/awt/Font.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/classes/java/awt/Font.java b/jdk/src/share/classes/java/awt/Font.java index f73e0e90c15..97773143415 100644 --- a/jdk/src/share/classes/java/awt/Font.java +++ b/jdk/src/share/classes/java/awt/Font.java @@ -445,18 +445,19 @@ public class Font implements java.io.Serializable */ private AttributeValues getAttributeValues() { if (values == null) { - values = new AttributeValues(); - values.setFamily(name); - values.setSize(pointSize); // expects the float value. + AttributeValues valuesTmp = new AttributeValues(); + valuesTmp.setFamily(name); + valuesTmp.setSize(pointSize); // expects the float value. if ((style & BOLD) != 0) { - values.setWeight(2); // WEIGHT_BOLD + valuesTmp.setWeight(2); // WEIGHT_BOLD } if ((style & ITALIC) != 0) { - values.setPosture(.2f); // POSTURE_OBLIQUE + valuesTmp.setPosture(.2f); // POSTURE_OBLIQUE } - values.defineAll(PRIMARY_MASK); // for streaming compatibility + valuesTmp.defineAll(PRIMARY_MASK); // for streaming compatibility + values = valuesTmp; } return values; From e798379e7fff8dae090041f39d363f11b252fe5e Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 25 Jun 2009 12:09:43 -0700 Subject: [PATCH 15/23] Added tag jdk7-b62 for changeset 5d65d3a7be83 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index f29e5783c6c..bacb8f8c516 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -36,3 +36,4 @@ ffd09e767dfa6d21466183a400f72cf62d53297f jdk7-b57 030142474602b4a067662fffc0c8e541de5a78df jdk7-b59 39565502682c7085369bd09e51640919dc741097 jdk7-b60 472c21584cfd7e9c0229ad6a100366a5c03d2976 jdk7-b61 +c7ed15ab92ce36a09d264a5e34025884b2d7607f jdk7-b62 From c8519d5bfacbb96b4933ba15b35f92d70b1e55ce Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 25 Jun 2009 12:09:45 -0700 Subject: [PATCH 16/23] Added tag jdk7-b62 for changeset 71847d16bc71 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index d29fd94ac73..076e5ff8160 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -36,3 +36,4 @@ bec82237d694f9802b820fa11bbb4f7fa9bf8e77 jdk7-b52 7e6b2b55c00cc523b468272353ada3979adbbf16 jdk7-b59 f1e1cccbd13aa96d2d8bd872782ff764010bc22c jdk7-b60 e906b16a12a9a63b615898afa5d9673cbd1c5ab8 jdk7-b61 +65b66117dbd70a493e9644aeb4033cf95a4e3c99 jdk7-b62 From 5cd0d5d07cfb09a561d9ffecc39dfe436ce8b835 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 25 Jun 2009 12:09:48 -0700 Subject: [PATCH 17/23] Added tag jdk7-b62 for changeset c9577b36ceac --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index d8265014a47..b0d86eec8af 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -36,3 +36,4 @@ f4cbf78110c726919f46b59a3b054c54c7e889b4 jdk7-b57 c55be0c7bd32c016c52218eb4c8b5da8a75450b5 jdk7-b59 a77eddcd510c3972717c025cfcef9a60bfa4ecac jdk7-b60 27b728fd1281ab62e9d7e4424f8bbb6ca438d803 jdk7-b61 +a88386380bdaaa5ab4ffbedf22c57bac5dbec034 jdk7-b62 From fd510076920562cb0b4c17ac353d500a046782d4 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 25 Jun 2009 12:09:53 -0700 Subject: [PATCH 18/23] Added tag jdk7-b62 for changeset fe183c0b19a9 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 32cf0403d8b..3a9475b40a6 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -36,3 +36,4 @@ e4851e9f7be26fc52a628be06ffa8aaea0919bd7 jdk7-b57 75113d7ce083048e7576b9d0d60a4e80db6b181f jdk7-b59 259aef5045a155eb6a2f8dd0e2429c6dbe0f652f jdk7-b60 f1ac756616eaaad795f77f7f5e7f7c7bfdc9c1de jdk7-b61 +a97dd57a62604c35c79bc2fa77a612ed547f6135 jdk7-b62 From 6b2bc4b69ee1d35767c53cead54f797e2c528ad3 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 25 Jun 2009 12:09:54 -0700 Subject: [PATCH 19/23] Added tag jdk7-b62 for changeset 90c518858444 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index be249530760..d4c9c44c6bf 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -36,3 +36,4 @@ e0eebd978b830c09e7862cff3f77a914c15651c9 jdk7-b55 f64566bf4c2bc92e65ab2b9fab51b119f0d493d1 jdk7-b59 3b054db3e277ca224fe6576c59ed6f4ab5ed0bb5 jdk7-b60 aeabf802f2a1ca72b87d7397c5ece58058e000a9 jdk7-b61 +75c801c13ea1ddebc58b1a8c8da9318d72750e62 jdk7-b62 From a37f5785ad909c461fbc510027b7744c0de6970b Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 25 Jun 2009 12:10:11 -0700 Subject: [PATCH 20/23] Added tag jdk7-b62 for changeset aca415f62ac6 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index a7151c2e4df..3f17fa3d3b5 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -36,3 +36,4 @@ dbdeb4a7581b2a8699644b91cae6793cb01953f7 jdk7-b53 88bcb6772159602317f2e184a69010737db72270 jdk7-b59 5cdce469ea2ad90d308c9abe420fd0643c0a6b9e jdk7-b60 522520757dd34321b27a7145ecbd24ac4fb64f34 jdk7-b61 +6855e5aa3348f185fe5b443ee43a1b00ec5d390e jdk7-b62 From 9fa3fbda4ba3a6574c7abe02cf286a366d5042d8 Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Tue, 30 Jun 2009 10:40:31 -0700 Subject: [PATCH 21/23] 6856257: Bump the HS16 build number to 05 Update the HS16 build number to 05 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 7e2008714ec..6635ba6afd7 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009 HS_MAJOR_VER=16 HS_MINOR_VER=0 -HS_BUILD_NUMBER=04 +HS_BUILD_NUMBER=05 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 From 5032399d573cc73b658e0178878ff64ac3d26ce1 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 16:55:03 +0200 Subject: [PATCH 22/23] Added tag jdk7-b62 for changeset 6107cbff3130 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 3b65a80e8b7..20ada94d378 100644 --- a/.hgtags +++ b/.hgtags @@ -36,3 +36,4 @@ d60a9ce3c3eabf28f5d50ae839d18be04a551bc2 jdk7-b58 c33e7d38c9210741dbc285507403a4b20bd802a0 jdk7-b59 5a10e4d0b14d7beac53a7b2213ae6864afe1fd3e jdk7-b60 dbb955b1ee59b876dd1f133952b557b48b1d7732 jdk7-b61 +6107cbff3130c747d243c25a7874cd59db5744a8 jdk7-b62 From 618ccf3eb4fa34f733026839dd3ccda6b5b2d388 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 2 Jul 2009 11:11:03 -0700 Subject: [PATCH 23/23] Added tag jdk7-b63 for changeset c8270bf40b76 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index f1ddffab9ae..78053b178ae 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -37,3 +37,4 @@ d5a1223e961891564de25c39fba6f2442d0fb045 jdk7-b57 0c3ef2d612a47667829eb17a192decef23f1c536 jdk7-b60 f72c0dc047b9b2e797beee68ae0b50decb1f020d jdk7-b61 12e11fab9a839a9666a996a8f9a02fd8fa03aab6 jdk7-b62 +2ed6ed6b5bfc7dd724925b90dbb31223df59c25d jdk7-b63